curb 1.0.1 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.markdown +22 -9
- data/Rakefile +9 -7
- data/ext/curb.c +4 -0
- data/ext/curb.h +3 -3
- data/ext/curb_easy.c +26 -19
- data/ext/curb_macros.h +12 -0
- data/ext/curb_multi.c +40 -14
- data/ext/curb_postfield.c +2 -0
- data/ext/curb_upload.c +1 -0
- data/ext/extconf.rb +2 -0
- data/lib/curl/multi.rb +8 -1
- data/tests/bug_crash_on_debug.rb +14 -28
- data/tests/bug_crash_on_progress.rb +7 -31
- data/tests/bug_curb_easy_blocks_ruby_threads.rb +8 -13
- data/tests/bug_curb_easy_post_with_string_no_content_length_header.rb +6 -30
- data/tests/bug_follow_redirect_288.rb +83 -0
- data/tests/bug_instance_post_differs_from_class_post.rb +3 -5
- data/tests/bug_multi_segfault.rb +1 -0
- data/tests/bug_raise_on_callback.rb +29 -0
- data/tests/helper.rb +26 -0
- data/tests/tc_curl_easy.rb +6 -6
- data/tests/tc_curl_multi.rb +47 -7
- metadata +27 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e28b1d05b46460867acfadc87bbe422d58d8f2cdb93397fa6ded906b01cd7dab
|
4
|
+
data.tar.gz: 33e7037c1c2b23a793ec96c73bc80c008939c880702f884d2b258d4afd18c368
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6eb448726a4fdce1e0832e36a45b2c8e0a078fbc2c04b3fe34f87fc38397f5c4ecc4fe621aed5637750c5c7a7a9d05b30c03f9f7db153c23d3694eb6adb464e8
|
7
|
+
data.tar.gz: 624e3f39af79eff874784a662776debc2b405378c6cdc963a50dee525d36aa225cc5f40558f9b35b396c222416006f66c29fc6193e651b5aa84093fdd52cb2ba
|
data/README.markdown
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
# Curb - Libcurl bindings for Ruby
|
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
|
-
|
20
|
+
GET request
|
20
21
|
```
|
21
|
-
res = Curl.get("https://www.google.com/")
|
22
|
-
|
23
|
-
|
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
|
-
|
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.
|
33
|
-
puts res.
|
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.
|
32
|
-
#define CURB_VER_NUM
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
47
|
-
|
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
|
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
|
-
|
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
|
-
|
338
|
+
rb_rescue(call_status_handler2, callargs, callback_exception, did_raise);
|
317
339
|
rbce->callback_active = 0;
|
318
|
-
|
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
|
-
|
347
|
+
rb_rescue(call_status_handler1, callargs, callback_exception, did_raise);
|
326
348
|
rbce->callback_active = 0;
|
327
|
-
|
328
|
-
|
329
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
368
|
+
rb_rescue(call_status_handler2, callargs, callback_exception, did_raise);
|
345
369
|
rbce->callback_active = 0;
|
346
|
-
|
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
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
|
-
|
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
|
|
data/tests/bug_crash_on_debug.rb
CHANGED
@@ -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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
28
|
-
|
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
|
-
|
16
|
-
|
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(
|
33
|
+
c = Curl::Easy.new("http://127.0.0.1:#{@port}/test")
|
34
|
+
did_progress = false
|
58
35
|
c.on_progress do|x|
|
59
|
-
|
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
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
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...
|
data/tests/bug_multi_segfault.rb
CHANGED
@@ -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}")
|
data/tests/tc_curl_easy.rb
CHANGED
@@ -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.
|
16
|
+
assert_equal 404, res.code
|
17
17
|
}
|
18
|
-
assert_equal 200, easy.
|
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.
|
725
|
-
|
726
|
-
assert_match(/^# DO NOT REMOVE THIS COMMENT/, c.
|
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
|
data/tests/tc_curl_multi.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
-
|
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
|
543
|
+
assert_equal 200, code
|
504
544
|
case method
|
505
545
|
when :post
|
506
|
-
assert_match(/POST/, easy.
|
546
|
+
assert_match(/POST/, easy.body)
|
507
547
|
when :get
|
508
|
-
assert_match(/GET/, easy.
|
548
|
+
assert_match(/GET/, easy.body)
|
509
549
|
when :put
|
510
|
-
assert_match(/PUT/, easy.
|
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.
|
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:
|
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.
|
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/
|
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/
|
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/
|
115
|
-
- tests/
|
116
|
-
- tests/
|
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/
|
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/
|
132
|
-
- tests/
|
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
|