curb 1.0.1 → 1.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b452d79ee28ee380d6741f39f9fbf826a33a46d473fa4444edb6a56a122af8f8
4
- data.tar.gz: '094812699e5b64584d6dd02a17b16884ee696a20dbf324c05498a46509e39b16'
3
+ metadata.gz: e28b1d05b46460867acfadc87bbe422d58d8f2cdb93397fa6ded906b01cd7dab
4
+ data.tar.gz: 33e7037c1c2b23a793ec96c73bc80c008939c880702f884d2b258d4afd18c368
5
5
  SHA512:
6
- metadata.gz: 0df71c1a4eb7896f89da78a79ba9160d5606aa235b89544e08630c558a7cebb1220ec026f99f404915f52e15162cf2c988a66abe04932c3cd1104a1784bd3056
7
- data.tar.gz: '08fba6b5b9a9404f839e4110b0d485e1595be36554345abb88a05482183204f4e0f13001a7731db75e89ca890bfa8ad19ccced63dfecd0e766f1b825ff5e9f1a'
6
+ metadata.gz: 6eb448726a4fdce1e0832e36a45b2c8e0a078fbc2c04b3fe34f87fc38397f5c4ecc4fe621aed5637750c5c7a7a9d05b30c03f9f7db153c23d3694eb6adb464e8
7
+ data.tar.gz: 624e3f39af79eff874784a662776debc2b405378c6cdc963a50dee525d36aa225cc5f40558f9b35b396c222416006f66c29fc6193e651b5aa84093fdd52cb2ba
data/README.markdown CHANGED
@@ -1,5 +1,6 @@
1
- # Curb - Libcurl bindings for Ruby [![Build Status](https://travis-ci.org/taf2/curb.svg?branch=master)](https://travis-ci.org/taf2/curb)
1
+ # Curb - Libcurl bindings for Ruby
2
2
 
