curb 0.9.10 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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 => #<Curl::Easy...>
331
- * Curl::Easy.new(url = nil) => #<Curl::Easy...>
332
- * Curl::Easy.new(url = nil) { |self| ... } => #<Curl::Easy...>
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
- rb_easy_set("url", url);
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 => #&lt;easy clone&gt;
377
- * easy.dup => #&lt;easy clone&gt;
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
- /* rest clobbers the private setting, so reset it to self */
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| ... } => &lt;old handler&gt;
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| ... } => &lt;old handler&gt;
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| ... } => &lt;old handler&gt;
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| ... } => &lt;old handler;&gt;
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| ... } => &lt;old handler;&gt;
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| ... } => &lt;old handler&gt;
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| ... } => &lt;old handler&gt;
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| ... } => &lt;old handler&gt;
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| ... } => &lt;old handler&gt;
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
- // This is a bit inefficient, but we don't want to be modifying
2133
- // the actual values in the original hash.
2134
- header_str = rb_str_plus(name, rb_str_new2(": "));
2135
- header_str = rb_str_plus(header_str, value);
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
- * pippelining where the pretransfer time can be delayed due to waits in line
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, HAVE_CURLOPT_HAPROXYPROTOCOL, NUM2LONG(val));
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 => #&lt;Curl::Easy...&gt;
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 => [#&lt;Curl::Easy...&gt;, ...]
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) => #&lt;Curl::PostField...&gt;
199
- * Curl::PostField.content(name, content, content_type = nil) => #&lt;Curl::PostField...&gt;
200
- * Curl::PostField.content(name, content_type = nil) { |field| ... } => #&lt;Curl::PostField...&gt;
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) => #&lt;Curl::PostField...&gt;
245
- * Curl::PostField.file(name, local_file_name, remote_file_name = local_file_name) => #&lt;Curl::PostField...&gt;
246
- * Curl::PostField.file(name, remote_file_name) { |field| ... } => #&lt;Curl::PostField...&gt;
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| ... } => &lt;old proc&gt;
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{ |match| match[1] }
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
- error = Curl::Easy.error(self.last_result)
79
- raise error.first.new(self.head)
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| ... } => #&lt;Curl::Easy...&gt;
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| ... } => #&lt;Curl::Easy...&gt;
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| ... } => #&lt;Curl::Easy...&gt;
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| ... } => #&lt;Curl::Easy...&gt;
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 conf, nil
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 conf, easy
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
- handle = Thread.current[:curb_curl] ||= Curl::Easy.new
13
- handle.reset
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
- yield handle if block_given?
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
@@ -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('HTTP/1.1 200 OK ', output)
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