curb 0.9.10 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.markdown +33 -4
- data/Rakefile +8 -11
- data/ext/banned.h +32 -0
- data/ext/curb.c +150 -8
- data/ext/curb.h +11 -5
- data/ext/curb_easy.c +75 -26
- data/ext/curb_easy.h +3 -0
- data/ext/curb_multi.c +11 -11
- data/ext/curb_postfield.c +7 -7
- data/ext/extconf.rb +36 -0
- data/lib/curl/easy.rb +8 -7
- data/lib/curl/multi.rb +2 -2
- data/lib/curl.rb +11 -3
- data/tests/helper.rb +0 -1
- data/tests/tc_curl_easy.rb +9 -1
- data/tests/tc_curl_multi.rb +52 -11
- data/tests/tc_curl_postfield.rb +29 -29
- data/tests/tc_curl_protocols.rb +37 -0
- data/tests/timeout.rb +21 -5
- metadata +9 -7
data/ext/curb_easy.c
CHANGED
@@ -268,6 +268,8 @@ void curl_easy_free(ruby_curl_easy *rbce) {
|
|
268
268
|
static void ruby_curl_easy_zero(ruby_curl_easy *rbce) {
|
269
269
|
rbce->opts = rb_hash_new();
|
270
270
|
|
271
|
+
memset(rbce->err_buf, 0, sizeof(rbce->err_buf));
|
272
|
+
|
271
273
|
rbce->curl_headers = NULL;
|
272
274
|
rbce->curl_proxy_headers = NULL;
|
273
275
|
rbce->curl_ftp_commands = NULL;
|
@@ -327,9 +329,9 @@ static VALUE ruby_curl_easy_allocate(VALUE klass) {
|
|
327
329
|
|
328
330
|
/*
|
329
331
|
* call-seq:
|
330
|
-
* Curl::Easy.new =>
|
331
|
-
* Curl::Easy.new(url = nil) =>
|
332
|
-
* Curl::Easy.new(url = nil) { |self| ... } =>
|
332
|
+
* Curl::Easy.new => #<Curl::Easy...>
|
333
|
+
* Curl::Easy.new(url = nil) => #<Curl::Easy...>
|
334
|
+
* Curl::Easy.new(url = nil) { |self| ... } => #<Curl::Easy...>
|
333
335
|
*
|
334
336
|
* Initialize a new Curl::Easy instance, optionally supplying the URL.
|
335
337
|
* The block form allows further configuration to be supplied before
|
@@ -355,8 +357,9 @@ static VALUE ruby_curl_easy_initialize(int argc, VALUE *argv, VALUE self) {
|
|
355
357
|
|
356
358
|
ruby_curl_easy_zero(rbce);
|
357
359
|
|
358
|
-
|
360
|
+
curl_easy_setopt(rbce->curl, CURLOPT_ERRORBUFFER, &rbce->err_buf);
|
359
361
|
|
362
|
+
rb_easy_set("url", url);
|
360
363
|
|
361
364
|
/* set the pointer to the curl handle */
|
362
365
|
ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)self);
|
@@ -373,8 +376,8 @@ static VALUE ruby_curl_easy_initialize(int argc, VALUE *argv, VALUE self) {
|
|
373
376
|
|
374
377
|
/*
|
375
378
|
* call-seq:
|
376
|
-
* easy.clone =>
|
377
|
-
* easy.dup =>
|
379
|
+
* easy.clone => <easy clone>
|
380
|
+
* easy.dup => <easy clone>
|
378
381
|
*
|
379
382
|
* Clone this Curl::Easy instance, creating a new instance.
|
380
383
|
* This method duplicates the underlying CURL* handle.
|
@@ -392,6 +395,8 @@ static VALUE ruby_curl_easy_clone(VALUE self) {
|
|
392
395
|
newrbce->curl_ftp_commands = NULL;
|
393
396
|
newrbce->curl_resolve = NULL;
|
394
397
|
|
398
|
+
curl_easy_setopt(rbce->curl, CURLOPT_ERRORBUFFER, &rbce->err_buf);
|
399
|
+
|
395
400
|
return Data_Wrap_Struct(cCurlEasy, curl_easy_mark, curl_easy_free, newrbce);
|
396
401
|
}
|
397
402
|
|
@@ -461,7 +466,9 @@ static VALUE ruby_curl_easy_reset(VALUE self) {
|
|
461
466
|
curl_easy_reset(rbce->curl);
|
462
467
|
ruby_curl_easy_zero(rbce);
|
463
468
|
|
464
|
-
|
469
|
+
curl_easy_setopt(rbce->curl, CURLOPT_ERRORBUFFER, &rbce->err_buf);
|
470
|
+
|
471
|
+
/* reset clobbers the private setting, so reset it to self */
|
465
472
|
ecode = curl_easy_setopt(rbce->curl, CURLOPT_PRIVATE, (void*)self);
|
466
473
|
if (ecode != CURLE_OK) {
|
467
474
|
raise_curl_easy_error_exception(ecode);
|
@@ -950,7 +957,7 @@ static VALUE ruby_curl_easy_ftp_commands_set(VALUE self, VALUE ftp_commands) {
|
|
950
957
|
}
|
951
958
|
|
952
959
|
/*
|
953
|
-
* call-seq
|
960
|
+
* call-seq:
|
954
961
|
* easy.ftp_commands => array or nil
|
955
962
|
*/
|
956
963
|
static VALUE ruby_curl_easy_ftp_commands_get(VALUE self) {
|
@@ -969,7 +976,7 @@ static VALUE ruby_curl_easy_resolve_set(VALUE self, VALUE resolve) {
|
|
969
976
|
}
|
970
977
|
|
971
978
|
/*
|
972
|
-
* call-seq
|
979
|
+
* call-seq:
|
973
980
|
* easy.resolve => array or nil
|
974
981
|
*/
|
975
982
|
static VALUE ruby_curl_easy_resolve_get(VALUE self) {
|
@@ -1539,6 +1546,7 @@ static VALUE ruby_curl_easy_password_get(VALUE self, VALUE password) {
|
|
1539
1546
|
* Curl::CURL_SSLVERSION_TLSv1_0
|
1540
1547
|
* Curl::CURL_SSLVERSION_TLSv1_1
|
1541
1548
|
* Curl::CURL_SSLVERSION_TLSv1_2
|
1549
|
+
* Curl::CURL_SSLVERSION_TLSv1_3
|
1542
1550
|
*/
|
1543
1551
|
static VALUE ruby_curl_easy_ssl_version_set(VALUE self, VALUE ssl_version) {
|
1544
1552
|
CURB_IMMED_SETTER(ruby_curl_easy, ssl_version, -1);
|
@@ -1587,7 +1595,7 @@ static VALUE ruby_curl_easy_ftp_filemethod_set(VALUE self, VALUE ftp_filemethod)
|
|
1587
1595
|
}
|
1588
1596
|
|
1589
1597
|
/*
|
1590
|
-
* call-seq
|
1598
|
+
* call-seq:
|
1591
1599
|
* easy.ftp_filemethod => fixnum
|
1592
1600
|
*
|
1593
1601
|
* Get the configuration for how libcurl will reach files on the server.
|
@@ -1959,7 +1967,7 @@ static VALUE ruby_curl_easy_resolve_mode_set(VALUE self, VALUE resolve_mode) {
|
|
1959
1967
|
|
1960
1968
|
/*
|
1961
1969
|
* call-seq:
|
1962
|
-
* easy.on_body { |body_data| ... } =>
|
1970
|
+
* easy.on_body { |body_data| ... } => <old handler>
|
1963
1971
|
*
|
1964
1972
|
* Assign or remove the +on_body+ handler for this Curl::Easy instance.
|
1965
1973
|
* To remove a previously-supplied handler, call this method with no
|
@@ -1978,7 +1986,7 @@ static VALUE ruby_curl_easy_on_body_set(int argc, VALUE *argv, VALUE self) {
|
|
1978
1986
|
|
1979
1987
|
/*
|
1980
1988
|
* call-seq:
|
1981
|
-
* easy.on_success { |easy| ... } =>
|
1989
|
+
* easy.on_success { |easy| ... } => <old handler>
|
1982
1990
|
*
|
1983
1991
|
* Assign or remove the +on_success+ handler for this Curl::Easy instance.
|
1984
1992
|
* To remove a previously-supplied handler, call this method with no
|
@@ -1993,7 +2001,7 @@ static VALUE ruby_curl_easy_on_success_set(int argc, VALUE *argv, VALUE self) {
|
|
1993
2001
|
|
1994
2002
|
/*
|
1995
2003
|
* call-seq:
|
1996
|
-
* easy.on_failure {|easy,code| ... } =>
|
2004
|
+
* easy.on_failure {|easy,code| ... } => <old handler>
|
1997
2005
|
*
|
1998
2006
|
* Assign or remove the +on_failure+ handler for this Curl::Easy instance.
|
1999
2007
|
* To remove a previously-supplied handler, call this method with no
|
@@ -2008,7 +2016,7 @@ static VALUE ruby_curl_easy_on_failure_set(int argc, VALUE *argv, VALUE self) {
|
|
2008
2016
|
|
2009
2017
|
/*
|
2010
2018
|
* call-seq:
|
2011
|
-
* easy.on_missing {|easy,code| ... } =>
|
2019
|
+
* easy.on_missing {|easy,code| ... } => <old handler;>
|
2012
2020
|
*
|
2013
2021
|
* Assign or remove the on_missing handler for this Curl::Easy instance.
|
2014
2022
|
* To remove a previously-supplied handler, call this method with no attached
|
@@ -2023,7 +2031,7 @@ static VALUE ruby_curl_easy_on_missing_set(int argc, VALUE *argv, VALUE self) {
|
|
2023
2031
|
|
2024
2032
|
/*
|
2025
2033
|
* call-seq:
|
2026
|
-
* easy.on_redirect {|easy,code| ... } =>
|
2034
|
+
* easy.on_redirect {|easy,code| ... } => <old handler;>
|
2027
2035
|
*
|
2028
2036
|
* Assign or remove the on_redirect handler for this Curl::Easy instance.
|
2029
2037
|
* To remove a previously-supplied handler, call this method with no attached
|
@@ -2038,7 +2046,7 @@ static VALUE ruby_curl_easy_on_redirect_set(int argc, VALUE *argv, VALUE self) {
|
|
2038
2046
|
|
2039
2047
|
/*
|
2040
2048
|
* call-seq:
|
2041
|
-
* easy.on_complete {|easy| ... } =>
|
2049
|
+
* easy.on_complete {|easy| ... } => <old handler>
|
2042
2050
|
*
|
2043
2051
|
* Assign or remove the +on_complete+ handler for this Curl::Easy instance.
|
2044
2052
|
* To remove a previously-supplied handler, call this method with no
|
@@ -2052,7 +2060,7 @@ static VALUE ruby_curl_easy_on_complete_set(int argc, VALUE *argv, VALUE self) {
|
|
2052
2060
|
|
2053
2061
|
/*
|
2054
2062
|
* call-seq:
|
2055
|
-
* easy.on_header { |header_data| ... } =>
|
2063
|
+
* easy.on_header { |header_data| ... } => <old handler>
|
2056
2064
|
*
|
2057
2065
|
* Assign or remove the +on_header+ handler for this Curl::Easy instance.
|
2058
2066
|
* To remove a previously-supplied handler, call this method with no
|
@@ -2068,7 +2076,7 @@ static VALUE ruby_curl_easy_on_header_set(int argc, VALUE *argv, VALUE self) {
|
|
2068
2076
|
|
2069
2077
|
/*
|
2070
2078
|
* call-seq:
|
2071
|
-
* easy.on_progress { |dl_total, dl_now, ul_total, ul_now| ... } =>
|
2079
|
+
* easy.on_progress { |dl_total, dl_now, ul_total, ul_now| ... } => <old handler>
|
2072
2080
|
*
|
2073
2081
|
* Assign or remove the +on_progress+ handler for this Curl::Easy instance.
|
2074
2082
|
* To remove a previously-supplied handler, call this method with no
|
@@ -2089,7 +2097,7 @@ static VALUE ruby_curl_easy_on_progress_set(int argc, VALUE *argv, VALUE self) {
|
|
2089
2097
|
|
2090
2098
|
/*
|
2091
2099
|
* call-seq:
|
2092
|
-
* easy.on_debug { |type, data| ... } =>
|
2100
|
+
* easy.on_debug { |type, data| ... } => <old handler>
|
2093
2101
|
*
|
2094
2102
|
* Assign or remove the +on_debug+ handler for this Curl::Easy instance.
|
2095
2103
|
* To remove a previously-supplied handler, call this method with no
|
@@ -2128,11 +2136,14 @@ static VALUE cb_each_http_header(VALUE header, VALUE wrap) {
|
|
2128
2136
|
|
2129
2137
|
name = rb_obj_as_string(rb_ary_entry(header, 0));
|
2130
2138
|
value = rb_obj_as_string(rb_ary_entry(header, 1));
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2134
|
-
|
2135
|
-
|
2139
|
+
if (rb_str_strlen(value) == 0) { // removing the header e.g. Accept: with nothing trailing should remove it see: https://curl.se/libcurl/c/CURLOPT_HTTPHEADER.html
|
2140
|
+
header_str = rb_str_plus(name, rb_str_new2(":"));
|
2141
|
+
} else {
|
2142
|
+
// This is a bit inefficient, but we don't want to be modifying
|
2143
|
+
// the actual values in the original hash.
|
2144
|
+
header_str = rb_str_plus(name, rb_str_new2(": "));
|
2145
|
+
header_str = rb_str_plus(header_str, value);
|
2146
|
+
}
|
2136
2147
|
} else {
|
2137
2148
|
header_str = rb_obj_as_string(header);
|
2138
2149
|
}
|
@@ -2607,6 +2618,8 @@ static VALUE ruby_curl_easy_perform_verb_str(VALUE self, const char *verb) {
|
|
2607
2618
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2608
2619
|
curl = rbce->curl;
|
2609
2620
|
|
2621
|
+
memset(rbce->err_buf, 0, sizeof(rbce->err_buf));
|
2622
|
+
|
2610
2623
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, verb);
|
2611
2624
|
|
2612
2625
|
retval = rb_funcall(self, rb_intern("perform"), 0);
|
@@ -2672,6 +2685,8 @@ static VALUE ruby_curl_easy_perform_post(int argc, VALUE *argv, VALUE self) {
|
|
2672
2685
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2673
2686
|
curl = rbce->curl;
|
2674
2687
|
|
2688
|
+
memset(rbce->err_buf, 0, sizeof(rbce->err_buf));
|
2689
|
+
|
2675
2690
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
|
2676
2691
|
|
2677
2692
|
if (rbce->multipart_form_post) {
|
@@ -2743,6 +2758,8 @@ static VALUE ruby_curl_easy_perform_put(VALUE self, VALUE data) {
|
|
2743
2758
|
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
2744
2759
|
curl = rbce->curl;
|
2745
2760
|
|
2761
|
+
memset(rbce->err_buf, 0, sizeof(rbce->err_buf));
|
2762
|
+
|
2746
2763
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, NULL);
|
2747
2764
|
ruby_curl_easy_put_data_set(self, data);
|
2748
2765
|
|
@@ -2761,6 +2778,10 @@ static VALUE ruby_curl_easy_perform_put(VALUE self, VALUE data) {
|
|
2761
2778
|
* your own body handler, this string will be empty.
|
2762
2779
|
*/
|
2763
2780
|
static VALUE ruby_curl_easy_body_str_get(VALUE self) {
|
2781
|
+
/*
|
2782
|
+
TODO: can we force_encoding on the return here if we see charset=utf-8 in the content-type header?
|
2783
|
+
Content-Type: application/json; charset=utf-8
|
2784
|
+
*/
|
2764
2785
|
CURB_OBJECT_HGETTER(ruby_curl_easy, body_data);
|
2765
2786
|
}
|
2766
2787
|
|
@@ -2955,7 +2976,7 @@ static VALUE ruby_curl_easy_connect_time_get(VALUE self) {
|
|
2955
2976
|
* Retrieve the time, in seconds, it took from the start until the SSL/SSH
|
2956
2977
|
* connect/handshake to the remote host was completed. This time is most often
|
2957
2978
|
* very near to the pre transfer time, except for cases such as HTTP
|
2958
|
-
*
|
2979
|
+
* pipelining where the pretransfer time can be delayed due to waits in line
|
2959
2980
|
* for the pipeline and more.
|
2960
2981
|
*/
|
2961
2982
|
#if defined(HAVE_CURLINFO_APPCONNECT_TIME)
|
@@ -3448,6 +3469,21 @@ static VALUE ruby_curl_easy_last_result(VALUE self) {
|
|
3448
3469
|
return LONG2NUM(rbce->last_result);
|
3449
3470
|
}
|
3450
3471
|
|
3472
|
+
/*
|
3473
|
+
* call-seq:
|
3474
|
+
* easy.last_error => "Error details" or nil
|
3475
|
+
*/
|
3476
|
+
static VALUE ruby_curl_easy_last_error(VALUE self) {
|
3477
|
+
ruby_curl_easy *rbce;
|
3478
|
+
Data_Get_Struct(self, ruby_curl_easy, rbce);
|
3479
|
+
|
3480
|
+
if (rbce->err_buf[0]) { // curl returns NULL or empty string if none
|
3481
|
+
return rb_str_new2(rbce->err_buf);
|
3482
|
+
} else {
|
3483
|
+
return Qnil;
|
3484
|
+
}
|
3485
|
+
}
|
3486
|
+
|
3451
3487
|
/*
|
3452
3488
|
* call-seq:
|
3453
3489
|
* easy.setopt Fixnum, value => value
|
@@ -3546,6 +3582,9 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
|
3546
3582
|
case CURLOPT_TCP_NODELAY: {
|
3547
3583
|
curl_easy_setopt(rbce->curl, CURLOPT_TCP_NODELAY, NUM2LONG(val));
|
3548
3584
|
} break;
|
3585
|
+
case CURLOPT_RANGE: {
|
3586
|
+
curl_easy_setopt(rbce->curl, CURLOPT_RANGE, StringValueCStr(val));
|
3587
|
+
} break;
|
3549
3588
|
case CURLOPT_RESUME_FROM: {
|
3550
3589
|
curl_easy_setopt(rbce->curl, CURLOPT_RESUME_FROM, NUM2LONG(val));
|
3551
3590
|
} break;
|
@@ -3596,7 +3635,7 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
|
3596
3635
|
#endif
|
3597
3636
|
#if HAVE_CURLOPT_HAPROXYPROTOCOL
|
3598
3637
|
case CURLOPT_HAPROXYPROTOCOL:
|
3599
|
-
curl_easy_setopt(rbce->curl,
|
3638
|
+
curl_easy_setopt(rbce->curl, CURLOPT_HAPROXYPROTOCOL, NUM2LONG(val));
|
3600
3639
|
break;
|
3601
3640
|
#endif
|
3602
3641
|
case CURLOPT_STDERR:
|
@@ -3606,6 +3645,15 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
|
|
3606
3645
|
GetOpenFile(val, open_f_ptr);
|
3607
3646
|
curl_easy_setopt(rbce->curl, CURLOPT_STDERR, rb_io_stdio_file(open_f_ptr));
|
3608
3647
|
break;
|
3648
|
+
case CURLOPT_PROTOCOLS:
|
3649
|
+
case CURLOPT_REDIR_PROTOCOLS:
|
3650
|
+
curl_easy_setopt(rbce->curl, option, NUM2LONG(val));
|
3651
|
+
break;
|
3652
|
+
#if HAVE_CURLOPT_SSL_SESSIONID_CACHE
|
3653
|
+
case CURLOPT_SSL_SESSIONID_CACHE:
|
3654
|
+
curl_easy_setopt(rbce->curl, CURLOPT_SSL_SESSIONID_CACHE, NUM2LONG(val));
|
3655
|
+
break;
|
3656
|
+
#endif
|
3609
3657
|
default:
|
3610
3658
|
rb_raise(rb_eTypeError, "Curb unsupported option");
|
3611
3659
|
}
|
@@ -3913,6 +3961,7 @@ void init_curb_easy() {
|
|
3913
3961
|
rb_define_method(cCurlEasy, "multi", ruby_curl_easy_multi_get, 0);
|
3914
3962
|
rb_define_method(cCurlEasy, "multi=", ruby_curl_easy_multi_set, 1);
|
3915
3963
|
rb_define_method(cCurlEasy, "last_result", ruby_curl_easy_last_result, 0);
|
3964
|
+
rb_define_method(cCurlEasy, "last_error", ruby_curl_easy_last_error, 0);
|
3916
3965
|
|
3917
3966
|
rb_define_method(cCurlEasy, "setopt", ruby_curl_easy_set_opt, 2);
|
3918
3967
|
rb_define_method(cCurlEasy, "getinfo", ruby_curl_easy_get_opt, 1);
|
data/ext/curb_easy.h
CHANGED
@@ -36,6 +36,9 @@ typedef struct {
|
|
36
36
|
/* The handler */
|
37
37
|
CURL *curl;
|
38
38
|
|
39
|
+
/* Buffer for error details from CURLOPT_ERRORBUFFER */
|
40
|
+
char err_buf[CURL_ERROR_SIZE];
|
41
|
+
|
39
42
|
VALUE opts; /* rather then allocate everything we might need to store, allocate a Hash and only store objects we actually use... */
|
40
43
|
VALUE multi; /* keep a multi handle alive for each easy handle not being used by a multi handle. This improves easy performance when not within a multi context */
|
41
44
|
|
data/ext/curb_multi.c
CHANGED
@@ -64,7 +64,7 @@ static void ruby_curl_multi_init(ruby_curl_multi *rbcm) {
|
|
64
64
|
|
65
65
|
/*
|
66
66
|
* call-seq:
|
67
|
-
* Curl::Multi.new =>
|
67
|
+
* Curl::Multi.new => #<Curl::Easy...>
|
68
68
|
*
|
69
69
|
* Create a new Curl::Multi instance
|
70
70
|
*/
|
@@ -132,7 +132,7 @@ VALUE ruby_curl_multi_get_autoclose(VALUE klass) {
|
|
132
132
|
|
133
133
|
/*
|
134
134
|
* call-seq:
|
135
|
-
* multi.requests => [
|
135
|
+
* multi.requests => [#<Curl::Easy...>, ...]
|
136
136
|
*
|
137
137
|
* Returns an array containing all the active requests on this Curl::Multi object.
|
138
138
|
*/
|
@@ -300,10 +300,14 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
|
|
300
300
|
rbce->callback_active = 1;
|
301
301
|
val = rb_rescue(call_status_handler1, callargs, callback_exception, Qnil);
|
302
302
|
rbce->callback_active = 0;
|
303
|
-
//rb_funcall( rb_easy_get("complete_proc"), idCall, 1, easy );
|
304
303
|
}
|
305
304
|
|
305
|
+
#ifdef HAVE_CURLINFO_RESPONSE_CODE
|
306
306
|
curl_easy_getinfo(rbce->curl, CURLINFO_RESPONSE_CODE, &response_code);
|
307
|
+
#else
|
308
|
+
// old libcurl
|
309
|
+
curl_easy_getinfo(rbce->curl, CURLINFO_HTTP_CODE, &response_code);
|
310
|
+
#endif
|
307
311
|
|
308
312
|
if (result != 0) {
|
309
313
|
if (!rb_easy_nil("failure_proc")) {
|
@@ -313,8 +317,7 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
|
|
313
317
|
rbce->callback_active = 0;
|
314
318
|
//rb_funcall( rb_easy_get("failure_proc"), idCall, 2, easy, rb_curl_easy_error(result) );
|
315
319
|
}
|
316
|
-
}
|
317
|
-
else if (!rb_easy_nil("success_proc") &&
|
320
|
+
} else if (!rb_easy_nil("success_proc") &&
|
318
321
|
((response_code >= 200 && response_code < 300) || response_code == 0)) {
|
319
322
|
/* NOTE: we allow response_code == 0, in the case of non http requests e.g. reading from disk */
|
320
323
|
callargs = rb_ary_new3(2, rb_easy_get("success_proc"), easy);
|
@@ -322,22 +325,19 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
|
|
322
325
|
val = rb_rescue(call_status_handler1, callargs, callback_exception, Qnil);
|
323
326
|
rbce->callback_active = 0;
|
324
327
|
//rb_funcall( rb_easy_get("success_proc"), idCall, 1, easy );
|
325
|
-
}
|
326
|
-
else if (!rb_easy_nil("redirect_proc") &&
|
328
|
+
} else if (!rb_easy_nil("redirect_proc") &&
|
327
329
|
(response_code >= 300 && response_code < 400)) {
|
328
330
|
rbce->callback_active = 1;
|
329
331
|
callargs = rb_ary_new3(3, rb_easy_get("redirect_proc"), easy, rb_curl_easy_error(result));
|
330
332
|
rbce->callback_active = 0;
|
331
333
|
val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
|
332
|
-
}
|
333
|
-
else if (!rb_easy_nil("missing_proc") &&
|
334
|
+
} else if (!rb_easy_nil("missing_proc") &&
|
334
335
|
(response_code >= 400 && response_code < 500)) {
|
335
336
|
rbce->callback_active = 1;
|
336
337
|
callargs = rb_ary_new3(3, rb_easy_get("missing_proc"), easy, rb_curl_easy_error(result));
|
337
338
|
rbce->callback_active = 0;
|
338
339
|
val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
|
339
|
-
}
|
340
|
-
else if (!rb_easy_nil("failure_proc") &&
|
340
|
+
} else if (!rb_easy_nil("failure_proc") &&
|
341
341
|
(response_code >= 500 && response_code <= 999)) {
|
342
342
|
callargs = rb_ary_new3(3, rb_easy_get("failure_proc"), easy, rb_curl_easy_error(result));
|
343
343
|
rbce->callback_active = 1;
|
data/ext/curb_postfield.c
CHANGED
@@ -195,9 +195,9 @@ void curl_postfield_free(ruby_curl_postfield *rbcpf) {
|
|
195
195
|
|
196
196
|
/*
|
197
197
|
* call-seq:
|
198
|
-
* Curl::PostField.content(name, content) =>
|
199
|
-
* Curl::PostField.content(name, content, content_type = nil) =>
|
200
|
-
* Curl::PostField.content(name, content_type = nil) { |field| ... } =>
|
198
|
+
* Curl::PostField.content(name, content) => #<Curl::PostField...>
|
199
|
+
* Curl::PostField.content(name, content, content_type = nil) => #<Curl::PostField...>
|
200
|
+
* Curl::PostField.content(name, content_type = nil) { |field| ... } => #<Curl::PostField...>
|
201
201
|
*
|
202
202
|
* Create a new Curl::PostField, supplying the field name, content,
|
203
203
|
* and, optionally, Content-type (curl will attempt to determine this if
|
@@ -241,9 +241,9 @@ static VALUE ruby_curl_postfield_new_content(int argc, VALUE *argv, VALUE klass)
|
|
241
241
|
|
242
242
|
/*
|
243
243
|
* call-seq:
|
244
|
-
* Curl::PostField.file(name, local_file_name) =>
|
245
|
-
* Curl::PostField.file(name, local_file_name, remote_file_name = local_file_name) =>
|
246
|
-
* Curl::PostField.file(name, remote_file_name) { |field| ... } =>
|
244
|
+
* Curl::PostField.file(name, local_file_name) => #<Curl::PostField...>
|
245
|
+
* Curl::PostField.file(name, local_file_name, remote_file_name = local_file_name) => #<Curl::PostField...>
|
246
|
+
* Curl::PostField.file(name, remote_file_name) { |field| ... } => #<Curl::PostField...>
|
247
247
|
*
|
248
248
|
* Create a new Curl::PostField for a file upload field, supplying the local filename
|
249
249
|
* to read from, and optionally the remote filename (defaults to the local name).
|
@@ -399,7 +399,7 @@ static VALUE ruby_curl_postfield_remote_file_get(VALUE self) {
|
|
399
399
|
|
400
400
|
/*
|
401
401
|
* call-seq:
|
402
|
-
* field.set_content_proc { |field| ... } =>
|
402
|
+
* field.set_content_proc { |field| ... } => <old proc>
|
403
403
|
*
|
404
404
|
* Set a content proc for this field. This proc will be called during the
|
405
405
|
* perform to supply the content for this field, overriding any setting
|
data/ext/extconf.rb
CHANGED
@@ -18,6 +18,8 @@ elsif !have_library('curl') or !have_header('curl/curl.h')
|
|
18
18
|
fail <<-EOM
|
19
19
|
Can't find libcurl or curl/curl.h
|
20
20
|
|
21
|
+
Make sure development libs (ie libcurl4-openssl-dev) are installed on the system.
|
22
|
+
|
21
23
|
Try passing --with-curl-dir or --with-curl-lib and --with-curl-include
|
22
24
|
options to extconf.
|
23
25
|
EOM
|
@@ -341,6 +343,9 @@ have_constant :CURL_SSLVERSION_TLSv1_0
|
|
341
343
|
have_constant :CURL_SSLVERSION_TLSv1_1
|
342
344
|
have_constant :CURL_SSLVERSION_TLSv1_2
|
343
345
|
|
346
|
+
# Added in 7.52.0
|
347
|
+
have_constant :CURL_SSLVERSION_TLSv1_3
|
348
|
+
|
344
349
|
have_constant "curlopt_ssl_verifypeer"
|
345
350
|
have_constant "curlopt_cainfo"
|
346
351
|
have_constant "curlopt_issuercert"
|
@@ -400,6 +405,37 @@ have_constant "curlopt_path_as_is"
|
|
400
405
|
# added in 7.43.0
|
401
406
|
have_constant "curlopt_pipewait"
|
402
407
|
|
408
|
+
# protocol constants
|
409
|
+
have_constant "curlproto_all"
|
410
|
+
have_constant "curlproto_dict"
|
411
|
+
have_constant "curlproto_file"
|
412
|
+
have_constant "curlproto_ftp"
|
413
|
+
have_constant "curlproto_ftps"
|
414
|
+
have_constant "curlproto_gopher"
|
415
|
+
have_constant "curlproto_http"
|
416
|
+
have_constant "curlproto_https"
|
417
|
+
have_constant "curlproto_imap"
|
418
|
+
have_constant "curlproto_imaps"
|
419
|
+
have_constant "curlproto_ldap"
|
420
|
+
have_constant "curlproto_ldaps"
|
421
|
+
have_constant "curlproto_pop3"
|
422
|
+
have_constant "curlproto_pop3s"
|
423
|
+
have_constant "curlproto_rtmp"
|
424
|
+
have_constant "curlproto_rtmpe"
|
425
|
+
have_constant "curlproto_rtmps"
|
426
|
+
have_constant "curlproto_rtmpt"
|
427
|
+
have_constant "curlproto_rtmpte"
|
428
|
+
have_constant "curlproto_rtmpts"
|
429
|
+
have_constant "curlproto_rtsp"
|
430
|
+
have_constant "curlproto_scp"
|
431
|
+
have_constant "curlproto_sftp"
|
432
|
+
have_constant "curlproto_smb"
|
433
|
+
have_constant "curlproto_smbs"
|
434
|
+
have_constant "curlproto_smtp"
|
435
|
+
have_constant "curlproto_smtps"
|
436
|
+
have_constant "curlproto_telnet"
|
437
|
+
have_constant "curlproto_tftp"
|
438
|
+
|
403
439
|
if try_compile('int main() { return 0; }','-Wall')
|
404
440
|
$CFLAGS << ' -Wall'
|
405
441
|
end
|
data/lib/curl/easy.rb
CHANGED
@@ -21,7 +21,7 @@ module Curl
|
|
21
21
|
#
|
22
22
|
def status
|
23
23
|
# Matches the last HTTP Status - following the HTTP protocol specification 'Status-Line = HTTP-Version SP Status-Code SP (Opt:)Reason-Phrase CRLF'
|
24
|
-
statuses = self.header_str.scan(/HTTP\/\d(\.\d)?\s(\d+\s.*)\r\n/).map{
|
24
|
+
statuses = self.header_str.to_s.scan(/HTTP\/\d(\.\d)?\s(\d+\s.*)\r\n/).map {|match| match[1] }
|
25
25
|
statuses.last.strip if statuses.length > 0
|
26
26
|
end
|
27
27
|
|
@@ -75,8 +75,9 @@ module Curl
|
|
75
75
|
end
|
76
76
|
|
77
77
|
if self.last_result != 0 && self.on_failure.nil?
|
78
|
-
|
79
|
-
|
78
|
+
(err_class, err_summary) = Curl::Easy.error(self.last_result)
|
79
|
+
err_detail = self.last_error
|
80
|
+
raise err_class.new([err_summary, err_detail].compact.join(": "))
|
80
81
|
end
|
81
82
|
|
82
83
|
ret
|
@@ -320,7 +321,7 @@ module Curl
|
|
320
321
|
|
321
322
|
#
|
322
323
|
# call-seq:
|
323
|
-
# Curl::Easy.perform(url) { |easy| ... } =>
|
324
|
+
# Curl::Easy.perform(url) { |easy| ... } => #<Curl::Easy...>
|
324
325
|
#
|
325
326
|
# Convenience method that creates a new Curl::Easy instance with
|
326
327
|
# the specified URL and calls the general +perform+ method, before returning
|
@@ -338,7 +339,7 @@ module Curl
|
|
338
339
|
|
339
340
|
#
|
340
341
|
# call-seq:
|
341
|
-
# Curl::Easy.http_get(url) { |easy| ... } =>
|
342
|
+
# Curl::Easy.http_get(url) { |easy| ... } => #<Curl::Easy...>
|
342
343
|
#
|
343
344
|
# Convenience method that creates a new Curl::Easy instance with
|
344
345
|
# the specified URL and calls +http_get+, before returning the new instance.
|
@@ -355,7 +356,7 @@ module Curl
|
|
355
356
|
|
356
357
|
#
|
357
358
|
# call-seq:
|
358
|
-
# Curl::Easy.http_head(url) { |easy| ... } =>
|
359
|
+
# Curl::Easy.http_head(url) { |easy| ... } => #<Curl::Easy...>
|
359
360
|
#
|
360
361
|
# Convenience method that creates a new Curl::Easy instance with
|
361
362
|
# the specified URL and calls +http_head+, before returning the new instance.
|
@@ -409,7 +410,7 @@ module Curl
|
|
409
410
|
|
410
411
|
#
|
411
412
|
# call-seq:
|
412
|
-
# Curl::Easy.http_delete(url) { |easy| ... } =>
|
413
|
+
# Curl::Easy.http_delete(url) { |easy| ... } => #<Curl::Easy...>
|
413
414
|
#
|
414
415
|
# Convenience method that creates a new Curl::Easy instance with
|
415
416
|
# the specified URL and calls +http_delete+, before returning the new instance.
|
data/lib/curl/multi.rb
CHANGED
@@ -144,7 +144,7 @@ module Curl
|
|
144
144
|
|
145
145
|
max_connects.times do
|
146
146
|
conf = urls_with_config.pop
|
147
|
-
add_free_handle.call
|
147
|
+
add_free_handle.call(conf, nil) if conf
|
148
148
|
break if urls_with_config.empty?
|
149
149
|
end
|
150
150
|
|
@@ -153,7 +153,7 @@ module Curl
|
|
153
153
|
if urls_with_config.size > 0 && free_handles.size > 0
|
154
154
|
easy = free_handles.pop
|
155
155
|
conf = urls_with_config.pop
|
156
|
-
add_free_handle.call
|
156
|
+
add_free_handle.call(conf, easy) if conf
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
data/lib/curl.rb
CHANGED
@@ -9,12 +9,20 @@ require 'cgi'
|
|
9
9
|
module Curl
|
10
10
|
|
11
11
|
def self.http(verb, url, post_body=nil, put_data=nil, &block)
|
12
|
-
|
13
|
-
|
12
|
+
if Thread.current[:curb_curl_yielding]
|
13
|
+
handle = Curl::Easy.new # we can't reuse this
|
14
|
+
else
|
15
|
+
handle = Thread.current[:curb_curl] ||= Curl::Easy.new
|
16
|
+
handle.reset
|
17
|
+
end
|
14
18
|
handle.url = url
|
15
19
|
handle.post_body = post_body if post_body
|
16
20
|
handle.put_data = put_data if put_data
|
17
|
-
|
21
|
+
if block_given?
|
22
|
+
Thread.current[:curb_curl_yielding] = true
|
23
|
+
yield handle
|
24
|
+
Thread.current[:curb_curl_yielding] = false
|
25
|
+
end
|
18
26
|
handle.http(verb)
|
19
27
|
handle
|
20
28
|
end
|
data/tests/helper.rb
CHANGED
@@ -143,7 +143,6 @@ module TestServerMethods
|
|
143
143
|
def server_setup(port=9129,servlet=TestServlet)
|
144
144
|
@__port = port
|
145
145
|
if (@server ||= nil).nil? and !File.exist?(locked_file)
|
146
|
-
|
147
146
|
File.open(locked_file,'w') {|f| f << 'locked' }
|
148
147
|
if TEST_SINGLE_THREADED
|
149
148
|
rd, wr = IO.pipe
|
data/tests/tc_curl_easy.rb
CHANGED
@@ -10,6 +10,14 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
10
10
|
Curl.reset
|
11
11
|
end
|
12
12
|
|
13
|
+
def test_nested_easy_methods
|
14
|
+
easy = Curl.get(TestServlet.url) {|http|
|
15
|
+
res = Curl.get(TestServlet.url + '/not_here')
|
16
|
+
assert_equal 404, res.response_code
|
17
|
+
}
|
18
|
+
assert_equal 200, easy.response_code
|
19
|
+
end
|
20
|
+
|
13
21
|
def test_curlopt_stderr_with_file
|
14
22
|
# does not work with Tempfile directly
|
15
23
|
path = Tempfile.new('curb_test_curlopt_stderr').path
|
@@ -21,7 +29,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
|
|
21
29
|
end
|
22
30
|
output = File.read(path)
|
23
31
|
|
24
|
-
assert_match(
|
32
|
+
assert_match(/HTTP\/1\.1\ 200\ OK(?:\ )?/, output)
|
25
33
|
assert_match('Host: 127.0.0.1:9129', output)
|
26
34
|
end
|
27
35
|
|