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.
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