curb 1.3.4 → 1.3.6
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.md +57 -0
- data/Rakefile +24 -2
- data/doc.rb +48 -8
- data/ext/curb.c +24 -0
- data/ext/curb.h +3 -3
- data/ext/curb_easy.c +1378 -55
- data/ext/curb_easy.h +26 -0
- data/ext/curb_errors.c +2 -0
- data/ext/curb_errors.h +1 -0
- data/ext/curb_multi.c +330 -74
- data/ext/curb_multi.h +1 -0
- data/ext/extconf.rb +9 -0
- data/lib/curl/download.rb +160 -0
- data/lib/curl/easy.rb +113 -13
- data/lib/curl/multi.rb +172 -39
- data/lib/curl.rb +471 -11
- data/tests/bug_poison.rb +29 -0
- data/tests/tc_curl_download.rb +86 -0
- data/tests/tc_curl_easy.rb +76 -0
- data/tests/tc_curl_maxfilesize.rb +201 -1
- data/tests/tc_curl_multi.rb +293 -0
- data/tests/tc_curl_network_policy.rb +1475 -0
- data/tests/tc_curl_protocols.rb +351 -0
- data/tests/tc_fiber_scheduler.rb +64 -5
- metadata +8 -3
data/tests/tc_curl_protocols.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
|
2
|
+
|
|
1
3
|
class TestCurbCurlProtocols < Test::Unit::TestCase
|
|
2
4
|
include TestServerMethods
|
|
3
5
|
|
|
@@ -8,6 +10,11 @@ class TestCurbCurlProtocols < Test::Unit::TestCase
|
|
|
8
10
|
server_setup
|
|
9
11
|
end
|
|
10
12
|
|
|
13
|
+
def teardown
|
|
14
|
+
Curl.__send__(:clear_safe!) if Curl.respond_to?(:clear_safe!, true)
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
11
18
|
def test_protocol_allowed
|
|
12
19
|
@easy.set :url, "http://127.0.0.1:9129/this_file_does_not_exist.html"
|
|
13
20
|
@easy.perform
|
|
@@ -34,4 +41,348 @@ class TestCurbCurlProtocols < Test::Unit::TestCase
|
|
|
34
41
|
@easy.perform
|
|
35
42
|
end
|
|
36
43
|
end
|
|
44
|
+
|
|
45
|
+
def test_protocols_str_setopt_supported
|
|
46
|
+
omit('CURLOPT_PROTOCOLS_STR not supported by this libcurl') unless Curl.const_defined?(:CURLOPT_PROTOCOLS_STR)
|
|
47
|
+
|
|
48
|
+
@easy.set :protocols_str, 'http,https'
|
|
49
|
+
@easy.set :url, "http://127.0.0.1:9129/this_file_does_not_exist.html"
|
|
50
|
+
@easy.perform
|
|
51
|
+
assert_equal 404, @easy.response_code
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_redir_protocols_str_setopt_supported
|
|
55
|
+
omit('CURLOPT_REDIR_PROTOCOLS_STR not supported by this libcurl') unless Curl.const_defined?(:CURLOPT_REDIR_PROTOCOLS_STR)
|
|
56
|
+
|
|
57
|
+
@easy.set :url, TestServlet.url + "/redirect"
|
|
58
|
+
@easy.set :redir_protocols_str, 'https'
|
|
59
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
|
60
|
+
@easy.perform
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_allowed_protocols_denies_file_protocol
|
|
65
|
+
easy = Curl::Easy.new($TEST_URL)
|
|
66
|
+
easy.allowed_protocols = [:http, :https]
|
|
67
|
+
|
|
68
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
|
69
|
+
easy.perform
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_safe_http_denies_file_protocol
|
|
74
|
+
easy = Curl::Easy.new($TEST_URL)
|
|
75
|
+
easy.safe_http!
|
|
76
|
+
|
|
77
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
|
78
|
+
easy.perform
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_safe_http_override_is_cleared_by_close
|
|
83
|
+
easy = Curl::Easy.new($TEST_URL)
|
|
84
|
+
easy.safe_http!
|
|
85
|
+
easy.close
|
|
86
|
+
easy.url = $TEST_URL
|
|
87
|
+
|
|
88
|
+
easy.perform
|
|
89
|
+
|
|
90
|
+
assert_match(/TESTMODEL/, easy.body_str)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_safe_get_denies_file_protocol
|
|
94
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
|
95
|
+
Curl.safe_get($TEST_URL)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_safe_get_reapplies_protocols_after_user_block
|
|
100
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
|
101
|
+
Curl.safe_get($TEST_URL) do |easy|
|
|
102
|
+
easy.allowed_protocols = [:file]
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def test_safe_get_allows_http_protocol
|
|
108
|
+
easy = Curl.safe_get(TestServlet.url)
|
|
109
|
+
|
|
110
|
+
assert_equal 200, easy.response_code
|
|
111
|
+
assert_match(/GET/, easy.body_str)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_safe_bang_denies_file_protocol_for_easy_perform
|
|
115
|
+
Curl.safe!
|
|
116
|
+
easy = Curl::Easy.new($TEST_URL)
|
|
117
|
+
|
|
118
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
|
119
|
+
easy.perform
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_safe_bang_denies_file_protocol_for_shortcut_helpers
|
|
124
|
+
Curl.safe!
|
|
125
|
+
|
|
126
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
|
127
|
+
Curl.get($TEST_URL)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def test_safe_bang_reapplies_protocols_after_shortcut_block
|
|
132
|
+
Curl.safe!
|
|
133
|
+
|
|
134
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
|
135
|
+
Curl.get($TEST_URL) do |easy|
|
|
136
|
+
easy.allowed_protocols = [:file]
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def test_safe_bang_allows_configured_protocols
|
|
142
|
+
Curl.safe! do |config|
|
|
143
|
+
config.protocols = [:http, :file]
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
easy = Curl::Easy.new($TEST_URL)
|
|
147
|
+
easy.perform
|
|
148
|
+
|
|
149
|
+
assert_match(/DO NOT REMOVE THIS COMMENT/, easy.body_str)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def test_safe_get_remains_http_safe_with_broader_global_policy
|
|
153
|
+
Curl.safe! do |config|
|
|
154
|
+
config.protocols = [:http, :file]
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
|
158
|
+
Curl.safe_get($TEST_URL)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def test_safe_bang_allows_http_protocol
|
|
163
|
+
Curl.safe!
|
|
164
|
+
easy = Curl.get(TestServlet.url)
|
|
165
|
+
|
|
166
|
+
assert_equal 200, easy.response_code
|
|
167
|
+
assert_match(/GET/, easy.body_str)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def test_safe_bang_applies_to_multi_perform
|
|
171
|
+
Curl.safe!
|
|
172
|
+
easy = Curl::Easy.new($TEST_URL)
|
|
173
|
+
multi = Curl::Multi.new
|
|
174
|
+
|
|
175
|
+
multi.add(easy)
|
|
176
|
+
multi.perform
|
|
177
|
+
|
|
178
|
+
assert_equal Curl::Err::UnsupportedProtocolError, Curl::Easy.error(easy.last_result).first
|
|
179
|
+
ensure
|
|
180
|
+
multi.close if defined?(multi) && multi
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def test_safe_http_denies_file_redirect
|
|
184
|
+
with_file_redirect_server do |url|
|
|
185
|
+
easy = Curl::Easy.new(url)
|
|
186
|
+
easy.follow_location = true
|
|
187
|
+
easy.safe_http!
|
|
188
|
+
|
|
189
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
|
190
|
+
easy.perform
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def test_safe_bang_denies_file_redirect
|
|
196
|
+
with_file_redirect_server do |url|
|
|
197
|
+
Curl.safe!
|
|
198
|
+
|
|
199
|
+
easy = Curl::Easy.new(url)
|
|
200
|
+
easy.follow_location = true
|
|
201
|
+
|
|
202
|
+
assert_raises Curl::Err::UnsupportedProtocolError do
|
|
203
|
+
easy.perform
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def test_safe_http_allows_http_to_https_redirect
|
|
209
|
+
with_http_https_redirect_servers(:http, :https) do |url|
|
|
210
|
+
easy = Curl::Easy.new(url)
|
|
211
|
+
easy.follow_location = true
|
|
212
|
+
easy.ssl_verify_peer = false
|
|
213
|
+
easy.ssl_verify_host = false
|
|
214
|
+
easy.safe_http!
|
|
215
|
+
|
|
216
|
+
easy.perform
|
|
217
|
+
|
|
218
|
+
assert_equal 200, easy.response_code
|
|
219
|
+
assert_equal 'https target', easy.body_str
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def test_safe_http_allows_https_to_http_redirect
|
|
224
|
+
with_http_https_redirect_servers(:https, :http) do |url|
|
|
225
|
+
easy = Curl::Easy.new(url)
|
|
226
|
+
easy.follow_location = true
|
|
227
|
+
easy.ssl_verify_peer = false
|
|
228
|
+
easy.ssl_verify_host = false
|
|
229
|
+
easy.safe_http!
|
|
230
|
+
|
|
231
|
+
easy.perform
|
|
232
|
+
|
|
233
|
+
assert_equal 200, easy.response_code
|
|
234
|
+
assert_equal 'http target', easy.body_str
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def test_safe_http_honors_redirect_limit
|
|
239
|
+
with_redirect_loop_server do |url, hits|
|
|
240
|
+
easy = Curl::Easy.new(url)
|
|
241
|
+
easy.follow_location = true
|
|
242
|
+
easy.max_redirects = 2
|
|
243
|
+
easy.safe_http!
|
|
244
|
+
|
|
245
|
+
assert_raises Curl::Err::TooManyRedirectsError do
|
|
246
|
+
easy.perform
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
assert_operator hits[:loop], :>=, 2
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
private
|
|
254
|
+
|
|
255
|
+
def with_file_redirect_server
|
|
256
|
+
port_socket = TCPServer.new('127.0.0.1', 0)
|
|
257
|
+
port = port_socket.addr[1]
|
|
258
|
+
port_socket.close
|
|
259
|
+
|
|
260
|
+
server = WEBrick::HTTPServer.new(:Port => port, :Logger => WEBRICK_TEST_LOG, :AccessLog => [])
|
|
261
|
+
server.mount_proc('/redirect-file') do |_req, res|
|
|
262
|
+
res.status = 302
|
|
263
|
+
res['Location'] = $TEST_URL
|
|
264
|
+
res.body = 'redirect'
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
thread = Thread.new(server) { |srv| srv.start }
|
|
268
|
+
wait_for_server_ready(port, thread: thread)
|
|
269
|
+
|
|
270
|
+
yield "http://127.0.0.1:#{port}/redirect-file"
|
|
271
|
+
ensure
|
|
272
|
+
server.shutdown if defined?(server) && server
|
|
273
|
+
thread.join(server_shutdown_timeout) if defined?(thread) && thread
|
|
274
|
+
if defined?(thread) && thread&.alive?
|
|
275
|
+
thread.kill
|
|
276
|
+
thread.join(server_shutdown_timeout)
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def with_redirect_loop_server
|
|
281
|
+
port_socket = TCPServer.new('127.0.0.1', 0)
|
|
282
|
+
port = port_socket.addr[1]
|
|
283
|
+
port_socket.close
|
|
284
|
+
|
|
285
|
+
hits = Hash.new(0)
|
|
286
|
+
server = WEBrick::HTTPServer.new(:Port => port, :Logger => WEBRICK_TEST_LOG, :AccessLog => [])
|
|
287
|
+
server.mount_proc('/loop') do |_req, res|
|
|
288
|
+
hits[:loop] += 1
|
|
289
|
+
res.status = 302
|
|
290
|
+
res['Location'] = '/loop'
|
|
291
|
+
res.body = 'redirect'
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
thread = Thread.new(server) { |srv| srv.start }
|
|
295
|
+
wait_for_server_ready(port, thread: thread)
|
|
296
|
+
|
|
297
|
+
yield "http://127.0.0.1:#{port}/loop", hits
|
|
298
|
+
ensure
|
|
299
|
+
server.shutdown if defined?(server) && server
|
|
300
|
+
thread.join(server_shutdown_timeout) if defined?(thread) && thread
|
|
301
|
+
if defined?(thread) && thread&.alive?
|
|
302
|
+
thread.kill
|
|
303
|
+
thread.join(server_shutdown_timeout)
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def with_http_https_redirect_servers(initial_scheme, target_scheme)
|
|
308
|
+
require 'webrick/https'
|
|
309
|
+
require 'openssl'
|
|
310
|
+
|
|
311
|
+
omit('HTTPS redirect fixtures require OpenSSL') unless defined?(OpenSSL::PKey::RSA)
|
|
312
|
+
|
|
313
|
+
initial_server = nil
|
|
314
|
+
target_server = nil
|
|
315
|
+
initial_thread = nil
|
|
316
|
+
target_thread = nil
|
|
317
|
+
|
|
318
|
+
initial_port = unused_redirect_port
|
|
319
|
+
target_port = unused_redirect_port
|
|
320
|
+
target_server = redirect_matrix_server(target_scheme, target_port)
|
|
321
|
+
target_server.mount_proc('/target') do |_req, res|
|
|
322
|
+
res['Content-Type'] = 'text/plain'
|
|
323
|
+
res.body = "#{target_scheme} target"
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
target_thread = Thread.new(target_server) { |srv| srv.start }
|
|
327
|
+
wait_for_server_ready(target_port, thread: target_thread)
|
|
328
|
+
|
|
329
|
+
initial_server = redirect_matrix_server(initial_scheme, initial_port)
|
|
330
|
+
initial_server.mount_proc('/redirect') do |_req, res|
|
|
331
|
+
res.status = 302
|
|
332
|
+
res['Location'] = "#{target_scheme}://127.0.0.1:#{target_port}/target"
|
|
333
|
+
res.body = 'redirect'
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
initial_thread = Thread.new(initial_server) { |srv| srv.start }
|
|
337
|
+
wait_for_server_ready(initial_port, thread: initial_thread)
|
|
338
|
+
|
|
339
|
+
yield "#{initial_scheme}://127.0.0.1:#{initial_port}/redirect"
|
|
340
|
+
ensure
|
|
341
|
+
initial_server.shutdown if initial_server
|
|
342
|
+
target_server.shutdown if target_server
|
|
343
|
+
initial_thread.join(server_shutdown_timeout) if initial_thread
|
|
344
|
+
target_thread.join(server_shutdown_timeout) if target_thread
|
|
345
|
+
[initial_thread, target_thread].compact.each do |thread|
|
|
346
|
+
next unless thread.alive?
|
|
347
|
+
|
|
348
|
+
thread.kill
|
|
349
|
+
thread.join(server_shutdown_timeout)
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def redirect_matrix_server(scheme, port)
|
|
354
|
+
options = {:BindAddress => '127.0.0.1', :Port => port, :Logger => WEBRICK_TEST_LOG, :AccessLog => []}
|
|
355
|
+
return WEBrick::HTTPServer.new(options) if scheme == :http
|
|
356
|
+
|
|
357
|
+
cert, key = redirect_matrix_certificate
|
|
358
|
+
WEBrick::HTTPServer.new(options.merge(:SSLEnable => true, :SSLCertificate => cert, :SSLPrivateKey => key))
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def redirect_matrix_certificate
|
|
362
|
+
key = OpenSSL::PKey::RSA.new(2048)
|
|
363
|
+
cert = OpenSSL::X509::Certificate.new
|
|
364
|
+
cert.version = 2
|
|
365
|
+
cert.serial = 1
|
|
366
|
+
cert.subject = OpenSSL::X509::Name.parse('/CN=127.0.0.1')
|
|
367
|
+
cert.issuer = cert.subject
|
|
368
|
+
cert.public_key = key.public_key
|
|
369
|
+
cert.not_before = Time.now - 60
|
|
370
|
+
cert.not_after = Time.now + 3600
|
|
371
|
+
|
|
372
|
+
extensions = OpenSSL::X509::ExtensionFactory.new
|
|
373
|
+
extensions.subject_certificate = cert
|
|
374
|
+
extensions.issuer_certificate = cert
|
|
375
|
+
cert.add_extension(extensions.create_extension('basicConstraints', 'CA:FALSE', true))
|
|
376
|
+
cert.add_extension(extensions.create_extension('subjectAltName', 'IP:127.0.0.1', false))
|
|
377
|
+
cert.sign(key, OpenSSL::Digest::SHA256.new)
|
|
378
|
+
|
|
379
|
+
[cert, key]
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def unused_redirect_port
|
|
383
|
+
socket = TCPServer.new('127.0.0.1', 0)
|
|
384
|
+
socket.addr[1]
|
|
385
|
+
ensure
|
|
386
|
+
socket.close if socket
|
|
387
|
+
end
|
|
37
388
|
end
|
data/tests/tc_fiber_scheduler.rb
CHANGED
|
@@ -15,10 +15,11 @@ class TestCurbFiberScheduler < Test::Unit::TestCase
|
|
|
15
15
|
include TestServerMethods
|
|
16
16
|
|
|
17
17
|
class RecordingScheduler
|
|
18
|
-
attr_reader :io_wait_events
|
|
18
|
+
attr_reader :io_wait_events, :io_select_calls
|
|
19
19
|
|
|
20
20
|
def initialize
|
|
21
21
|
@io_wait_events = []
|
|
22
|
+
@io_select_calls = 0
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def fiber(&block)
|
|
@@ -31,7 +32,7 @@ class TestCurbFiberScheduler < Test::Unit::TestCase
|
|
|
31
32
|
|
|
32
33
|
readers = (events & IO::READABLE) != 0 ? [io] : nil
|
|
33
34
|
writers = (events & IO::WRITABLE) != 0 ? [io] : nil
|
|
34
|
-
readable, writable = IO.select(readers, writers, nil, timeout)
|
|
35
|
+
readable, writable = blocking_io { IO.select(readers, writers, nil, timeout) }
|
|
35
36
|
|
|
36
37
|
ready = 0
|
|
37
38
|
ready |= IO::READABLE if readable && !readable.empty?
|
|
@@ -39,6 +40,11 @@ class TestCurbFiberScheduler < Test::Unit::TestCase
|
|
|
39
40
|
ready.zero? ? false : ready
|
|
40
41
|
end
|
|
41
42
|
|
|
43
|
+
def io_select(readers, writers, excepts, timeout = nil)
|
|
44
|
+
@io_select_calls += 1
|
|
45
|
+
blocking_io { IO.select(readers, writers, excepts, timeout) }
|
|
46
|
+
end
|
|
47
|
+
|
|
42
48
|
def kernel_sleep(duration = nil)
|
|
43
49
|
sleep(duration || 0)
|
|
44
50
|
end
|
|
@@ -56,6 +62,16 @@ class TestCurbFiberScheduler < Test::Unit::TestCase
|
|
|
56
62
|
|
|
57
63
|
def fiber_interrupt(*)
|
|
58
64
|
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def blocking_io(&block)
|
|
69
|
+
if Fiber.respond_to?(:blocking)
|
|
70
|
+
Fiber.blocking(&block)
|
|
71
|
+
else
|
|
72
|
+
block.call
|
|
73
|
+
end
|
|
74
|
+
end
|
|
59
75
|
end
|
|
60
76
|
|
|
61
77
|
ITERS = 4
|
|
@@ -208,9 +224,11 @@ class TestCurbFiberScheduler < Test::Unit::TestCase
|
|
|
208
224
|
end
|
|
209
225
|
|
|
210
226
|
assert_equal 200, result
|
|
211
|
-
assert_operator scheduler.io_wait_events.length, :>=, 1
|
|
212
|
-
|
|
213
|
-
|
|
227
|
+
assert_operator scheduler.io_wait_events.length + scheduler.io_select_calls, :>=, 1
|
|
228
|
+
unless scheduler.io_wait_events.empty?
|
|
229
|
+
assert scheduler.io_wait_events.all? { |events| events.is_a?(Integer) }
|
|
230
|
+
assert scheduler.io_wait_events.any? { |events| (events & (IO::READABLE | IO::WRITABLE)) != 0 }
|
|
231
|
+
end
|
|
214
232
|
end
|
|
215
233
|
|
|
216
234
|
def test_multi_reuse_after_scheduler_perform
|
|
@@ -431,6 +449,47 @@ class TestCurbFiberScheduler < Test::Unit::TestCase
|
|
|
431
449
|
end
|
|
432
450
|
end
|
|
433
451
|
|
|
452
|
+
def test_easy_perform_isolates_public_network_policy_block_under_scheduler
|
|
453
|
+
if skip_no_async
|
|
454
|
+
return
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
with_ephemeral_http_server do |port, hits|
|
|
458
|
+
results = {}
|
|
459
|
+
details = {}
|
|
460
|
+
|
|
461
|
+
async_run do |top|
|
|
462
|
+
blocked = top.async do
|
|
463
|
+
easy = Curl::Easy.new("http://127.0.0.1:#{port}/fast")
|
|
464
|
+
easy.network_policy = :public
|
|
465
|
+
easy.perform
|
|
466
|
+
results[:blocked] = :returned
|
|
467
|
+
rescue => e
|
|
468
|
+
results[:blocked] = e
|
|
469
|
+
details[:blocked_error] = easy.unsafe_destination_error if defined?(easy) && easy
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
successful = top.async do
|
|
473
|
+
easy = Curl::Easy.new("http://127.0.0.1:#{port}/slow")
|
|
474
|
+
easy.perform
|
|
475
|
+
results[:successful] = easy.response_code
|
|
476
|
+
rescue => e
|
|
477
|
+
results[:successful] = e
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
blocked.wait
|
|
481
|
+
successful.wait
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
assert_equal 200, results[:successful], "scheduler peer without public policy should return normally"
|
|
485
|
+
assert_kind_of Curl::Err::UnsafeDestinationError, results[:blocked]
|
|
486
|
+
assert_match(/127\.0\.0\.1/, results[:blocked].message)
|
|
487
|
+
assert_match(/127\.0\.0\.1/, details[:blocked_error])
|
|
488
|
+
assert_equal 0, hits[:fast], "blocked public-policy peer should not reach the server"
|
|
489
|
+
assert_equal 1, hits[:slow]
|
|
490
|
+
end
|
|
491
|
+
end
|
|
492
|
+
|
|
434
493
|
def test_drain_scheduler_pending_does_not_drop_work_rejected_during_deferred_abort
|
|
435
494
|
state = Curl.scheduler_state
|
|
436
495
|
easy = Curl::Easy.new("http://127.0.0.1:#{@port}/test")
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: curb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ross Bamford
|
|
8
8
|
- Todd A. Fisher
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-06-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Curb (probably CUrl-RuBy or something) provides Ruby-language bindings
|
|
14
14
|
for the libcurl(3), a fully-featured client-side URL transfer library. cURL and
|
|
@@ -42,6 +42,7 @@ files:
|
|
|
42
42
|
- ext/extconf.rb
|
|
43
43
|
- lib/curb.rb
|
|
44
44
|
- lib/curl.rb
|
|
45
|
+
- lib/curl/download.rb
|
|
45
46
|
- lib/curl/easy.rb
|
|
46
47
|
- lib/curl/multi.rb
|
|
47
48
|
- tests/alltests.rb
|
|
@@ -56,6 +57,7 @@ files:
|
|
|
56
57
|
- tests/bug_issue_post_redirect.rb
|
|
57
58
|
- tests/bug_issue_spnego.rb
|
|
58
59
|
- tests/bug_multi_segfault.rb
|
|
60
|
+
- tests/bug_poison.rb
|
|
59
61
|
- tests/bug_postfields_crash.rb
|
|
60
62
|
- tests/bug_postfields_crash2.rb
|
|
61
63
|
- tests/bug_raise_on_callback.rb
|
|
@@ -76,6 +78,7 @@ files:
|
|
|
76
78
|
- tests/tc_curl_maxfilesize.rb
|
|
77
79
|
- tests/tc_curl_multi.rb
|
|
78
80
|
- tests/tc_curl_native_coverage.rb
|
|
81
|
+
- tests/tc_curl_network_policy.rb
|
|
79
82
|
- tests/tc_curl_postfield.rb
|
|
80
83
|
- tests/tc_curl_protocols.rb
|
|
81
84
|
- tests/tc_fiber_scheduler.rb
|
|
@@ -107,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
107
110
|
- !ruby/object:Gem::Version
|
|
108
111
|
version: '0'
|
|
109
112
|
requirements: []
|
|
110
|
-
rubygems_version: 4.0.
|
|
113
|
+
rubygems_version: 4.0.10
|
|
111
114
|
specification_version: 4
|
|
112
115
|
summary: Ruby libcurl bindings
|
|
113
116
|
test_files:
|
|
@@ -123,6 +126,7 @@ test_files:
|
|
|
123
126
|
- tests/bug_issue_post_redirect.rb
|
|
124
127
|
- tests/bug_issue_spnego.rb
|
|
125
128
|
- tests/bug_multi_segfault.rb
|
|
129
|
+
- tests/bug_poison.rb
|
|
126
130
|
- tests/bug_postfields_crash.rb
|
|
127
131
|
- tests/bug_postfields_crash2.rb
|
|
128
132
|
- tests/bug_raise_on_callback.rb
|
|
@@ -143,6 +147,7 @@ test_files:
|
|
|
143
147
|
- tests/tc_curl_maxfilesize.rb
|
|
144
148
|
- tests/tc_curl_multi.rb
|
|
145
149
|
- tests/tc_curl_native_coverage.rb
|
|
150
|
+
- tests/tc_curl_network_policy.rb
|
|
146
151
|
- tests/tc_curl_postfield.rb
|
|
147
152
|
- tests/tc_curl_protocols.rb
|
|
148
153
|
- tests/tc_fiber_scheduler.rb
|