curb 0.9.11 → 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 +4 -4
- data/README.markdown +48 -6
- data/Rakefile +17 -18
- data/ext/curb.c +154 -8
- data/ext/curb.h +10 -5
- data/ext/curb_easy.c +100 -44
- data/ext/curb_easy.h +3 -0
- data/ext/curb_macros.h +12 -0
- data/ext/curb_multi.c +50 -24
- data/ext/curb_postfield.c +9 -7
- data/ext/curb_upload.c +1 -0
- data/ext/extconf.rb +38 -0
- data/lib/curl/easy.rb +8 -7
- data/lib/curl/multi.rb +8 -1
- data/lib/curl.rb +11 -3
- 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 -1
- data/tests/tc_curl_easy.rb +13 -5
- data/tests/tc_curl_multi.rb +98 -17
- data/tests/tc_curl_protocols.rb +37 -0
- data/tests/timeout.rb +21 -5
- metadata +28 -22
data/tests/tc_curl_multi.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
|
+
require 'set'
|
2
3
|
|
3
4
|
class TestCurbCurlMulti < Test::Unit::TestCase
|
4
5
|
def teardown
|
@@ -9,20 +10,58 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
9
10
|
# for https://github.com/taf2/curb/issues/277
|
10
11
|
# must connect to an external
|
11
12
|
def test_connection_keepalive
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
# this test fails with libcurl 7.22.0. I didn't investigate, but it may be related
|
14
|
+
# to CURLOPT_MAXCONNECTS bug fixed in 7.30.0:
|
15
|
+
# https://github.com/curl/curl/commit/e87e76e2dc108efb1cae87df496416f49c55fca0
|
16
|
+
omit("Skip, libcurl too old (< 7.22.0)") if Curl::CURL_VERSION.split('.')[1].to_i <= 22
|
17
|
+
|
18
|
+
@server.shutdown if @server
|
19
|
+
@test_thread.kill if @test_thread
|
20
|
+
@server = nil
|
21
|
+
File.unlink(locked_file)
|
22
|
+
Curl::Multi.autoclose = true
|
23
|
+
assert Curl::Multi.autoclose
|
24
|
+
# XXX: thought maybe we can clean house here to have the full suite pass in osx... but for now running this test in isolate does pass
|
25
|
+
# additionally, if ss allows this to pass on linux without requesting google i think this is a good trade off... leaving some of the thoughts below
|
26
|
+
# in hopes that coming back to this later will find it and remember how to fix it
|
27
|
+
# types = Set.new
|
28
|
+
# close_types = Set.new([TCPServer,TCPSocket,Socket,Curl::Multi, Curl::Easy,WEBrick::Log])
|
29
|
+
# ObjectSpace.each_object {|o|
|
30
|
+
# if o.respond_to?(:close)
|
31
|
+
# types << o.class
|
32
|
+
# end
|
33
|
+
# if close_types.include?(o.class)
|
34
|
+
# o.close
|
35
|
+
# end
|
36
|
+
# }
|
37
|
+
#puts "unique types: #{types.to_a.join("\n")}"
|
38
|
+
GC.start # cleanup FDs left over from other tests
|
39
|
+
server_setup
|
40
|
+
GC.start # cleanup FDs left over from other tests
|
41
|
+
|
42
|
+
if `which ss`.strip.size == 0
|
43
|
+
# osx need lsof still :(
|
44
|
+
open_fds = lambda do
|
45
|
+
out = `/usr/sbin/lsof -p #{Process.pid} | egrep "TCP|UDP"`# | egrep ':#{TestServlet.port} ' | egrep ESTABLISHED`# | wc -l`.strip.to_i
|
46
|
+
#puts out.lines.join("\n")
|
47
|
+
out.lines.size
|
48
|
+
end
|
49
|
+
else
|
50
|
+
ss = `which ss`.strip
|
51
|
+
open_fds = lambda do
|
52
|
+
`#{ss} -n4 state established dport = :#{TestServlet.port} | wc -l`.strip.to_i
|
53
|
+
end
|
16
54
|
end
|
55
|
+
Curl::Multi.autoclose = false
|
17
56
|
before_open = open_fds.call
|
57
|
+
#puts "before_open: #{before_open.inspect}"
|
18
58
|
assert !Curl::Multi.autoclose
|
19
59
|
multi = Curl::Multi.new
|
20
60
|
multi.max_connects = 1 # limit to 1 connection within the multi handle
|
21
61
|
|
22
62
|
did_complete = false
|
23
63
|
5.times do |n|
|
24
|
-
|
25
|
-
easy = Curl::Easy.new("http://google.com/") do |curl|
|
64
|
+
easy = Curl::Easy.new(TestServlet.url) do |curl|
|
26
65
|
curl.timeout = 5 # ensure we don't hang for ever connecting to an external host
|
27
66
|
curl.on_complete {
|
28
67
|
did_complete = true
|
@@ -34,18 +73,21 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
34
73
|
multi.perform
|
35
74
|
assert did_complete
|
36
75
|
after_open = open_fds.call
|
37
|
-
|
76
|
+
#puts "after_open: #{after_open} before_open: #{before_open.inspect}"
|
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"
|
38
80
|
multi.close
|
39
81
|
|
40
82
|
after_open = open_fds.call
|
41
|
-
|
83
|
+
#puts "after_open: #{after_open} before_open: #{before_open.inspect}"
|
84
|
+
assert_equal 0, (after_open - before_open), "after closing the multi handle all connections should be closed"
|
42
85
|
|
43
86
|
Curl::Multi.autoclose = true
|
44
87
|
multi = Curl::Multi.new
|
45
88
|
did_complete = false
|
46
89
|
5.times do |n|
|
47
|
-
|
48
|
-
easy = Curl::Easy.new("http://google.com/") do |curl|
|
90
|
+
easy = Curl::Easy.new(TestServlet.url) do |curl|
|
49
91
|
curl.timeout = 5 # ensure we don't hang for ever connecting to an external host
|
50
92
|
curl.on_complete {
|
51
93
|
did_complete = true
|
@@ -57,7 +99,8 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
57
99
|
multi.perform
|
58
100
|
assert did_complete
|
59
101
|
after_open = open_fds.call
|
60
|
-
|
102
|
+
#puts "after_open: #{after_open} before_open: #{before_open.inspect}"
|
103
|
+
assert_equal 0, (after_open - before_open), "auto close the connections"
|
61
104
|
ensure
|
62
105
|
Curl::Multi.autoclose = false # restore default
|
63
106
|
end
|
@@ -118,6 +161,44 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
118
161
|
|
119
162
|
end
|
120
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
|
+
|
121
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
|
122
203
|
# on my MacBook, this causes curl_easy_init to take nearly 0.01 seconds / * 100 below is 1 second too many!
|
123
204
|
def test_n_requests
|
@@ -439,7 +520,7 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
439
520
|
{ :url => TestServlet.url, :method => :get }
|
440
521
|
]
|
441
522
|
Curl::Multi.http(urls, {:pipeline => true}) do|easy, code, method|
|
442
|
-
assert_equal
|
523
|
+
assert_equal 200, code
|
443
524
|
case method
|
444
525
|
when :post
|
445
526
|
assert_match(/POST/, easy.body_str)
|
@@ -453,20 +534,20 @@ class TestCurbCurlMulti < Test::Unit::TestCase
|
|
453
534
|
end
|
454
535
|
|
455
536
|
def test_multi_easy_http_with_max_connects
|
456
|
-
|
537
|
+
urls = [
|
457
538
|
{ :url => TestServlet.url + '?q=1', :method => :get },
|
458
539
|
{ :url => TestServlet.url + '?q=2', :method => :get },
|
459
540
|
{ :url => TestServlet.url + '?q=3', :method => :get }
|
460
541
|
]
|
461
542
|
Curl::Multi.http(urls, {:pipeline => true, :max_connects => 1}) do|easy, code, method|
|
462
|
-
assert_equal
|
543
|
+
assert_equal 200, code
|
463
544
|
case method
|
464
545
|
when :post
|
465
|
-
assert_match(/POST/, easy.
|
546
|
+
assert_match(/POST/, easy.body)
|
466
547
|
when :get
|
467
|
-
assert_match(/GET/, easy.
|
548
|
+
assert_match(/GET/, easy.body)
|
468
549
|
when :put
|
469
|
-
assert_match(/PUT/, easy.
|
550
|
+
assert_match(/PUT/, easy.body)
|
470
551
|
end
|
471
552
|
end
|
472
553
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class TestCurbCurlProtocols < Test::Unit::TestCase
|
2
|
+
include TestServerMethods
|
3
|
+
|
4
|
+
def setup
|
5
|
+
@easy = Curl::Easy.new
|
6
|
+
@easy.set :protocols, Curl::CURLPROTO_HTTP | Curl::CURLPROTO_HTTPS
|
7
|
+
@easy.follow_location = true
|
8
|
+
server_setup
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_protocol_allowed
|
12
|
+
@easy.set :url, "http://127.0.0.1:9129/this_file_does_not_exist.html"
|
13
|
+
@easy.perform
|
14
|
+
assert_equal 404, @easy.response_code
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_protocol_denied
|
18
|
+
@easy.set :url, "gopher://google.com/"
|
19
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
20
|
+
@easy.perform
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_redir_protocol_allowed
|
25
|
+
@easy.set :url, TestServlet.url + "/redirect"
|
26
|
+
@easy.set :redir_protocols, Curl::CURLPROTO_HTTP
|
27
|
+
@easy.perform
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_redir_protocol_denied
|
31
|
+
@easy.set :url, TestServlet.url + "/redirect"
|
32
|
+
@easy.set :redir_protocols, Curl::CURLPROTO_HTTPS
|
33
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
34
|
+
@easy.perform
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/tests/timeout.rb
CHANGED
@@ -17,9 +17,13 @@ class TestCurbTimeouts < Test::Unit::TestCase
|
|
17
17
|
def test_overall_timeout_on_dead_transfer
|
18
18
|
curl = Curl::Easy.new(wait_url(2))
|
19
19
|
curl.timeout = 1
|
20
|
-
assert_raise(Curl::Err::TimeoutError) do
|
20
|
+
exception = assert_raise(Curl::Err::TimeoutError) do
|
21
21
|
curl.http_get
|
22
22
|
end
|
23
|
+
assert_match(
|
24
|
+
/^Timeout was reached: Operation timed out after/,
|
25
|
+
exception.message
|
26
|
+
)
|
23
27
|
end
|
24
28
|
|
25
29
|
def test_overall_timeout_ms_on_dead_transfer
|
@@ -44,16 +48,20 @@ class TestCurbTimeouts < Test::Unit::TestCase
|
|
44
48
|
curl = Curl::Easy.new(serve_url(100, 2, 3))
|
45
49
|
curl.timeout = 1
|
46
50
|
# transfer is aborted despite data being exchanged
|
47
|
-
assert_raise(Curl::Err::TimeoutError) do
|
51
|
+
exception = assert_raise(Curl::Err::TimeoutError) do
|
48
52
|
curl.http_get
|
49
53
|
end
|
54
|
+
assert_match(
|
55
|
+
/^Timeout was reached: Operation timed out after/,
|
56
|
+
exception.message
|
57
|
+
)
|
50
58
|
end
|
51
59
|
|
52
60
|
def test_low_speed_time_on_slow_transfer
|
53
61
|
curl = Curl::Easy.new(serve_url(100, 1, 3))
|
54
62
|
curl.low_speed_time = 2
|
55
63
|
# use default low_speed_limit of 1
|
56
|
-
|
64
|
+
assert_equal true, curl.http_get
|
57
65
|
end
|
58
66
|
|
59
67
|
def test_low_speed_time_on_very_slow_transfer
|
@@ -63,18 +71,26 @@ class TestCurbTimeouts < Test::Unit::TestCase
|
|
63
71
|
# XXX for some reason this test fails if low speed limit is not specified
|
64
72
|
curl.low_speed_limit = 1
|
65
73
|
# use default low_speed_limit of 1
|
66
|
-
assert_raise(Curl::Err::TimeoutError) do
|
74
|
+
exception = assert_raise(Curl::Err::TimeoutError) do
|
67
75
|
curl.http_get
|
68
76
|
end
|
77
|
+
assert_match(
|
78
|
+
/^Timeout was reached: Operation too slow/,
|
79
|
+
exception.message
|
80
|
+
)
|
69
81
|
end
|
70
82
|
|
71
83
|
def test_low_speed_limit_on_slow_transfer
|
72
84
|
curl = Curl::Easy.new(serve_url(10, 1, 3))
|
73
85
|
curl.low_speed_time = 2
|
74
86
|
curl.low_speed_limit = 1000
|
75
|
-
assert_raise(Curl::Err::TimeoutError) do
|
87
|
+
exception = assert_raise(Curl::Err::TimeoutError) do
|
76
88
|
curl.http_get
|
77
89
|
end
|
90
|
+
assert_match(
|
91
|
+
/^Timeout was reached: Operation too slow/,
|
92
|
+
exception.message
|
93
|
+
)
|
78
94
|
end
|
79
95
|
|
80
96
|
def test_clearing_low_speed_time
|
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: 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
|
@@ -70,6 +72,7 @@ files:
|
|
70
72
|
- tests/tc_curl_maxfilesize.rb
|
71
73
|
- tests/tc_curl_multi.rb
|
72
74
|
- tests/tc_curl_postfield.rb
|
75
|
+
- tests/tc_curl_protocols.rb
|
73
76
|
- tests/timeout.rb
|
74
77
|
- tests/timeout_server.rb
|
75
78
|
- tests/unittests.rb
|
@@ -95,36 +98,39 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
98
|
- !ruby/object:Gem::Version
|
96
99
|
version: '0'
|
97
100
|
requirements: []
|
98
|
-
rubygems_version: 3.
|
101
|
+
rubygems_version: 3.2.33
|
99
102
|
signing_key:
|
100
103
|
specification_version: 4
|
101
104
|
summary: Ruby libcurl bindings
|
102
105
|
test_files:
|
103
|
-
- tests/tc_curl_multi.rb
|
104
106
|
- tests/alltests.rb
|
105
|
-
- tests/
|
106
|
-
- tests/tc_curl.rb
|
107
|
-
- tests/bug_postfields_crash.rb
|
107
|
+
- tests/bug_crash_on_debug.rb
|
108
108
|
- tests/bug_crash_on_progress.rb
|
109
|
-
- 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
|
110
114
|
- tests/bug_issue277.rb
|
115
|
+
- tests/bug_multi_segfault.rb
|
116
|
+
- tests/bug_postfields_crash.rb
|
111
117
|
- tests/bug_postfields_crash2.rb
|
118
|
+
- tests/bug_raise_on_callback.rb
|
112
119
|
- tests/bug_require_last_or_segfault.rb
|
113
|
-
- tests/
|
114
|
-
- tests/
|
115
|
-
- tests/
|
116
|
-
- tests/bug_issue102.rb
|
117
|
-
- tests/bug_curb_easy_blocks_ruby_threads.rb
|
118
|
-
- tests/bug_multi_segfault.rb
|
119
|
-
- tests/bug_instance_post_differs_from_class_post.rb
|
120
|
+
- tests/bugtests.rb
|
121
|
+
- tests/helper.rb
|
122
|
+
- tests/mem_check.rb
|
120
123
|
- tests/require_last_or_segfault_script.rb
|
121
|
-
- tests/
|
124
|
+
- tests/signals.rb
|
125
|
+
- tests/tc_curl.rb
|
122
126
|
- tests/tc_curl_download.rb
|
123
127
|
- tests/tc_curl_easy.rb
|
124
|
-
- tests/mem_check.rb
|
125
|
-
- tests/tc_curl_postfield.rb
|
126
|
-
- tests/tc_curl_maxfilesize.rb
|
127
|
-
- tests/bugtests.rb
|
128
128
|
- tests/tc_curl_easy_resolve.rb
|
129
|
-
- tests/
|
130
|
-
- 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
|