3
+ * [CI Build Status](https://github.com/taf2/curb/actions/workflows/CI.yml)
3
4
  * [rubydoc rdoc](http://www.rubydoc.info/github/taf2/curb/)
4
5
  * [github project](http://github.com/taf2/curb/tree/master)
5
6
 
@@ -11,26 +12,38 @@ Curb is a work-in-progress, and currently only supports libcurl's `easy` and `mu
11
12
 
12
13
  ## License
13
14
 
14
- Curb is copyright (c)2006 Ross Bamford, and released under the terms of the
15
+ Curb is copyright (c) 2006 Ross Bamford, and released under the terms of the
15
16
  Ruby license. See the LICENSE file for the gory details.
16
17
 
17
18
  ## Easy mode
18
19
 
19
- Get stuff
20
+ GET request
20
21
  ```
21
- res = Curl.get("https://www.google.com/")
22
- puts res.response_code
23
- puts res.header_str
22
+ res = Curl.get("https://www.google.com/") {|http|
23
+ http.timeout = 10 # raise exception if request/response not handled within 10 seconds
24
+ }
25
+ puts res.code
26
+ puts res.head
24
27
  puts res.body
25
28
  ```
26
29
 
27
- Post stuff
30
+ POST request
28
31
  ```
29
32
  res = Curl.post("https://your-server.com/endpoint", {post: "this"}.to_json) {|http|
30
33
  http.headers["Content-Type"] = "application/json"
31
34
  }
32
- puts res.response_code
33
- puts res.header_str
35
+ puts res.code
36
+ puts res.head
37
+ puts res.body
38
+ ```
39
+
40
+ PATCH request
41
+ ```
42
+ res = Curl.patch("https://your-server.com/endpoint", {post: "this"}.to_json) {|http|
43
+ http.headers["Content-Type"] = "application/json"
44
+ }
45
+ puts res.code
46
+ puts res.head
34
47
  puts res.body
35
48
  ```
36
49
 
data/Rakefile CHANGED
@@ -2,6 +2,7 @@
2
2
  #
3
3
  require 'rake/clean'
4
4
  require 'rake/testtask'
5
+ require "ruby_memcheck"
5
6
 
6
7
  CLEAN.include '**/*.o'
7
8
  CLEAN.include "**/*.#{(defined?(RbConfig) ? RbConfig : Config)::MAKEFILE_CONFIG['DLEXT']}"
@@ -10,13 +11,6 @@ CLOBBER.include '**/*.log'
10
11
  CLOBBER.include '**/Makefile'
11
12
  CLOBBER.include '**/extconf.h'
12
13
 
13
- # Not available for really old rubies, but that's ok.
14
- begin
15
- require 'pry'
16
- rescue LoadError
17
- puts "Failed to load pry."
18
- end
19
-
20
14
  # Load support ruby and rake files (in this order)
21
15
  Dir.glob('tasks/*.rb').each { |r| load r}
22
16
  Dir.glob('tasks/*.rake').each { |r| load r}
@@ -97,6 +91,14 @@ else
97
91
  task :alltests => [:unittests, :bugtests]
98
92
  end
99
93
 
94
+ RubyMemcheck.config(binary_name: 'curb_core')
95
+ namespace :test do
96
+ RubyMemcheck::TestTask.new(valgrind: :compile) do|t|
97
+ t.test_files = FileList['tests/tc_*.rb']
98
+ t.verbose = false
99
+ end
100
+ end
101
+
100
102
  Rake::TestTask.new(:unittests) do |t|
101
103
  t.test_files = FileList['tests/tc_*.rb']
102
104
  t.verbose = false
data/ext/curb.c CHANGED
@@ -1076,6 +1076,10 @@ void Init_curb_core() {
1076
1076
  CURB_DEFINE(CURLOPT_HAPROXYPROTOCOL);
1077
1077
  #endif
1078
1078
 
1079
+ #if HAVE_CURLOPT_PROXY_SSL_VERIFYHOST
1080
+ CURB_DEFINE(CURLOPT_PROXY_SSL_VERIFYHOST);
1081
+ #endif
1082
+
1079
1083
  #if HAVE_CURLPROTO_RTMPTE
1080
1084
  CURB_DEFINE(CURLPROTO_RTMPTE);
1081
1085
  #endif
data/ext/curb.h CHANGED
@@ -28,11 +28,11 @@
28
28
  #include "curb_macros.h"
29
29
 
30
30
  // These should be managed from the Rake 'release' task.
31
- #define CURB_VERSION "1.0.1"
32
- #define CURB_VER_NUM 1001
31
+ #define CURB_VERSION "1.0.5"
32
+ #define CURB_VER_NUM 1005
33
33
  #define CURB_VER_MAJ 1
34
34
  #define CURB_VER_MIN 0
35
- #define CURB_VER_MIC 1
35
+ #define CURB_VER_MIC 5
36
36
  #define CURB_VER_PATCH 0
37
37
 
38
38
 
data/ext/curb_easy.c CHANGED
@@ -34,7 +34,7 @@ static FILE * rb_io_stdio_file(rb_io_t *fptr) {
34
34
 
35
35
  /* ================== CURL HANDLER FUNCS ==============*/
36
36
 
37
- static VALUE callback_exception(VALUE unused) {
37
+ static VALUE callback_exception(VALUE unused, VALUE exception) {
38
38
  return Qfalse;
39
39
  }
40
40
 
@@ -1311,7 +1311,7 @@ static VALUE ruby_curl_easy_connect_timeout_set(VALUE self, VALUE connect_timeou
1311
1311
  * Obtain the maximum time in seconds that you allow the connection to the
1312
1312
  * server to take.
1313
1313
  */
1314
- static VALUE ruby_curl_easy_connect_timeout_get(VALUE self, VALUE connect_timeout) {
1314
+ static VALUE ruby_curl_easy_connect_timeout_get(VALUE self) {
1315
1315
  CURB_IMMED_GETTER(ruby_curl_easy, connect_timeout, 0);
1316
1316
  }
1317
1317
 
@@ -1337,7 +1337,7 @@ static VALUE ruby_curl_easy_connect_timeout_ms_set(VALUE self, VALUE connect_tim
1337
1337
  * Obtain the maximum time in milliseconds that you allow the connection to the
1338
1338
  * server to take.
1339
1339
  */
1340
- static VALUE ruby_curl_easy_connect_timeout_ms_get(VALUE self, VALUE connect_timeout_ms) {
1340
+ static VALUE ruby_curl_easy_connect_timeout_ms_get(VALUE self) {
1341
1341
  CURB_IMMED_GETTER(ruby_curl_easy, connect_timeout_ms, 0);
1342
1342
  }
1343
1343
 
@@ -1360,7 +1360,7 @@ static VALUE ruby_curl_easy_dns_cache_timeout_set(VALUE self, VALUE dns_cache_ti
1360
1360
  *
1361
1361
  * Obtain the dns cache timeout in seconds.
1362
1362
  */
1363
- static VALUE ruby_curl_easy_dns_cache_timeout_get(VALUE self, VALUE dns_cache_timeout) {
1363
+ static VALUE ruby_curl_easy_dns_cache_timeout_get(VALUE self) {
1364
1364
  CURB_IMMED_GETTER(ruby_curl_easy, dns_cache_timeout, -1);
1365
1365
  }
1366
1366
 
@@ -1387,7 +1387,7 @@ static VALUE ruby_curl_easy_ftp_response_timeout_set(VALUE self, VALUE ftp_respo
1387
1387
  *
1388
1388
  * Obtain the maximum time that libcurl will wait for FTP command responses.
1389
1389
  */
1390
- static VALUE ruby_curl_easy_ftp_response_timeout_get(VALUE self, VALUE ftp_response_timeout) {
1390
+ static VALUE ruby_curl_easy_ftp_response_timeout_get(VALUE self) {
1391
1391
  CURB_IMMED_GETTER(ruby_curl_easy, ftp_response_timeout, 0);
1392
1392
  }
1393
1393
 
@@ -1410,7 +1410,7 @@ static VALUE ruby_curl_easy_low_speed_limit_set(VALUE self, VALUE low_speed_limi
1410
1410
  * Obtain the minimum transfer speed over +low_speed+time+ below which the
1411
1411
  * transfer will be aborted.
1412
1412
  */
1413
- static VALUE ruby_curl_easy_low_speed_limit_get(VALUE self, VALUE low_speed_limit) {
1413
+ static VALUE ruby_curl_easy_low_speed_limit_get(VALUE self) {
1414
1414
  CURB_IMMED_GETTER(ruby_curl_easy, low_speed_limit, 0);
1415
1415
  }
1416
1416
 
@@ -1432,7 +1432,7 @@ static VALUE ruby_curl_easy_low_speed_time_set(VALUE self, VALUE low_speed_time)
1432
1432
  * Obtain the time that the transfer should be below +low_speed_limit+ for
1433
1433
  * the library to abort it.
1434
1434
  */
1435
- static VALUE ruby_curl_easy_low_speed_time_get(VALUE self, VALUE low_speed_time) {
1435
+ static VALUE ruby_curl_easy_low_speed_time_get(VALUE self) {
1436
1436
  CURB_IMMED_GETTER(ruby_curl_easy, low_speed_time, 0);
1437
1437
  }
1438
1438
 
@@ -1452,7 +1452,7 @@ static VALUE ruby_curl_easy_max_send_speed_large_set(VALUE self, VALUE max_send_
1452
1452
  *
1453
1453
  * Get the maximal sending transfer speed (in bytes per second)
1454
1454
  */
1455
- static VALUE ruby_curl_easy_max_send_speed_large_get(VALUE self, VALUE max_send_speed_large) {
1455
+ static VALUE ruby_curl_easy_max_send_speed_large_get(VALUE self) {
1456
1456
  CURB_IMMED_GETTER(ruby_curl_easy, max_send_speed_large, 0);
1457
1457
  }
1458
1458
 
@@ -1472,7 +1472,7 @@ static VALUE ruby_curl_easy_max_recv_speed_large_set(VALUE self, VALUE max_recv_
1472
1472
  *
1473
1473
  * Get the maximal receiving transfer speed (in bytes per second)
1474
1474
  */
1475
- static VALUE ruby_curl_easy_max_recv_speed_large_get(VALUE self, VALUE max_recv_speed_large) {
1475
+ static VALUE ruby_curl_easy_max_recv_speed_large_get(VALUE self) {
1476
1476
  CURB_IMMED_GETTER(ruby_curl_easy, max_recv_speed_large, 0);
1477
1477
  }
1478
1478
 
@@ -1496,7 +1496,7 @@ static VALUE ruby_curl_easy_username_set(VALUE self, VALUE username) {
1496
1496
  *
1497
1497
  * Get the current username
1498
1498
  */
1499
- static VALUE ruby_curl_easy_username_get(VALUE self, VALUE username) {
1499
+ static VALUE ruby_curl_easy_username_get(VALUE self) {
1500
1500
  #if HAVE_CURLOPT_USERNAME
1501
1501
  CURB_OBJECT_HGETTER(ruby_curl_easy, username);
1502
1502
  #else
@@ -1524,7 +1524,7 @@ static VALUE ruby_curl_easy_password_set(VALUE self, VALUE password) {
1524
1524
  *
1525
1525
  * Get the current password
1526
1526
  */
1527
- static VALUE ruby_curl_easy_password_get(VALUE self, VALUE password) {
1527
+ static VALUE ruby_curl_easy_password_get(VALUE self) {
1528
1528
  #if HAVE_CURLOPT_PASSWORD
1529
1529
  CURB_OBJECT_HGETTER(ruby_curl_easy, password);
1530
1530
  #else
@@ -1558,7 +1558,7 @@ static VALUE ruby_curl_easy_ssl_version_set(VALUE self, VALUE ssl_version) {
1558
1558
  *
1559
1559
  * Get the version of SSL/TLS that libcurl will attempt to use.
1560
1560
  */
1561
- static VALUE ruby_curl_easy_ssl_version_get(VALUE self, VALUE ssl_version) {
1561
+ static VALUE ruby_curl_easy_ssl_version_get(VALUE self) {
1562
1562
  CURB_IMMED_GETTER(ruby_curl_easy, ssl_version, -1);
1563
1563
  }
1564
1564
 
@@ -1579,7 +1579,7 @@ static VALUE ruby_curl_easy_use_ssl_set(VALUE self, VALUE use_ssl) {
1579
1579
  *
1580
1580
  * Get the desired level for using SSL on FTP connections.
1581
1581
  */
1582
- static VALUE ruby_curl_easy_use_ssl_get(VALUE self, VALUE use_ssl) {
1582
+ static VALUE ruby_curl_easy_use_ssl_get(VALUE self) {
1583
1583
  CURB_IMMED_GETTER(ruby_curl_easy, use_ssl, -1);
1584
1584
  }
1585
1585
 
@@ -1600,7 +1600,7 @@ static VALUE ruby_curl_easy_ftp_filemethod_set(VALUE self, VALUE ftp_filemethod)
1600
1600
  *
1601
1601
  * Get the configuration for how libcurl will reach files on the server.
1602
1602
  */
1603
- static VALUE ruby_curl_easy_ftp_filemethod_get(VALUE self, VALUE ftp_filemethod) {
1603
+ static VALUE ruby_curl_easy_ftp_filemethod_get(VALUE self) {
1604
1604
  CURB_IMMED_GETTER(ruby_curl_easy, ftp_filemethod, -1);
1605
1605
  }
1606
1606
 
@@ -2122,7 +2122,7 @@ static VALUE ruby_curl_easy_on_debug_set(int argc, VALUE *argv, VALUE self) {
2122
2122
  /***********************************************
2123
2123
  * This is an rb_iterate callback used to set up http headers.
2124
2124
  */
2125
- static VALUE cb_each_http_header(VALUE header, VALUE wrap) {
2125
+ static VALUE cb_each_http_header(VALUE header, VALUE wrap, int _c, const VALUE *_ptr, VALUE unused) {
2126
2126
  struct curl_slist **list;
2127
2127
  VALUE header_str = Qnil;
2128
2128
 
@@ -2157,7 +2157,7 @@ static VALUE cb_each_http_header(VALUE header, VALUE wrap) {
2157
2157
  /***********************************************
2158
2158
  * This is an rb_iterate callback used to set up http proxy headers.
2159
2159
  */
2160
- static VALUE cb_each_http_proxy_header(VALUE proxy_header, VALUE wrap) {
2160
+ static VALUE cb_each_http_proxy_header(VALUE proxy_header, VALUE wrap, int _c, const VALUE *_ptr, VALUE unused) {
2161
2161
  struct curl_slist **list;
2162
2162
  VALUE proxy_header_str = Qnil;
2163
2163
 
@@ -2189,7 +2189,7 @@ static VALUE cb_each_http_proxy_header(VALUE proxy_header, VALUE wrap) {
2189
2189
  /***********************************************
2190
2190
  * This is an rb_iterate callback used to set up ftp commands.
2191
2191
  */
2192
- static VALUE cb_each_ftp_command(VALUE ftp_command, VALUE wrap) {
2192
+ static VALUE cb_each_ftp_command(VALUE ftp_command, VALUE wrap, int _c, const VALUE *_ptr, VALUE unused) {
2193
2193
  struct curl_slist **list;
2194
2194
  VALUE ftp_command_string;
2195
2195
  Data_Get_Struct(wrap, struct curl_slist *, list);
@@ -2203,7 +2203,7 @@ static VALUE cb_each_ftp_command(VALUE ftp_command, VALUE wrap) {
2203
2203
  /***********************************************
2204
2204
  * This is an rb_iterate callback used to set up the resolve list.
2205
2205
  */
2206
- static VALUE cb_each_resolve(VALUE resolve, VALUE wrap) {
2206
+ static VALUE cb_each_resolve(VALUE resolve, VALUE wrap, int _c, const VALUE *_ptr, VALUE unused) {
2207
2207
  struct curl_slist **list;
2208
2208
  VALUE resolve_string;
2209
2209
  Data_Get_Struct(wrap, struct curl_slist *, list);
@@ -2602,7 +2602,7 @@ VALUE ruby_curl_easy_cleanup( VALUE self, ruby_curl_easy *rbce ) {
2602
2602
  }
2603
2603
 
2604
2604
  // set values on cleanup to nil
2605
- rb_easy_del("multi");
2605
+ //rb_easy_del("multi");
2606
2606
 
2607
2607
  return Qnil;
2608
2608
  }
@@ -3653,6 +3653,11 @@ static VALUE ruby_curl_easy_set_opt(VALUE self, VALUE opt, VALUE val) {
3653
3653
  case CURLOPT_SSL_SESSIONID_CACHE:
3654
3654
  curl_easy_setopt(rbce->curl, CURLOPT_SSL_SESSIONID_CACHE, NUM2LONG(val));
3655
3655
  break;
3656
+ #endif
3657
+ #if HAVE_CURLOPT_PROXY_SSL_VERIFYHOST
3658
+ case CURLOPT_PROXY_SSL_VERIFYHOST:
3659
+ curl_easy_setopt(rbce->curl, CURLOPT_PROXY_SSL_VERIFYHOST, NUM2LONG(val));
3660
+ break;
3656
3661
  #endif
3657
3662
  default:
3658
3663
  rb_raise(rb_eTypeError, "Curb unsupported option");
@@ -3770,6 +3775,7 @@ static VALUE ruby_curl_easy_error_message(VALUE klass, VALUE code) {
3770
3775
  }
3771
3776
 
3772
3777
  /* =================== INIT LIB =====================*/
3778
+ // TODO: https://bugs.ruby-lang.org/issues/18007
3773
3779
  void init_curb_easy() {
3774
3780
  idCall = rb_intern("call");
3775
3781
  idJoin = rb_intern("join");
@@ -3915,6 +3921,7 @@ void init_curb_easy() {
3915
3921
 
3916
3922
  rb_define_method(cCurlEasy, "last_effective_url", ruby_curl_easy_last_effective_url_get, 0);
3917
3923
  rb_define_method(cCurlEasy, "response_code", ruby_curl_easy_response_code_get, 0);
3924
+ rb_define_method(cCurlEasy, "code", ruby_curl_easy_response_code_get, 0);
3918
3925
  #if defined(HAVE_CURLINFO_PRIMARY_IP)
3919
3926
  rb_define_method(cCurlEasy, "primary_ip", ruby_curl_easy_primary_ip_get, 0);
3920
3927
  #endif
data/ext/curb_macros.h CHANGED
@@ -156,4 +156,16 @@
156
156
  #define CURB_DEFINE(name) \
157
157
  rb_define_const(mCurl, #name, LONG2NUM(name))
158
158
 
159
+ /* copy and raise exception */
160
+ #define CURB_CHECK_RB_CALLBACK_RAISE(did_raise) \
161
+ VALUE exception = rb_hash_aref(did_raise, rb_easy_hkey("error")); \
162
+ if (FIX2INT(rb_hash_size(did_raise)) > 0 && exception != Qnil) { \
163
+ rb_hash_clear(did_raise); \
164
+ VALUE message = rb_funcall(exception, rb_intern("message"), 0); \
165
+ VALUE aborted_exception = rb_exc_new_str(eCurlErrAbortedByCallback, message); \
166
+ VALUE backtrace = rb_funcall(exception, rb_intern("backtrace"), 0); \
167
+ rb_funcall(aborted_exception, rb_intern("set_backtrace"), 1, backtrace); \
168
+ rb_exc_raise(aborted_exception); \
169
+ }
170
+
159
171
  #endif
data/ext/curb_multi.c CHANGED
@@ -43,8 +43,25 @@ static void rb_curl_multi_remove(ruby_curl_multi *rbcm, VALUE easy);
43
43
  static void rb_curl_multi_read_info(VALUE self, CURLM *mptr);
44
44
  static void rb_curl_multi_run(VALUE self, CURLM *multi_handle, int *still_running);
45
45
 
46
- static VALUE callback_exception(VALUE unused) {
47
- return Qfalse;
46
+ static VALUE callback_exception(VALUE did_raise, VALUE exception) {
47
+ // TODO: we could have an option to enable exception reporting
48
+ /* VALUE ret = rb_funcall(exception, rb_intern("message"), 0);
49
+ VALUE trace = rb_funcall(exception, rb_intern("backtrace"), 0);
50
+ if (RB_TYPE_P(trace, T_ARRAY) && RARRAY_LEN(trace) > 0) {
51
+ printf("we got an exception: %s:%d\n", StringValueCStr(ret), RARRAY_LEN(trace));
52
+ VALUE sep = rb_str_new_cstr("\n");
53
+ VALUE trace_lines = rb_ary_join(trace, sep);
54
+ if (RB_TYPE_P(trace_lines, T_STRING)) {
55
+ printf("%s\n", StringValueCStr(trace_lines));
56
+ } else {
57
+ printf("trace is not a string??\n");
58
+ }
59
+ } else {
60
+ printf("we got an exception: %s\nno stack available\n", StringValueCStr(ret));
61
+ }
62
+ */
63
+ rb_hash_aset(did_raise, rb_easy_hkey("error"), exception);
64
+ return exception;
48
65
  }
49
66
 
50
67
  void curl_multi_free(ruby_curl_multi *rbcm) {
@@ -274,7 +291,7 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
274
291
  long response_code = -1;
275
292
  VALUE easy;
276
293
  ruby_curl_easy *rbce = NULL;
277
- VALUE callargs, val = Qtrue;
294
+ VALUE callargs;
278
295
 
279
296
  CURLcode ecode = curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, (char**)&easy);
280
297
 
@@ -295,11 +312,14 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
295
312
  raise_curl_easy_error_exception(ecode);
296
313
  }
297
314
 
315
+ VALUE did_raise = rb_hash_new();
316
+
298
317
  if (!rb_easy_nil("complete_proc")) {
299
318
  callargs = rb_ary_new3(2, rb_easy_get("complete_proc"), easy);
300
319
  rbce->callback_active = 1;
301
- val = rb_rescue(call_status_handler1, callargs, callback_exception, Qnil);
320
+ rb_rescue(call_status_handler1, callargs, callback_exception, did_raise);
302
321
  rbce->callback_active = 0;
322
+ CURB_CHECK_RB_CALLBACK_RAISE(did_raise);
303
323
  }
304
324
 
305
325
  #ifdef HAVE_CURLINFO_RESPONSE_CODE
@@ -308,42 +328,46 @@ static void rb_curl_mutli_handle_complete(VALUE self, CURL *easy_handle, int res
308
328
  // old libcurl
309
329
  curl_easy_getinfo(rbce->curl, CURLINFO_HTTP_CODE, &response_code);
310
330
  #endif
331
+ long redirect_count;
332
+ curl_easy_getinfo(rbce->curl, CURLINFO_REDIRECT_COUNT, &redirect_count);
311
333
 
312
334
  if (result != 0) {
313
335
  if (!rb_easy_nil("failure_proc")) {
314
336
  callargs = rb_ary_new3(3, rb_easy_get("failure_proc"), easy, rb_curl_easy_error(result));
315
337
  rbce->callback_active = 1;
316
- val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
338
+ rb_rescue(call_status_handler2, callargs, callback_exception, did_raise);
317
339
  rbce->callback_active = 0;
318
- //rb_funcall( rb_easy_get("failure_proc"), idCall, 2, easy, rb_curl_easy_error(result) );
340
+ CURB_CHECK_RB_CALLBACK_RAISE(did_raise);
319
341
  }
320
342
  } else if (!rb_easy_nil("success_proc") &&
321
343
  ((response_code >= 200 && response_code < 300) || response_code == 0)) {
322
344
  /* NOTE: we allow response_code == 0, in the case of non http requests e.g. reading from disk */
323
345
  callargs = rb_ary_new3(2, rb_easy_get("success_proc"), easy);
324
346
  rbce->callback_active = 1;
325
- val = rb_rescue(call_status_handler1, callargs, callback_exception, Qnil);
347
+ rb_rescue(call_status_handler1, callargs, callback_exception, did_raise);
326
348
  rbce->callback_active = 0;
327
- //rb_funcall( rb_easy_get("success_proc"), idCall, 1, easy );
328
- } else if (!rb_easy_nil("redirect_proc") &&
329
- (response_code >= 300 && response_code < 400)) {
349
+ CURB_CHECK_RB_CALLBACK_RAISE(did_raise);
350
+
351
+ } else if (!rb_easy_nil("redirect_proc") && ((response_code >= 300 && response_code < 400) || redirect_count > 0) ) {
330
352
  rbce->callback_active = 1;
331
353
  callargs = rb_ary_new3(3, rb_easy_get("redirect_proc"), easy, rb_curl_easy_error(result));
332
354
  rbce->callback_active = 0;
333
- val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
355
+ rb_rescue(call_status_handler2, callargs, callback_exception, did_raise);
356
+ CURB_CHECK_RB_CALLBACK_RAISE(did_raise);
334
357
  } else if (!rb_easy_nil("missing_proc") &&
335
358
  (response_code >= 400 && response_code < 500)) {
336
359
  rbce->callback_active = 1;
337
360
  callargs = rb_ary_new3(3, rb_easy_get("missing_proc"), easy, rb_curl_easy_error(result));
338
361
  rbce->callback_active = 0;
339
- val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
362
+ rb_rescue(call_status_handler2, callargs, callback_exception, did_raise);
363
+ CURB_CHECK_RB_CALLBACK_RAISE(did_raise);
340
364
  } else if (!rb_easy_nil("failure_proc") &&
341
365
  (response_code >= 500 && response_code <= 999)) {
342
366
  callargs = rb_ary_new3(3, rb_easy_get("failure_proc"), easy, rb_curl_easy_error(result));
343
367
  rbce->callback_active = 1;
344
- val = rb_rescue(call_status_handler2, callargs, callback_exception, Qnil);
368
+ rb_rescue(call_status_handler2, callargs, callback_exception, did_raise);
345
369
  rbce->callback_active = 0;
346
- //rb_funcall( rb_easy_get("failure_proc"), idCall, 2, easy, rb_curl_easy_error(result) );
370
+ CURB_CHECK_RB_CALLBACK_RAISE(did_raise);
347
371
  }
348
372
 
349
373
  }
@@ -627,6 +651,8 @@ void init_curb_multi() {
627
651
  idCall = rb_intern("call");
628
652
  cCurlMulti = rb_define_class_under(mCurl, "Multi", rb_cObject);
629
653
 
654
+ rb_undef_alloc_func(cCurlMulti);
655
+
630
656
  /* Class methods */
631
657
  rb_define_singleton_method(cCurlMulti, "new", ruby_curl_multi_new, 0);
632
658
  rb_define_singleton_method(cCurlMulti, "default_timeout=", ruby_curl_multi_set_default_timeout, 1);
data/ext/curb_postfield.c CHANGED
@@ -498,6 +498,8 @@ void init_curb_postfield() {
498
498
 
499
499
  cCurlPostField = rb_define_class_under(mCurl, "PostField", rb_cObject);
500
500
 
501
+ rb_undef_alloc_func(cCurlPostField);
502
+
501
503
  /* Class methods */
502
504
  rb_define_singleton_method(cCurlPostField, "content", ruby_curl_postfield_new_content, -1);
503
505
  rb_define_singleton_method(cCurlPostField, "file", ruby_curl_postfield_new_file, -1);
data/ext/curb_upload.c CHANGED
@@ -72,6 +72,7 @@ VALUE ruby_curl_upload_offset_get(VALUE self) {
72
72
  /* =================== INIT LIB =====================*/
73
73
  void init_curb_upload() {
74
74
  cCurlUpload = rb_define_class_under(mCurl, "Upload", rb_cObject);
75
+ rb_undef_alloc_func(cCurlUpload);
75
76
  rb_define_singleton_method(cCurlUpload, "new", ruby_curl_upload_new, 0);
76
77
  rb_define_method(cCurlUpload, "stream=", ruby_curl_upload_stream_set, 1);
77
78
  rb_define_method(cCurlUpload, "stream", ruby_curl_upload_stream_get, 0);
data/ext/extconf.rb CHANGED
@@ -405,6 +405,8 @@ have_constant "curlopt_path_as_is"
405
405
  # added in 7.43.0
406
406
  have_constant "curlopt_pipewait"
407
407
 
408
+ have_constant "curlopt_proxy_ssl_verifyhost"
409
+
408
410
  # protocol constants
409
411
  have_constant "curlproto_all"
410
412
  have_constant "curlproto_dict"
data/lib/curl/multi.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
  module Curl
3
3
  class Multi
4
+ class DownloadError < RuntimeError
5
+ attr_accessor :errors
6
+ end
4
7
  class << self
5
8
  # call-seq:
6
9
  # Curl::Multi.get(['url1','url2','url3','url4','url5'], :follow_location => true) do|easy|
@@ -241,7 +244,11 @@ module Curl
241
244
  errors << e
242
245
  end
243
246
  }
244
- raise errors unless errors.empty?
247
+ if errors.any?
248
+ de = Curl::Multi::DownloadError.new
249
+ de.errors = errors
250
+ raise de
251
+ end
245
252
  end
246
253
  end
247
254
 
@@ -1,37 +1,23 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
2
 
3
- require 'webrick'
4
- class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
5
- class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
6
-
7
- require 'curl'
8
-
9
3
  class BugCrashOnDebug < Test::Unit::TestCase
4
+ include BugTestServerSetupTeardown
10
5
 
11
6
  def test_on_debug
12
- server = WEBrick::HTTPServer.new( :Port => 9999 )
13
- server.mount_proc("/test") do|req,res|
14
- res.body = "hi"
15
- res['Content-Type'] = "text/html"
16
- end
17
- puts 'a'
18
- thread = Thread.new(server) do|srv|
19
- srv.start
20
- end
21
- puts 'b'
22
- c = Curl::Easy.new('http://127.0.0.1:9999/test')
23
- c.on_debug do|x|
24
- puts x.inspect
25
- raise "error" # this will get swallowed
7
+ c = Curl::Easy.new("http://127.0.0.1:#{@port}/test")
8
+ did_raise = false
9
+ did_call = false
10
+ begin
11
+ c.on_success do|x|
12
+ did_call = true
13
+ raise "error" # this will get swallowed
14
+ end
15
+ c.perform
16
+ rescue => e
17
+ did_raise = true
26
18
  end
27
- c.perform
28
- puts 'c'
29
- ensure
30
- puts 'd'
31
- server.shutdown
32
- puts 'e'
33
- puts thread.exit
34
- puts 'f'
19
+ assert did_raise
20
+ assert did_call
35
21
  end
36
22
 
37
23
  end
@@ -1,22 +1,10 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
- require 'webrick'
3
- class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
4
- class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
5
2
 
6
3
  class BugCrashOnDebug < Test::Unit::TestCase
7
-
8
- def test_on_progress_raise
9
- server = WEBrick::HTTPServer.new( :Port => 9999 )
10
- server.mount_proc("/test") do|req,res|
11
- res.body = "hi"
12
- res['Content-Type'] = "text/html"
13
- end
4
+ include BugTestServerSetupTeardown
14
5
 
15
- thread = Thread.new(server) do|srv|
16
- srv.start
17
- end
18
-
19
- c = Curl::Easy.new('http://127.0.0.1:9999/test')
6
+ def test_on_progress_raise
7
+ c = Curl::Easy.new("http://127.0.0.1:#{@port}/test")
20
8
  c.on_progress do|x|
21
9
  raise "error"
22
10
  end
@@ -27,21 +15,9 @@ class BugCrashOnDebug < Test::Unit::TestCase
27
15
  rescue => e
28
16
  assert_equal 'Curl::Err::AbortedByCallbackError', e.class.to_s
29
17
  c.close
30
- ensure
31
- server.shutdown
32
18
  end
33
19
 
34
20
  def test_on_progress_abort
35
- server = WEBrick::HTTPServer.new( :Port => 9999 )
36
- server.mount_proc("/test") do|req,res|
37
- res.body = "hi"
38
- res['Content-Type'] = "text/html"
39
- end
40
-
41
- thread = Thread.new(server) do|srv|
42
- srv.start
43
- end
44
-
45
21
  # see: https://github.com/taf2/curb/issues/192,
46
22
  # to pass:
47
23
  #
@@ -54,20 +30,20 @@ class BugCrashOnDebug < Test::Unit::TestCase
54
30
  #
55
31
  # notice no return keyword
56
32
  #
57
- c = Curl::Easy.new('http://127.0.0.1:9999/test')
33
+ c = Curl::Easy.new("http://127.0.0.1:#{@port}/test")
34
+ did_progress = false
58
35
  c.on_progress do|x|
59
- puts "we're in the progress callback"
36
+ did_progress = true
60
37
  return false
61
38
  end
62
39
  c.perform
40
+ assert did_progress
63
41
 
64
42
  assert false, "should not reach this point"
65
43
 
66
44
  rescue => e
67
45
  assert_equal 'Curl::Err::AbortedByCallbackError', e.class.to_s
68
46
  c.close
69
- ensure
70
- server.shutdown
71
47
  end
72
48
 
73
49
  end
@@ -1,21 +1,19 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
- require 'webrick'
3
- class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
4
- class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
5
2
 
6
3
  class BugTestInstancePostDiffersFromClassPost < Test::Unit::TestCase
7
- def test_bug
8
- server = WEBrick::HTTPServer.new( :Port => 9999 )
9
- server.mount_proc("/test") do|req,res|
4
+ include BugTestServerSetupTeardown
5
+
6
+ def setup
7
+ @port = 9999
8
+ @response_proc = lambda do|res|
10
9
  sleep 0.5
11
10
  res.body = "hi"
12
11
  res['Content-Type'] = "text/html"
13
12
  end
13
+ super
14
+ end
14
15
 
15
- thread = Thread.new(server) do|srv|
16
- srv.start
17
- end
18
-
16
+ def test_bug
19
17
  threads = []
20
18
  timer = Time.now
21
19
 
@@ -45,8 +43,5 @@ class BugTestInstancePostDiffersFromClassPost < Test::Unit::TestCase
45
43
  puts "requested in #{single_time}"
46
44
 
47
45
  assert single_time > multi_time
48
-
49
- server.shutdown
50
- thread.join
51
46
  end
52
47
  end
@@ -22,26 +22,15 @@ end
22
22
  Any insight you care to share would be helpful. Thanks.
23
23
  =end
24
24
  require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
25
- require 'webrick'
26
- class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
27
- class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
28
25
 
29
26
  class BugCurbEasyPostWithStringNoContentLengthHeader < Test::Unit::TestCase
30
- def test_bug_workaround
31
- server = WEBrick::HTTPServer.new( :Port => 9999 )
32
- server.mount_proc("/test") do|req,res|
33
- assert_equal '15', req['Content-Length']
34
- res.body = "hi"
35
- res['Content-Type'] = "text/html"
36
- end
27
+ include BugTestServerSetupTeardown
37
28
 
38
- thread = Thread.new(server) do|srv|
39
- srv.start
40
- end
29
+ def test_bug_workaround
41
30
  params = {:cat => "hat", :foo => "bar"}
42
31
 
43
32
  post_body = params.map{|f,k| "#{Curl::Easy.new.escape(f)}=#{Curl::Easy.new.escape(k)}"}.join('&')
44
- c = Curl::Easy.http_post("http://127.0.0.1:9999/test",post_body) do |curl|
33
+ c = Curl::Easy.http_post("http://127.0.0.1:#{@port}/test",post_body) do |curl|
45
34
  curl.headers["User-Agent"] = "Curl/Ruby"
46
35
  curl.headers["X-Tender-Auth"] = "A Token"
47
36
  curl.headers["Accept"] = "application/vnd.tender-v1+json"
@@ -50,23 +39,12 @@ class BugCurbEasyPostWithStringNoContentLengthHeader < Test::Unit::TestCase
50
39
  curl.enable_cookies = true
51
40
  end
52
41
 
53
- server.shutdown
54
- thread.join
55
42
  end
56
- def test_bug
57
- server = WEBrick::HTTPServer.new( :Port => 9999 )
58
- server.mount_proc("/test") do|req,res|
59
- assert_equal '15', req['Content-Length']
60
- res.body = "hi"
61
- res['Content-Type'] = "text/html"
62
- end
63
43
 
64
- thread = Thread.new(server) do|srv|
65
- srv.start
66
- end
44
+ def test_bug
67
45
  params = {:cat => "hat", :foo => "bar"}
68
46
 
69
- c = Curl::Easy.http_post("http://127.0.0.1:9999/test") do |curl|
47
+ c = Curl::Easy.http_post("http://127.0.0.1:#{@port}/test") do |curl|
70
48
  curl.headers["User-Agent"] = "Curl/Ruby"
71
49
  curl.headers["X-Tender-Auth"] = "A Token"
72
50
  curl.headers["Accept"] = "application/vnd.tender-v1+json"
@@ -76,8 +54,6 @@ class BugCurbEasyPostWithStringNoContentLengthHeader < Test::Unit::TestCase
76
54
  curl.follow_location = true
77
55
  curl.enable_cookies = true
78
56
  end
79
-
80
- server.shutdown
81
- thread.join
82
57
  end
58
+
83
59
  end
@@ -0,0 +1,83 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+
3
+ class BugFollowRedirect288 < Test::Unit::TestCase
4
+ include BugTestServerSetupTeardown
5
+
6
+ def setup
7
+ @port = 9999
8
+ super
9
+ @server.mount_proc("/redirect_to_test") do|req,res|
10
+ res.set_redirect(WEBrick::HTTPStatus::TemporaryRedirect, "/test")
11
+ end
12
+ end
13
+
14
+ def test_follow_redirect_with_no_redirect
15
+
16
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
17
+ did_call_redirect = false
18
+ c.on_redirect do|x|
19
+ did_call_redirect = true
20
+ end
21
+ c.perform
22
+
23
+ assert !did_call_redirect, "should reach this point redirect should not have been called"
24
+
25
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
26
+ did_call_redirect = false
27
+ c.on_redirect do|x|
28
+ did_call_redirect = true
29
+ end
30
+ c.follow_location = true
31
+ c.perform
32
+
33
+ assert_equal 0, c.redirect_count
34
+ assert !did_call_redirect, "should reach this point redirect should not have been called"
35
+
36
+ c = Curl::Easy.new('http://127.0.0.1:9999/redirect_to_test')
37
+ did_call_redirect = false
38
+ c.on_redirect do|x|
39
+ did_call_redirect = true
40
+ end
41
+ c.perform
42
+ assert_equal 307, c.response_code
43
+
44
+ assert did_call_redirect, "we should have called on_redirect"
45
+
46
+ c = Curl::Easy.new('http://127.0.0.1:9999/redirect_to_test')
47
+ did_call_redirect = false
48
+ c.follow_location = true
49
+ # NOTE: while this API is not supported by libcurl e.g. there is no redirect function callback in libcurl we could
50
+ # add support in ruby for this by executing this callback if redirect_count is greater than 0 at the end of a request in curb_multi.c
51
+ c.on_redirect do|x|
52
+ did_call_redirect = true
53
+ end
54
+ c.perform
55
+ assert_equal 1, c.redirect_count
56
+ assert_equal 200, c.response_code
57
+
58
+ assert did_call_redirect, "we should have called on_redirect"
59
+
60
+ c.url = 'http://127.0.0.1:9999/test'
61
+ c.perform
62
+ assert_equal 0, c.redirect_count
63
+ assert_equal 200, c.response_code
64
+
65
+ puts "checking for raise support"
66
+ did_raise = false
67
+ begin
68
+ c = Curl::Easy.new('http://127.0.0.1:9999/redirect_to_test')
69
+ did_call_redirect = false
70
+ c.on_redirect do|x|
71
+ raise "raise"
72
+ did_call_redirect = true
73
+ end
74
+ c.perform
75
+ rescue => e
76
+ did_raise = true
77
+ end
78
+ assert_equal 307, c.response_code
79
+ assert did_raise
80
+
81
+ end
82
+
83
+ end
@@ -35,15 +35,13 @@ class BugTestInstancePostDiffersFromClassPost < Test::Unit::TestCase
35
35
  end
36
36
 
37
37
  def do_test
38
- c = Curl::Easy.http_post('https://www.google.com/accounts/ServiceLoginAuth',
39
- Curl::PostField.content('ltmpl','m_blanco'))
38
+ c = Curl::Easy.http_post('https://www.google.com/accounts/ServiceLoginAuth', Curl::PostField.content('ltmpl','m_blanco'))
40
39
  body_c, header_c = c.body_str, c.header_str
41
40
 
42
41
  sleep 2
43
42
 
44
- c.http_post('https://www.google.com/accounts/ServiceLoginAuth',
45
- Curl::PostField.content('ltmpl','m_blanco'))
46
- body_i, header_i = c.body_str, c.header_str
43
+ c.http_post('https://www.google.com/accounts/ServiceLoginAuth', Curl::PostField.content('ltmpl','m_blanco'))
44
+ body_i, header_i = c.body, c.head
47
45
 
48
46
  # timestamps will differ, just check first bit. We wont get here if
49
47
  # the bug bites anyway...
@@ -3,6 +3,7 @@
3
3
  # irb: multi = Curl::Multi.new
4
4
  # irb: exit
5
5
  # <main>:47140: [BUG] Bus Error
6
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
6
7
  $:.unshift File.expand_path(File.join(File.dirname(__FILE__),'..','ext'))
7
8
  $:.unshift File.expand_path(File.join(File.dirname(__FILE__),'..','lib'))
8
9
  require 'curb'
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+
3
+ class BugRaiseOnCallback < Test::Unit::TestCase
4
+ include BugTestServerSetupTeardown
5
+
6
+ def setup
7
+ @port = 9999
8
+ super
9
+ end
10
+
11
+ def test_on_complte
12
+ c = Curl::Easy.new('http://127.0.0.1:9999/test')
13
+ did_raise = false
14
+ begin
15
+ c.on_complete do|x|
16
+ assert_equal 'http://127.0.0.1:9999/test', x.url
17
+ raise "error complete" # this will get swallowed
18
+ end
19
+ c.perform
20
+ rescue => e
21
+ did_raise = true
22
+ end
23
+ assert did_raise, "we want to raise an exception if the ruby callbacks raise"
24
+
25
+ end
26
+
27
+ end
28
+
29
+ #test_on_debug
data/tests/helper.rb CHANGED
@@ -135,6 +135,32 @@ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
135
135
 
136
136
  end
137
137
 
138
+ module BugTestServerSetupTeardown
139
+ def setup
140
+ @port ||= 9992
141
+ @server = WEBrick::HTTPServer.new( :Port => @port )
142
+ @server.mount_proc("/test") do|req,res|
143
+ if @response_proc
144
+ @response_proc.call(res)
145
+ else
146
+ res.body = "hi"
147
+ res['Content-Type'] = "text/html"
148
+ end
149
+ end
150
+
151
+ @thread = Thread.new(@server) do|srv|
152
+ srv.start
153
+ end
154
+ end
155
+
156
+ def teardown
157
+ while @server.status != :Shutdown
158
+ @server.shutdown
159
+ end
160
+ @thread.join
161
+ end
162
+ end
163
+
138
164
  module TestServerMethods
139
165
  def locked_file
140
166
  File.join(File.dirname(__FILE__),"server_lock-#{@__port}")
@@ -13,9 +13,9 @@ class TestCurbCurlEasy < Test::Unit::TestCase
13
13
  def test_nested_easy_methods
14
14
  easy = Curl.get(TestServlet.url) {|http|
15
15
  res = Curl.get(TestServlet.url + '/not_here')
16
- assert_equal 404, res.response_code
16
+ assert_equal 404, res.code
17
17
  }
18
- assert_equal 200, easy.response_code
18
+ assert_equal 200, easy.code
19
19
  end
20
20
 
21
21
  def test_curlopt_stderr_with_file
@@ -721,9 +721,9 @@ class TestCurbCurlEasy < Test::Unit::TestCase
721
721
  on_success_called = false
722
722
  curl.on_success {|c|
723
723
  on_success_called = true
724
- assert_not_nil c.body_str
725
- assert_equal "", c.header_str
726
- assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body_str)
724
+ assert_not_nil c.body
725
+ assert_match(/Content-Length: /, c.head)
726
+ assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.body)
727
727
  }
728
728
  curl.perform
729
729
  assert on_success_called, "Success handler not called"
@@ -1147,7 +1147,7 @@ class TestCurbCurlEasy < Test::Unit::TestCase
1147
1147
  c = Curl::Easy.new($TEST_URL)
1148
1148
  c.on_success {|x| raise "error" }
1149
1149
  c.perform
1150
- rescue => e
1150
+ rescue Curl::Err::AbortedByCallbackError => e
1151
1151
  assert_equal 'Curl::Err::AbortedByCallbackError', e.class.to_s
1152
1152
  c.close
1153
1153
  end
@@ -74,7 +74,9 @@ class TestCurbCurlMulti < Test::Unit::TestCase
74
74
  assert did_complete
75
75
  after_open = open_fds.call
76
76
  #puts "after_open: #{after_open} before_open: #{before_open.inspect}"
77
- assert_equal 1, (after_open - before_open), "with max connections set to 1 at this point the connection to google should still be open"
77
+ # ruby process may keep a connection alive
78
+ assert (after_open - before_open) < 3, "with max connections set to 1 at this point the connection to google should still be open"
79
+ assert (after_open - before_open) > 0, "with max connections set to 1 at this point the connection to google should still be open"
78
80
  multi.close
79
81
 
80
82
  after_open = open_fds.call
@@ -159,6 +161,44 @@ class TestCurbCurlMulti < Test::Unit::TestCase
159
161
 
160
162
  end
161
163
 
164
+ def test_multi_easy_get
165
+ n = 1
166
+ urls = []
167
+ n.times { urls << $TEST_URL }
168
+ Curl::Multi.get(urls, {timeout: 5}) {|easy|
169
+ assert_match(/file:/, easy.last_effective_url)
170
+ }
171
+ end
172
+
173
+ def test_multi_easy_get_with_error
174
+ begin
175
+ did_raise = false
176
+ n = 3
177
+ urls = []
178
+ n.times { urls << $TEST_URL }
179
+ error_line_number_should_be = nil
180
+ Curl::Multi.get(urls, {timeout: 5}) {|easy|
181
+ # if we got this right the error will be reported to be on the line below our error_line_number_should_be
182
+ error_line_number_should_be = __LINE__
183
+ raise
184
+ }
185
+
186
+ rescue Curl::Err::AbortedByCallbackError => e
187
+ did_raise = true
188
+ in_file = e.backtrace.detect {|err| err.match?(File.basename(__FILE__)) }
189
+ in_file_stack = e.backtrace.select {|err| err.match?(File.basename(__FILE__)) }
190
+ assert_match(__FILE__, in_file)
191
+ in_file.gsub!(__FILE__)
192
+ parts = in_file.split(':')
193
+ parts.shift
194
+ line_no = parts.shift.to_i
195
+ assert_equal error_line_number_should_be+1, line_no.to_i
196
+ end
197
+
198
+ assert did_raise, "we should have raised an exception"
199
+
200
+ end
201
+
162
202
  # NOTE: if this test runs slowly on Mac OSX, it is probably due to the use of a port install curl+ssl+ares install
163
203
  # on my MacBook, this causes curl_easy_init to take nearly 0.01 seconds / * 100 below is 1 second too many!
164
204
  def test_n_requests
@@ -480,7 +520,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
480
520
  { :url => TestServlet.url, :method => :get }
481
521
  ]
482
522
  Curl::Multi.http(urls, {:pipeline => true}) do|easy, code, method|
483
- assert_equal nil, code
523
+ assert_equal 200, code
484
524
  case method
485
525
  when :post
486
526
  assert_match(/POST/, easy.body_str)
@@ -494,20 +534,20 @@ class TestCurbCurlMulti < Test::Unit::TestCase
494
534
  end
495
535
 
496
536
  def test_multi_easy_http_with_max_connects
497
- urls = [
537
+ urls = [
498
538
  { :url => TestServlet.url + '?q=1', :method => :get },
499
539
  { :url => TestServlet.url + '?q=2', :method => :get },
500
540
  { :url => TestServlet.url + '?q=3', :method => :get }
501
541
  ]
502
542
  Curl::Multi.http(urls, {:pipeline => true, :max_connects => 1}) do|easy, code, method|
503
- assert_equal nil, code
543
+ assert_equal 200, code
504
544
  case method
505
545
  when :post
506
- assert_match(/POST/, easy.body_str)
546
+ assert_match(/POST/, easy.body)
507
547
  when :get
508
- assert_match(/GET/, easy.body_str)
548
+ assert_match(/GET/, easy.body)
509
549
  when :put
510
- assert_match(/PUT/, easy.body_str)
550
+ assert_match(/PUT/, easy.body)
511
551
  end
512
552
  end
513
553
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: curb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ross Bamford
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-04-29 00:00:00.000000000 Z
12
+ date: 2023-01-04 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Curb (probably CUrl-RuBy or something) provides Ruby-language bindings
15
15
  for the libcurl(3), a fully-featured client-side URL transfer library. cURL and
@@ -50,12 +50,14 @@ files:
50
50
  - tests/bug_crash_on_progress.rb
51
51
  - tests/bug_curb_easy_blocks_ruby_threads.rb
52
52
  - tests/bug_curb_easy_post_with_string_no_content_length_header.rb
53
+ - tests/bug_follow_redirect_288.rb
53
54
  - tests/bug_instance_post_differs_from_class_post.rb
54
55
  - tests/bug_issue102.rb
55
56
  - tests/bug_issue277.rb
56
57
  - tests/bug_multi_segfault.rb
57
58
  - tests/bug_postfields_crash.rb
58
59
  - tests/bug_postfields_crash2.rb
60
+ - tests/bug_raise_on_callback.rb
59
61
  - tests/bug_require_last_or_segfault.rb
60
62
  - tests/bugtests.rb
61
63
  - tests/helper.rb
@@ -96,37 +98,39 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
98
  - !ruby/object:Gem::Version
97
99
  version: '0'
98
100
  requirements: []
99
- rubygems_version: 3.1.4
101
+ rubygems_version: 3.2.33
100
102
  signing_key:
101
103
  specification_version: 4
102
104
  summary: Ruby libcurl bindings
103
105
  test_files:
104
- - tests/tc_curl_multi.rb
105
106
  - tests/alltests.rb
106
- - tests/tc_curl_easy_setopt.rb
107
- - tests/tc_curl.rb
108
- - tests/bug_postfields_crash.rb
107
+ - tests/bug_crash_on_debug.rb
109
108
  - tests/bug_crash_on_progress.rb
110
- - tests/helper.rb
109
+ - tests/bug_curb_easy_blocks_ruby_threads.rb
110
+ - tests/bug_curb_easy_post_with_string_no_content_length_header.rb
111
+ - tests/bug_follow_redirect_288.rb
112
+ - tests/bug_instance_post_differs_from_class_post.rb
113
+ - tests/bug_issue102.rb
111
114
  - tests/bug_issue277.rb
115
+ - tests/bug_multi_segfault.rb
116
+ - tests/bug_postfields_crash.rb
112
117
  - tests/bug_postfields_crash2.rb
118
+ - tests/bug_raise_on_callback.rb
113
119
  - tests/bug_require_last_or_segfault.rb
114
- - tests/timeout.rb
115
- - tests/bug_crash_on_debug.rb
116
- - tests/unittests.rb
117
- - tests/tc_curl_protocols.rb
118
- - tests/bug_issue102.rb
119
- - tests/bug_curb_easy_blocks_ruby_threads.rb
120
- - tests/bug_multi_segfault.rb
121
- - tests/bug_instance_post_differs_from_class_post.rb
120
+ - tests/bugtests.rb
121
+ - tests/helper.rb
122
+ - tests/mem_check.rb
122
123
  - tests/require_last_or_segfault_script.rb
123
- - tests/timeout_server.rb
124
+ - tests/signals.rb
125
+ - tests/tc_curl.rb
124
126
  - tests/tc_curl_download.rb
125
127
  - tests/tc_curl_easy.rb
126
- - tests/mem_check.rb
127
- - tests/tc_curl_postfield.rb
128
- - tests/tc_curl_maxfilesize.rb
129
- - tests/bugtests.rb
130
128
  - tests/tc_curl_easy_resolve.rb
131
- - tests/signals.rb
132
- - tests/bug_curb_easy_post_with_string_no_content_length_header.rb
129
+ - tests/tc_curl_easy_setopt.rb
130
+ - tests/tc_curl_maxfilesize.rb
131
+ - tests/tc_curl_multi.rb
132
+ - tests/tc_curl_postfield.rb
133
+ - tests/tc_curl_protocols.rb
134
+ - tests/timeout.rb
135
+ - tests/timeout_server.rb
136
+ - tests/unittests.rb