curb 0.9.10 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|