net-http-persistent 2.9.4 → 4.0.2
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 +5 -5
- data/Gemfile +14 -0
- data/History.txt +107 -0
- data/Manifest.txt +5 -3
- data/README.rdoc +10 -10
- data/Rakefile +20 -19
- data/lib/net/http/persistent/connection.rb +41 -0
- data/lib/net/http/persistent/pool.rb +65 -0
- data/lib/net/http/persistent/timed_stack_multi.rb +79 -0
- data/lib/net/http/persistent.rb +290 -426
- data/test/test_net_http_persistent.rb +415 -690
- data/test/test_net_http_persistent_timed_stack_multi.rb +151 -0
- metadata +25 -74
- checksums.yaml.gz.sig +0 -2
- data/lib/net/http/faster.rb +0 -27
- data/lib/net/http/persistent/ssl_reuse.rb +0 -129
- data/test/test_net_http_persistent_ssl_reuse.rb +0 -112
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
@@ -51,24 +51,13 @@ class Net::HTTP
|
|
51
51
|
include Net::HTTP::Persistent::TestConnect
|
52
52
|
end
|
53
53
|
|
54
|
-
class Net::HTTP::Persistent::SSLReuse
|
55
|
-
include Net::HTTP::Persistent::TestConnect
|
56
|
-
end
|
57
|
-
|
58
54
|
class TestNetHttpPersistent < Minitest::Test
|
59
55
|
|
60
|
-
RUBY_1 = RUBY_VERSION < '2'
|
61
|
-
|
62
56
|
def setup
|
63
|
-
@http_class = if RUBY_1 and HAVE_OPENSSL then
|
64
|
-
Net::HTTP::Persistent::SSLReuse
|
65
|
-
else
|
66
|
-
Net::HTTP
|
67
|
-
end
|
68
|
-
|
69
57
|
@http = Net::HTTP::Persistent.new
|
70
58
|
|
71
|
-
@uri
|
59
|
+
@uri = URI 'http://example.com/path'
|
60
|
+
@uri_v6 = URI 'http://[2001:db8::1]/path'
|
72
61
|
|
73
62
|
ENV.delete 'http_proxy'
|
74
63
|
ENV.delete 'HTTP_PROXY'
|
@@ -80,25 +69,23 @@ class TestNetHttpPersistent < Minitest::Test
|
|
80
69
|
ENV.delete 'NO_PROXY'
|
81
70
|
|
82
71
|
Net::HTTP.use_connect :test_connect
|
83
|
-
Net::HTTP::Persistent::SSLReuse.use_connect :test_connect
|
84
72
|
end
|
85
73
|
|
86
74
|
def teardown
|
87
|
-
Thread.current.keys.each do |key|
|
88
|
-
Thread.current[key] = nil
|
89
|
-
end
|
90
|
-
|
91
75
|
Net::HTTP.use_connect :orig_connect
|
92
|
-
Net::HTTP::Persistent::SSLReuse.use_connect :orig_connect
|
93
76
|
end
|
94
77
|
|
95
78
|
class BasicConnection
|
96
|
-
attr_accessor :started, :finished, :address, :port,
|
97
|
-
:read_timeout, :open_timeout
|
79
|
+
attr_accessor :started, :finished, :address, :port, :use_ssl,
|
80
|
+
:read_timeout, :open_timeout, :keep_alive_timeout
|
81
|
+
attr_accessor :ciphers, :ssl_timeout, :ssl_version, :min_version,
|
82
|
+
:max_version, :verify_depth, :verify_mode, :cert_store,
|
83
|
+
:ca_file, :ca_path, :cert, :key
|
98
84
|
attr_reader :req, :debug_output
|
99
85
|
def initialize
|
100
86
|
@started, @finished = 0, 0
|
101
87
|
@address, @port = 'example.com', 80
|
88
|
+
@use_ssl = false
|
102
89
|
end
|
103
90
|
def finish
|
104
91
|
@finished += 1
|
@@ -125,21 +112,34 @@ class TestNetHttpPersistent < Minitest::Test
|
|
125
112
|
def started?
|
126
113
|
@started >= 1
|
127
114
|
end
|
115
|
+
def proxy_address
|
116
|
+
end
|
117
|
+
def proxy_port
|
118
|
+
end
|
128
119
|
end
|
129
120
|
|
130
121
|
def basic_connection
|
131
122
|
raise "#{@uri} is not HTTP" unless @uri.scheme.downcase == 'http'
|
132
123
|
|
133
|
-
|
134
|
-
|
135
|
-
|
124
|
+
net_http_args = [@uri.hostname, @uri.port, nil, nil, nil, nil]
|
125
|
+
|
126
|
+
connection = Net::HTTP::Persistent::Connection.allocate
|
127
|
+
connection.ssl_generation = @http.ssl_generation
|
128
|
+
connection.http = BasicConnection.new
|
129
|
+
connection.reset
|
130
|
+
|
131
|
+
@http.pool.available.push connection, connection_args: net_http_args
|
132
|
+
|
133
|
+
connection
|
136
134
|
end
|
137
135
|
|
138
|
-
def connection
|
139
|
-
|
140
|
-
|
136
|
+
def connection uri = @uri
|
137
|
+
@uri = uri
|
138
|
+
|
139
|
+
connection = basic_connection
|
140
|
+
connection.last_use = Time.now
|
141
141
|
|
142
|
-
def
|
142
|
+
def (connection.http).request(req)
|
143
143
|
@req = req
|
144
144
|
r = Net::HTTPResponse.allocate
|
145
145
|
r.instance_variable_set :@header, {}
|
@@ -149,30 +149,22 @@ class TestNetHttpPersistent < Minitest::Test
|
|
149
149
|
r
|
150
150
|
end
|
151
151
|
|
152
|
-
|
152
|
+
connection
|
153
153
|
end
|
154
154
|
|
155
|
-
def
|
156
|
-
|
157
|
-
end
|
155
|
+
def ssl_connection
|
156
|
+
raise "#{@uri} is not HTTPS" unless @uri.scheme.downcase == 'https'
|
158
157
|
|
159
|
-
|
160
|
-
Thread.current[@http.request_key] ||= Hash.new 0
|
161
|
-
end
|
158
|
+
net_http_args = [@uri.hostname, @uri.port, nil, nil, nil, nil]
|
162
159
|
|
163
|
-
|
164
|
-
|
165
|
-
|
160
|
+
connection = Net::HTTP::Persistent::Connection.allocate
|
161
|
+
connection.ssl_generation = @http.ssl_generation
|
162
|
+
connection.http = BasicConnection.new
|
163
|
+
connection.reset
|
166
164
|
|
167
|
-
|
168
|
-
raise "#{@uri} is not HTTPS" unless @uri.scheme.downcase == 'https'
|
169
|
-
c = BasicConnection.new
|
170
|
-
ssl_conns[generation]["#{@uri.host}:#{@uri.port}"] = c
|
171
|
-
c
|
172
|
-
end
|
165
|
+
@http.pool.available.push connection, connection_args: net_http_args
|
173
166
|
|
174
|
-
|
175
|
-
Thread.current[@http.timeout_key] ||= Hash.new Net::HTTP::Persistent::EPOCH
|
167
|
+
connection
|
176
168
|
end
|
177
169
|
|
178
170
|
def test_initialize
|
@@ -188,7 +180,7 @@ class TestNetHttpPersistent < Minitest::Test
|
|
188
180
|
end
|
189
181
|
|
190
182
|
def test_initialize_name
|
191
|
-
http = Net::HTTP::Persistent.new 'name'
|
183
|
+
http = Net::HTTP::Persistent.new name: 'name'
|
192
184
|
assert_equal 'name', http.name
|
193
185
|
end
|
194
186
|
|
@@ -212,7 +204,7 @@ class TestNetHttpPersistent < Minitest::Test
|
|
212
204
|
def test_initialize_proxy
|
213
205
|
proxy_uri = URI.parse 'http://proxy.example'
|
214
206
|
|
215
|
-
http = Net::HTTP::Persistent.new
|
207
|
+
http = Net::HTTP::Persistent.new proxy: proxy_uri
|
216
208
|
|
217
209
|
assert_equal proxy_uri, http.proxy_uri
|
218
210
|
end
|
@@ -224,37 +216,11 @@ class TestNetHttpPersistent < Minitest::Test
|
|
224
216
|
assert_equal 1, @http.ssl_generation
|
225
217
|
end
|
226
218
|
|
227
|
-
def
|
228
|
-
|
219
|
+
def test_ca_path_equals
|
220
|
+
@http.ca_path = :ca_path
|
229
221
|
|
230
|
-
|
231
|
-
|
232
|
-
@http.retry_change_requests = true
|
233
|
-
|
234
|
-
assert @http.can_retry? post
|
235
|
-
end
|
236
|
-
|
237
|
-
if RUBY_1 then
|
238
|
-
def test_can_retry_eh_idempotent
|
239
|
-
head = Net::HTTP::Head.new '/'
|
240
|
-
|
241
|
-
assert @http.can_retry? head
|
242
|
-
|
243
|
-
post = Net::HTTP::Post.new '/'
|
244
|
-
|
245
|
-
refute @http.can_retry? post
|
246
|
-
end
|
247
|
-
else
|
248
|
-
def test_can_retry_eh_idempotent
|
249
|
-
head = Net::HTTP::Head.new '/'
|
250
|
-
|
251
|
-
assert @http.can_retry? head
|
252
|
-
refute @http.can_retry? head, true
|
253
|
-
|
254
|
-
post = Net::HTTP::Post.new '/'
|
255
|
-
|
256
|
-
refute @http.can_retry? post
|
257
|
-
end
|
222
|
+
assert_equal :ca_path, @http.ca_path
|
223
|
+
assert_equal 1, @http.ssl_generation
|
258
224
|
end
|
259
225
|
|
260
226
|
def test_cert_store_equals
|
@@ -271,168 +237,163 @@ class TestNetHttpPersistent < Minitest::Test
|
|
271
237
|
assert_equal 1, @http.ssl_generation
|
272
238
|
end
|
273
239
|
|
240
|
+
def test_ciphers_equals
|
241
|
+
@http.ciphers = :ciphers
|
242
|
+
|
243
|
+
assert_equal :ciphers, @http.ciphers
|
244
|
+
assert_equal 1, @http.ssl_generation
|
245
|
+
end
|
246
|
+
|
274
247
|
def test_connection_for
|
275
248
|
@http.open_timeout = 123
|
276
249
|
@http.read_timeout = 321
|
277
250
|
@http.idle_timeout = 42
|
278
|
-
|
251
|
+
@http.max_retries = 5
|
279
252
|
|
280
|
-
|
253
|
+
used = @http.connection_for @uri do |c|
|
254
|
+
assert_kind_of Net::HTTP, c.http
|
281
255
|
|
282
|
-
|
283
|
-
|
256
|
+
assert c.http.started?
|
257
|
+
refute c.http.proxy?
|
284
258
|
|
285
|
-
|
286
|
-
|
287
|
-
|
259
|
+
assert_equal 123, c.http.open_timeout
|
260
|
+
assert_equal 321, c.http.read_timeout
|
261
|
+
assert_equal 42, c.http.keep_alive_timeout
|
262
|
+
assert_equal 5, c.http.max_retries if c.http.respond_to?(:max_retries)
|
288
263
|
|
289
|
-
|
290
|
-
|
264
|
+
c
|
265
|
+
end
|
266
|
+
|
267
|
+
stored = @http.pool.checkout ['example.com', 80, nil, nil, nil, nil]
|
268
|
+
|
269
|
+
assert_same used, stored
|
291
270
|
end
|
292
271
|
|
293
272
|
def test_connection_for_cached
|
294
273
|
cached = basic_connection
|
295
|
-
cached.start
|
296
|
-
conns[0]['example.com:80'] = cached
|
274
|
+
cached.http.start
|
297
275
|
|
298
276
|
@http.read_timeout = 5
|
299
277
|
|
300
|
-
|
301
|
-
|
302
|
-
assert c.started?
|
278
|
+
@http.connection_for @uri do |c|
|
279
|
+
assert c.http.started?
|
303
280
|
|
304
|
-
|
281
|
+
assert_equal 5, c.http.read_timeout
|
305
282
|
|
306
|
-
|
283
|
+
assert_same cached, c
|
284
|
+
end
|
307
285
|
end
|
308
286
|
|
309
287
|
def test_connection_for_closed
|
310
288
|
cached = basic_connection
|
311
|
-
cached.start
|
289
|
+
cached.http.start
|
312
290
|
if Socket.const_defined? :TCP_NODELAY then
|
313
291
|
io = Object.new
|
314
292
|
def io.setsockopt(*a) raise IOError, 'closed stream' end
|
315
293
|
cached.instance_variable_set :@socket, Net::BufferedIO.new(io)
|
316
294
|
end
|
317
|
-
conns['example.com:80'] = cached
|
318
|
-
|
319
|
-
c = @http.connection_for @uri
|
320
|
-
|
321
|
-
assert c.started?
|
322
295
|
|
323
|
-
|
324
|
-
|
296
|
+
@http.connection_for @uri do |c|
|
297
|
+
assert c.http.started?
|
325
298
|
|
326
|
-
|
299
|
+
socket = c.http.instance_variable_get :@socket
|
327
300
|
|
328
|
-
|
329
|
-
|
301
|
+
refute_includes socket.io.instance_variables, :@setsockopt
|
302
|
+
refute_includes socket.io.instance_variables, '@setsockopt'
|
303
|
+
end
|
330
304
|
end
|
331
305
|
|
332
306
|
def test_connection_for_debug_output
|
333
307
|
io = StringIO.new
|
334
308
|
@http.debug_output = io
|
335
309
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
assert_includes conns[0].keys, 'example.com:80'
|
342
|
-
assert_same c, conns[0]['example.com:80']
|
310
|
+
@http.connection_for @uri do |c|
|
311
|
+
assert c.http.started?
|
312
|
+
assert_equal io, c.http.instance_variable_get(:@debug_output)
|
313
|
+
end
|
343
314
|
end
|
344
315
|
|
345
316
|
def test_connection_for_cached_expire_always
|
346
317
|
cached = basic_connection
|
347
|
-
cached.start
|
348
|
-
|
349
|
-
|
350
|
-
touts[cached.object_id] = Time.now # last used right now
|
318
|
+
cached.http.start
|
319
|
+
cached.requests = 10
|
320
|
+
cached.last_use = Time.now # last used right now
|
351
321
|
|
352
322
|
@http.idle_timeout = 0
|
353
323
|
|
354
|
-
|
355
|
-
|
356
|
-
assert c.started?
|
324
|
+
@http.connection_for @uri do |c|
|
325
|
+
assert c.http.started?
|
357
326
|
|
358
|
-
|
327
|
+
assert_same cached, c
|
359
328
|
|
360
|
-
|
361
|
-
|
329
|
+
assert_equal 0, c.requests, 'connection reset due to timeout'
|
330
|
+
end
|
362
331
|
end
|
363
332
|
|
364
333
|
def test_connection_for_cached_expire_never
|
365
334
|
cached = basic_connection
|
366
|
-
cached.start
|
367
|
-
|
368
|
-
|
369
|
-
touts[cached.object_id] = Time.now # last used right now
|
335
|
+
cached.http.start
|
336
|
+
cached.requests = 10
|
337
|
+
cached.last_use = Time.now # last used right now
|
370
338
|
|
371
339
|
@http.idle_timeout = nil
|
372
340
|
|
373
|
-
|
374
|
-
|
375
|
-
assert c.started?
|
341
|
+
@http.connection_for @uri do |c|
|
342
|
+
assert c.http.started?
|
376
343
|
|
377
|
-
|
344
|
+
assert_same cached, c
|
378
345
|
|
379
|
-
|
380
|
-
|
346
|
+
assert_equal 10, c.requests, 'connection reset despite no timeout'
|
347
|
+
end
|
381
348
|
end
|
382
349
|
|
383
350
|
def test_connection_for_cached_expired
|
384
351
|
cached = basic_connection
|
385
|
-
cached.start
|
386
|
-
|
387
|
-
|
388
|
-
touts[cached.object_id] = Time.now - 3600
|
389
|
-
|
390
|
-
c = @http.connection_for @uri
|
391
|
-
|
392
|
-
assert c.started?
|
352
|
+
cached.http.start
|
353
|
+
cached.requests = 10
|
354
|
+
cached.last_use = Time.now - 3600
|
393
355
|
|
394
|
-
|
395
|
-
|
396
|
-
'connection not reset due to timeout'
|
397
|
-
end
|
356
|
+
@http.connection_for @uri do |c|
|
357
|
+
assert c.http.started?
|
398
358
|
|
399
|
-
|
400
|
-
|
401
|
-
Net::HTTP::Persistent::SSLReuse.use_connect :refused_connect
|
402
|
-
|
403
|
-
e = assert_raises Net::HTTP::Persistent::Error do
|
404
|
-
@http.connection_for @uri
|
359
|
+
assert_same cached, c
|
360
|
+
assert_equal 0, cached.requests, 'connection not reset due to timeout'
|
405
361
|
end
|
406
|
-
|
407
|
-
assert_equal 'connection refused: example.com:80', e.message
|
408
362
|
end
|
409
363
|
|
410
364
|
def test_connection_for_finished_ssl
|
365
|
+
skip 'Broken on Windows' if Gem.win_platform?
|
411
366
|
skip 'OpenSSL is missing' unless HAVE_OPENSSL
|
412
367
|
|
413
368
|
uri = URI.parse 'https://example.com/path'
|
414
|
-
c = @http.connection_for uri
|
415
369
|
|
416
|
-
|
417
|
-
|
370
|
+
@http.connection_for uri do |c|
|
371
|
+
assert c.http.started?
|
372
|
+
assert c.http.use_ssl?
|
418
373
|
|
419
|
-
|
374
|
+
@http.finish c
|
420
375
|
|
421
|
-
|
376
|
+
refute c.http.started?
|
377
|
+
end
|
422
378
|
|
423
|
-
|
379
|
+
@http.connection_for uri do |c2|
|
380
|
+
assert c2.http.started?
|
381
|
+
end
|
382
|
+
end
|
424
383
|
|
425
|
-
|
384
|
+
def test_connection_for_ipv6
|
385
|
+
@http.connection_for @uri_v6 do |c|
|
386
|
+
assert_equal '2001:db8::1', c.http.address
|
387
|
+
end
|
426
388
|
end
|
427
389
|
|
428
390
|
def test_connection_for_host_down
|
429
|
-
|
430
|
-
def
|
431
|
-
def
|
432
|
-
conns[0]['example.com:80'] = cached
|
391
|
+
c = basic_connection
|
392
|
+
def (c.http).start; raise Errno::EHOSTDOWN end
|
393
|
+
def (c.http).started?; false end
|
433
394
|
|
434
395
|
e = assert_raises Net::HTTP::Persistent::Error do
|
435
|
-
@http.connection_for @uri
|
396
|
+
@http.connection_for @uri do end
|
436
397
|
end
|
437
398
|
|
438
399
|
assert_equal 'host down: example.com:80', e.message
|
@@ -440,8 +401,10 @@ class TestNetHttpPersistent < Minitest::Test
|
|
440
401
|
|
441
402
|
def test_connection_for_http_class_with_fakeweb
|
442
403
|
Object.send :const_set, :FakeWeb, nil
|
443
|
-
|
444
|
-
|
404
|
+
|
405
|
+
@http.connection_for @uri do |c|
|
406
|
+
assert_instance_of Net::HTTP, c.http
|
407
|
+
end
|
445
408
|
ensure
|
446
409
|
if Object.const_defined?(:FakeWeb) then
|
447
410
|
Object.send :remove_const, :FakeWeb
|
@@ -450,8 +413,9 @@ class TestNetHttpPersistent < Minitest::Test
|
|
450
413
|
|
451
414
|
def test_connection_for_http_class_with_webmock
|
452
415
|
Object.send :const_set, :WebMock, nil
|
453
|
-
|
454
|
-
|
416
|
+
@http.connection_for @uri do |c|
|
417
|
+
assert_instance_of Net::HTTP, c.http
|
418
|
+
end
|
455
419
|
ensure
|
456
420
|
if Object.const_defined?(:WebMock) then
|
457
421
|
Object.send :remove_const, :WebMock
|
@@ -460,8 +424,9 @@ class TestNetHttpPersistent < Minitest::Test
|
|
460
424
|
|
461
425
|
def test_connection_for_http_class_with_artifice
|
462
426
|
Object.send :const_set, :Artifice, nil
|
463
|
-
|
464
|
-
|
427
|
+
@http.connection_for @uri do |c|
|
428
|
+
assert_instance_of Net::HTTP, c.http
|
429
|
+
end
|
465
430
|
ensure
|
466
431
|
if Object.const_defined?(:Artifice) then
|
467
432
|
Object.send :remove_const, :Artifice
|
@@ -469,23 +434,12 @@ class TestNetHttpPersistent < Minitest::Test
|
|
469
434
|
end
|
470
435
|
|
471
436
|
def test_connection_for_name
|
472
|
-
http = Net::HTTP::Persistent.new 'name'
|
437
|
+
http = Net::HTTP::Persistent.new name: 'name'
|
473
438
|
uri = URI.parse 'http://example/'
|
474
439
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
refute_includes conns.keys, 'example:80'
|
480
|
-
end
|
481
|
-
|
482
|
-
def test_connection_for_no_ssl_reuse
|
483
|
-
@http.reuse_ssl_sessions = false
|
484
|
-
@http.open_timeout = 123
|
485
|
-
@http.read_timeout = 321
|
486
|
-
c = @http.connection_for @uri
|
487
|
-
|
488
|
-
assert_instance_of Net::HTTP, c
|
440
|
+
http.connection_for uri do |c|
|
441
|
+
assert c.http.started?
|
442
|
+
end
|
489
443
|
end
|
490
444
|
|
491
445
|
def test_connection_for_proxy
|
@@ -493,16 +447,20 @@ class TestNetHttpPersistent < Minitest::Test
|
|
493
447
|
uri.user = 'johndoe'
|
494
448
|
uri.password = 'muffins'
|
495
449
|
|
496
|
-
http = Net::HTTP::Persistent.new
|
450
|
+
http = Net::HTTP::Persistent.new proxy: uri
|
497
451
|
|
498
|
-
|
452
|
+
used = http.connection_for @uri do |c|
|
453
|
+
assert c.http.started?
|
454
|
+
assert c.http.proxy?
|
455
|
+
|
456
|
+
c
|
457
|
+
end
|
499
458
|
|
500
|
-
|
501
|
-
|
459
|
+
stored = http.pool.checkout ['example.com', 80,
|
460
|
+
'proxy.example', 80,
|
461
|
+
'johndoe', 'muffins']
|
502
462
|
|
503
|
-
|
504
|
-
'example.com:80:proxy.example:80:johndoe:muffins'
|
505
|
-
assert_same c, conns[1]['example.com:80:proxy.example:80:johndoe:muffins']
|
463
|
+
assert_same used, stored
|
506
464
|
end
|
507
465
|
|
508
466
|
def test_connection_for_proxy_unescaped
|
@@ -511,25 +469,28 @@ class TestNetHttpPersistent < Minitest::Test
|
|
511
469
|
uri.password = 'muf%3Afins'
|
512
470
|
uri.freeze
|
513
471
|
|
514
|
-
http = Net::HTTP::Persistent.new
|
515
|
-
|
472
|
+
http = Net::HTTP::Persistent.new proxy: uri
|
473
|
+
|
474
|
+
http.connection_for @uri do end
|
475
|
+
|
476
|
+
stored = http.pool.checkout ['example.com', 80,
|
477
|
+
'proxy.example', 80,
|
478
|
+
'john@doe', 'muf:fins']
|
516
479
|
|
517
|
-
|
518
|
-
'example.com:80:proxy.example:80:john@doe:muf:fins'
|
480
|
+
assert stored
|
519
481
|
end
|
520
482
|
|
521
483
|
def test_connection_for_proxy_host_down
|
522
484
|
Net::HTTP.use_connect :host_down_connect
|
523
|
-
Net::HTTP::Persistent::SSLReuse.use_connect :host_down_connect
|
524
485
|
|
525
486
|
uri = URI.parse 'http://proxy.example'
|
526
487
|
uri.user = 'johndoe'
|
527
488
|
uri.password = 'muffins'
|
528
489
|
|
529
|
-
http = Net::HTTP::Persistent.new
|
490
|
+
http = Net::HTTP::Persistent.new proxy: uri
|
530
491
|
|
531
492
|
e = assert_raises Net::HTTP::Persistent::Error do
|
532
|
-
http.connection_for @uri
|
493
|
+
http.connection_for @uri do end
|
533
494
|
end
|
534
495
|
|
535
496
|
assert_equal 'host down: proxy.example:80', e.message
|
@@ -537,16 +498,15 @@ class TestNetHttpPersistent < Minitest::Test
|
|
537
498
|
|
538
499
|
def test_connection_for_proxy_refused
|
539
500
|
Net::HTTP.use_connect :refused_connect
|
540
|
-
Net::HTTP::Persistent::SSLReuse.use_connect :refused_connect
|
541
501
|
|
542
502
|
uri = URI.parse 'http://proxy.example'
|
543
503
|
uri.user = 'johndoe'
|
544
504
|
uri.password = 'muffins'
|
545
505
|
|
546
|
-
http = Net::HTTP::Persistent.new
|
506
|
+
http = Net::HTTP::Persistent.new proxy: uri
|
547
507
|
|
548
508
|
e = assert_raises Net::HTTP::Persistent::Error do
|
549
|
-
http.connection_for @uri
|
509
|
+
http.connection_for @uri do end
|
550
510
|
end
|
551
511
|
|
552
512
|
assert_equal 'connection refused: proxy.example:80', e.message
|
@@ -558,38 +518,53 @@ class TestNetHttpPersistent < Minitest::Test
|
|
558
518
|
uri.password = 'muffins'
|
559
519
|
uri.query = 'no_proxy=example.com'
|
560
520
|
|
561
|
-
http = Net::HTTP::Persistent.new
|
521
|
+
http = Net::HTTP::Persistent.new proxy: uri
|
522
|
+
|
523
|
+
http.connection_for @uri do |c|
|
524
|
+
assert c.http.started?
|
525
|
+
refute c.http.proxy?
|
526
|
+
end
|
527
|
+
|
528
|
+
stored = http.pool.checkout ['example.com', 80]
|
562
529
|
|
563
|
-
|
530
|
+
assert stored
|
531
|
+
end
|
532
|
+
|
533
|
+
def test_connection_for_no_proxy_from_env
|
534
|
+
ENV['http_proxy'] = 'proxy.example'
|
535
|
+
ENV['no_proxy'] = 'localhost, example.com,'
|
536
|
+
ENV['proxy_user'] = 'johndoe'
|
537
|
+
ENV['proxy_password'] = 'muffins'
|
564
538
|
|
565
|
-
|
566
|
-
refute c.proxy?
|
539
|
+
http = Net::HTTP::Persistent.new proxy: :ENV
|
567
540
|
|
568
|
-
|
569
|
-
|
541
|
+
http.connection_for @uri do |c|
|
542
|
+
assert c.http.started?
|
543
|
+
refute c.http.proxy?
|
544
|
+
refute c.http.proxy_from_env?
|
545
|
+
end
|
570
546
|
end
|
571
547
|
|
572
548
|
def test_connection_for_refused
|
573
|
-
|
574
|
-
def cached.start; raise Errno::ECONNREFUSED end
|
575
|
-
def cached.started?; false end
|
576
|
-
conns[0]['example.com:80'] = cached
|
549
|
+
Net::HTTP.use_connect :refused_connect
|
577
550
|
|
578
551
|
e = assert_raises Net::HTTP::Persistent::Error do
|
579
|
-
@http.connection_for @uri
|
552
|
+
@http.connection_for @uri do end
|
580
553
|
end
|
581
554
|
|
582
|
-
|
555
|
+
assert_equal 'connection refused: example.com:80', e.message
|
583
556
|
end
|
584
557
|
|
585
558
|
def test_connection_for_ssl
|
559
|
+
skip 'Broken on Windows' if Gem.win_platform?
|
586
560
|
skip 'OpenSSL is missing' unless HAVE_OPENSSL
|
587
561
|
|
588
562
|
uri = URI.parse 'https://example.com/path'
|
589
|
-
c = @http.connection_for uri
|
590
563
|
|
591
|
-
|
592
|
-
|
564
|
+
@http.connection_for uri do |c|
|
565
|
+
assert c.http.started?
|
566
|
+
assert c.http.use_ssl?
|
567
|
+
end
|
593
568
|
end
|
594
569
|
|
595
570
|
def test_connection_for_ssl_cached
|
@@ -597,11 +572,11 @@ class TestNetHttpPersistent < Minitest::Test
|
|
597
572
|
|
598
573
|
@uri = URI.parse 'https://example.com/path'
|
599
574
|
|
600
|
-
cached = ssl_connection
|
601
|
-
|
602
|
-
c = @http.connection_for @uri
|
575
|
+
cached = ssl_connection
|
603
576
|
|
604
|
-
|
577
|
+
@http.connection_for @uri do |c|
|
578
|
+
assert_same cached, c
|
579
|
+
end
|
605
580
|
end
|
606
581
|
|
607
582
|
def test_connection_for_ssl_cached_reconnect
|
@@ -611,46 +586,39 @@ class TestNetHttpPersistent < Minitest::Test
|
|
611
586
|
|
612
587
|
cached = ssl_connection
|
613
588
|
|
614
|
-
@http.
|
589
|
+
ssl_generation = @http.ssl_generation
|
615
590
|
|
616
|
-
|
591
|
+
@http.reconnect_ssl
|
617
592
|
|
618
|
-
|
593
|
+
@http.connection_for @uri do |c|
|
594
|
+
assert_same cached, c
|
595
|
+
refute_equal ssl_generation, c.ssl_generation
|
596
|
+
end
|
619
597
|
end
|
620
598
|
|
621
599
|
def test_connection_for_ssl_case
|
600
|
+
skip 'Broken on Windows' if Gem.win_platform?
|
622
601
|
skip 'OpenSSL is missing' unless HAVE_OPENSSL
|
623
602
|
|
624
603
|
uri = URI.parse 'HTTPS://example.com/path'
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
604
|
+
@http.connection_for uri do |c|
|
605
|
+
assert c.http.started?
|
606
|
+
assert c.http.use_ssl?
|
607
|
+
end
|
629
608
|
end
|
630
609
|
|
631
610
|
def test_connection_for_timeout
|
632
611
|
cached = basic_connection
|
633
|
-
cached.start
|
634
|
-
|
635
|
-
|
636
|
-
conns[0]['example.com:80'] = cached
|
637
|
-
|
638
|
-
c = @http.connection_for @uri
|
612
|
+
cached.http.start
|
613
|
+
cached.requests = 10
|
614
|
+
cached.last_use = Time.now - 6
|
639
615
|
|
640
|
-
|
641
|
-
|
616
|
+
@http.connection_for @uri do |c|
|
617
|
+
assert c.http.started?
|
618
|
+
assert_equal 0, c.requests
|
642
619
|
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
def test_error_message
|
647
|
-
c = basic_connection
|
648
|
-
touts[c.object_id] = Time.now - 1
|
649
|
-
reqs[c.object_id] = 5
|
650
|
-
|
651
|
-
message = @http.error_message(c)
|
652
|
-
assert_match %r%after 4 requests on #{c.object_id}%, message
|
653
|
-
assert_match %r%, last used [\d.]+ seconds ago%, message
|
620
|
+
assert_same cached, c
|
621
|
+
end
|
654
622
|
end
|
655
623
|
|
656
624
|
def test_escape
|
@@ -666,9 +634,10 @@ class TestNetHttpPersistent < Minitest::Test
|
|
666
634
|
end
|
667
635
|
|
668
636
|
def test_expired_eh
|
637
|
+
skip 'Broken on Windows' if Gem.win_platform?
|
669
638
|
c = basic_connection
|
670
|
-
|
671
|
-
|
639
|
+
c.requests = 0
|
640
|
+
c.last_use = Time.now - 11
|
672
641
|
|
673
642
|
@http.idle_timeout = 0
|
674
643
|
assert @http.expired? c
|
@@ -688,41 +657,59 @@ class TestNetHttpPersistent < Minitest::Test
|
|
688
657
|
|
689
658
|
def test_expired_due_to_max_requests
|
690
659
|
c = basic_connection
|
691
|
-
|
692
|
-
|
660
|
+
c.requests = 0
|
661
|
+
c.last_use = Time.now
|
693
662
|
|
694
663
|
refute @http.expired? c
|
695
664
|
|
696
|
-
|
665
|
+
c.requests = 10
|
697
666
|
refute @http.expired? c
|
698
667
|
|
699
668
|
@http.max_requests = 10
|
700
669
|
assert @http.expired? c
|
701
670
|
|
702
|
-
|
671
|
+
c.requests = 9
|
703
672
|
refute @http.expired? c
|
704
673
|
end
|
705
674
|
|
706
675
|
def test_finish
|
707
676
|
c = basic_connection
|
708
|
-
|
677
|
+
c.requests = 5
|
678
|
+
c.http.instance_variable_set(:@last_communicated, Process.clock_gettime(Process::CLOCK_MONOTONIC))
|
709
679
|
|
710
680
|
@http.finish c
|
711
681
|
|
712
|
-
refute c.started?
|
713
|
-
assert c.finished?
|
714
|
-
|
682
|
+
refute c.http.started?
|
683
|
+
assert c.http.finished?
|
684
|
+
|
685
|
+
assert_equal 0, c.requests
|
686
|
+
assert_equal Net::HTTP::Persistent::EPOCH, c.last_use
|
687
|
+
assert_nil c.http.instance_variable_get(:@last_communicated)
|
715
688
|
end
|
716
689
|
|
717
690
|
def test_finish_io_error
|
718
691
|
c = basic_connection
|
719
|
-
def c.finish; @finished += 1; raise IOError end
|
720
|
-
|
692
|
+
def (c.http).finish; @finished += 1; raise IOError end
|
693
|
+
c.requests = 5
|
694
|
+
|
695
|
+
@http.finish c
|
696
|
+
|
697
|
+
refute c.http.started?
|
698
|
+
assert c.http.finished?
|
699
|
+
end
|
700
|
+
|
701
|
+
def test_finish_ssl_no_session_reuse
|
702
|
+
http = Net::HTTP.new 'localhost', 443, ssl: true
|
703
|
+
http.instance_variable_set :@ssl_session, :something
|
704
|
+
|
705
|
+
c = Net::HTTP::Persistent::Connection.allocate
|
706
|
+
c.instance_variable_set :@http, http
|
707
|
+
|
708
|
+
@http.reuse_ssl_sessions = false
|
721
709
|
|
722
710
|
@http.finish c
|
723
711
|
|
724
|
-
|
725
|
-
assert c.finished?
|
712
|
+
assert_nil c.http.instance_variable_get :@ssl_session
|
726
713
|
end
|
727
714
|
|
728
715
|
def test_http_version
|
@@ -735,23 +722,21 @@ class TestNetHttpPersistent < Minitest::Test
|
|
735
722
|
assert_equal '1.1', @http.http_version(@uri)
|
736
723
|
end
|
737
724
|
|
738
|
-
def
|
739
|
-
|
740
|
-
assert @http.idempotent? Net::HTTP::Get.new '/'
|
741
|
-
assert @http.idempotent? Net::HTTP::Head.new '/'
|
742
|
-
assert @http.idempotent? Net::HTTP::Options.new '/'
|
743
|
-
assert @http.idempotent? Net::HTTP::Put.new '/'
|
744
|
-
assert @http.idempotent? Net::HTTP::Trace.new '/'
|
725
|
+
def test_http_version_IPv6
|
726
|
+
assert_nil @http.http_version @uri_v6
|
745
727
|
|
746
|
-
|
747
|
-
end
|
728
|
+
connection @uri_v6
|
748
729
|
|
749
|
-
|
750
|
-
assert_in_delta Time.now - 5, @http.max_age
|
730
|
+
@http.request @uri_v6
|
751
731
|
|
752
|
-
@http.
|
732
|
+
assert_equal '1.1', @http.http_version(@uri_v6)
|
733
|
+
end
|
753
734
|
|
754
|
-
|
735
|
+
def test_max_retries_equals
|
736
|
+
@http.max_retries = 5
|
737
|
+
|
738
|
+
assert_equal 5, @http.max_retries
|
739
|
+
assert_equal 1, @http.generation
|
755
740
|
end
|
756
741
|
|
757
742
|
def test_normalize_uri
|
@@ -774,8 +759,7 @@ class TestNetHttpPersistent < Minitest::Test
|
|
774
759
|
skip 'net-http-pipeline not installed' unless defined?(Net::HTTP::Pipeline)
|
775
760
|
|
776
761
|
cached = basic_connection
|
777
|
-
cached.start
|
778
|
-
conns['example.com:80'] = cached
|
762
|
+
cached.http.start
|
779
763
|
|
780
764
|
requests = [
|
781
765
|
Net::HTTP::Get.new((@uri + '1').request_uri),
|
@@ -810,7 +794,7 @@ class TestNetHttpPersistent < Minitest::Test
|
|
810
794
|
def test_proxy_equals_nil
|
811
795
|
@http.proxy = nil
|
812
796
|
|
813
|
-
|
797
|
+
assert_nil @http.proxy_uri
|
814
798
|
|
815
799
|
assert_equal 1, @http.generation, 'generation'
|
816
800
|
assert_equal 1, @http.ssl_generation, 'ssl_generation'
|
@@ -824,6 +808,14 @@ class TestNetHttpPersistent < Minitest::Test
|
|
824
808
|
assert_equal proxy_uri, @http.proxy_uri
|
825
809
|
end
|
826
810
|
|
811
|
+
def test_proxy_equals_uri_IPv6
|
812
|
+
proxy_uri = @uri_v6
|
813
|
+
|
814
|
+
@http.proxy = proxy_uri
|
815
|
+
|
816
|
+
assert_equal proxy_uri, @http.proxy_uri
|
817
|
+
end
|
818
|
+
|
827
819
|
def test_proxy_from_env
|
828
820
|
ENV['http_proxy'] = 'proxy.example'
|
829
821
|
ENV['http_proxy_user'] = 'johndoe'
|
@@ -935,18 +927,47 @@ class TestNetHttpPersistent < Minitest::Test
|
|
935
927
|
end
|
936
928
|
|
937
929
|
def test_reconnect_ssl
|
938
|
-
|
930
|
+
skip 'OpenSSL is missing' unless HAVE_OPENSSL
|
939
931
|
|
940
|
-
|
932
|
+
@uri = URI 'https://example.com'
|
933
|
+
now = Time.now
|
934
|
+
|
935
|
+
ssl_http = ssl_connection
|
936
|
+
|
937
|
+
def (ssl_http.http).finish
|
938
|
+
@started = 0
|
939
|
+
end
|
940
|
+
|
941
|
+
used1 = @http.connection_for @uri do |c|
|
942
|
+
c.requests = 1
|
943
|
+
c.last_use = now
|
944
|
+
c
|
945
|
+
end
|
946
|
+
|
947
|
+
assert_equal OpenSSL::SSL::VERIFY_PEER, used1.http.verify_mode
|
948
|
+
|
949
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
950
|
+
@http.reconnect_ssl
|
951
|
+
|
952
|
+
used2 = @http.connection_for @uri do |c|
|
953
|
+
c
|
954
|
+
end
|
955
|
+
|
956
|
+
assert_same used1, used2
|
957
|
+
|
958
|
+
assert_equal OpenSSL::SSL::VERIFY_NONE, used2.http.verify_mode,
|
959
|
+
'verify mode must change'
|
960
|
+
assert_equal 0, used2.requests
|
961
|
+
assert_equal Net::HTTP::Persistent::EPOCH, used2.last_use
|
941
962
|
end
|
942
963
|
|
943
|
-
def
|
964
|
+
def test_requestx
|
944
965
|
@http.override_headers['user-agent'] = 'test ua'
|
945
966
|
@http.headers['accept'] = 'text/*'
|
946
967
|
c = connection
|
947
968
|
|
948
969
|
res = @http.request @uri
|
949
|
-
req = c.req
|
970
|
+
req = c.http.req
|
950
971
|
|
951
972
|
assert_kind_of Net::HTTPResponse, res
|
952
973
|
|
@@ -959,86 +980,12 @@ class TestNetHttpPersistent < Minitest::Test
|
|
959
980
|
assert_equal 'keep-alive', req['connection']
|
960
981
|
assert_equal '30', req['keep-alive']
|
961
982
|
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
end
|
966
|
-
|
967
|
-
def test_request_ETIMEDOUT
|
968
|
-
c = basic_connection
|
969
|
-
def c.request(*a) raise Errno::ETIMEDOUT, "timed out" end
|
970
|
-
|
971
|
-
e = assert_raises Net::HTTP::Persistent::Error do
|
972
|
-
@http.request @uri
|
973
|
-
end
|
974
|
-
|
975
|
-
assert_equal 0, reqs[c.object_id]
|
976
|
-
assert_match %r%too many connection resets%, e.message
|
977
|
-
end
|
978
|
-
|
979
|
-
def test_request_bad_response
|
980
|
-
c = basic_connection
|
981
|
-
def c.request(*a) raise Net::HTTPBadResponse end
|
982
|
-
|
983
|
-
e = assert_raises Net::HTTP::Persistent::Error do
|
984
|
-
@http.request @uri
|
985
|
-
end
|
986
|
-
|
987
|
-
assert_equal 0, reqs[c.object_id]
|
988
|
-
assert_match %r%too many bad responses%, e.message
|
989
|
-
end
|
990
|
-
|
991
|
-
if RUBY_1 then
|
992
|
-
def test_request_bad_response_retry
|
993
|
-
c = basic_connection
|
994
|
-
def c.request(*a)
|
995
|
-
if defined? @called then
|
996
|
-
r = Net::HTTPResponse.allocate
|
997
|
-
r.instance_variable_set :@header, {}
|
998
|
-
def r.http_version() '1.1' end
|
999
|
-
r
|
1000
|
-
else
|
1001
|
-
@called = true
|
1002
|
-
raise Net::HTTPBadResponse
|
1003
|
-
end
|
1004
|
-
end
|
1005
|
-
|
1006
|
-
@http.request @uri
|
1007
|
-
|
1008
|
-
assert c.finished?
|
983
|
+
# There's some roounding issue on jruby preventing this from passing
|
984
|
+
unless RUBY_PLATFORM == "java"
|
985
|
+
assert_in_delta Time.now, c.last_use
|
1009
986
|
end
|
1010
|
-
else
|
1011
|
-
def test_request_bad_response_retry
|
1012
|
-
c = basic_connection
|
1013
|
-
def c.request(*a)
|
1014
|
-
raise Net::HTTPBadResponse
|
1015
|
-
end
|
1016
|
-
|
1017
|
-
assert_raises Net::HTTP::Persistent::Error do
|
1018
|
-
@http.request @uri
|
1019
|
-
end
|
1020
987
|
|
1021
|
-
|
1022
|
-
end
|
1023
|
-
end
|
1024
|
-
|
1025
|
-
def test_request_bad_response_unsafe
|
1026
|
-
c = basic_connection
|
1027
|
-
def c.request(*a)
|
1028
|
-
if instance_variable_defined? :@request then
|
1029
|
-
raise 'POST must not be retried'
|
1030
|
-
else
|
1031
|
-
@request = true
|
1032
|
-
raise Net::HTTPBadResponse
|
1033
|
-
end
|
1034
|
-
end
|
1035
|
-
|
1036
|
-
e = assert_raises Net::HTTP::Persistent::Error do
|
1037
|
-
@http.request @uri, Net::HTTP::Post.new(@uri.path)
|
1038
|
-
end
|
1039
|
-
|
1040
|
-
assert_equal 0, reqs[c.object_id]
|
1041
|
-
assert_match %r%too many bad responses%, e.message
|
988
|
+
assert_equal 1, c.requests
|
1042
989
|
end
|
1043
990
|
|
1044
991
|
def test_request_block
|
@@ -1050,7 +997,7 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1050
997
|
body = r.read_body
|
1051
998
|
end
|
1052
999
|
|
1053
|
-
req = c.req
|
1000
|
+
req = c.http.req
|
1054
1001
|
|
1055
1002
|
assert_kind_of Net::HTTPResponse, res
|
1056
1003
|
refute_nil body
|
@@ -1061,17 +1008,17 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1061
1008
|
assert_equal '30', req['keep-alive']
|
1062
1009
|
assert_match %r%test ua%, req['user-agent']
|
1063
1010
|
|
1064
|
-
assert_equal 1,
|
1011
|
+
assert_equal 1, c.requests
|
1065
1012
|
end
|
1066
1013
|
|
1067
1014
|
def test_request_close_1_0
|
1068
1015
|
c = connection
|
1069
1016
|
|
1070
|
-
class << c
|
1017
|
+
class << c.http
|
1071
1018
|
remove_method :request
|
1072
1019
|
end
|
1073
1020
|
|
1074
|
-
def c.request req
|
1021
|
+
def (c.http).request req
|
1075
1022
|
@req = req
|
1076
1023
|
r = Net::HTTPResponse.allocate
|
1077
1024
|
r.instance_variable_set :@header, {}
|
@@ -1084,7 +1031,7 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1084
1031
|
request = Net::HTTP::Get.new @uri.request_uri
|
1085
1032
|
|
1086
1033
|
res = @http.request @uri, request
|
1087
|
-
req = c.req
|
1034
|
+
req = c.http.req
|
1088
1035
|
|
1089
1036
|
assert_kind_of Net::HTTPResponse, res
|
1090
1037
|
|
@@ -1093,7 +1040,7 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1093
1040
|
assert_equal 'keep-alive', req['connection']
|
1094
1041
|
assert_equal '30', req['keep-alive']
|
1095
1042
|
|
1096
|
-
assert c.finished?
|
1043
|
+
assert c.http.finished?
|
1097
1044
|
end
|
1098
1045
|
|
1099
1046
|
def test_request_connection_close_request
|
@@ -1103,26 +1050,26 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1103
1050
|
request['connection'] = 'close'
|
1104
1051
|
|
1105
1052
|
res = @http.request @uri, request
|
1106
|
-
req = c.req
|
1053
|
+
req = c.http.req
|
1107
1054
|
|
1108
1055
|
assert_kind_of Net::HTTPResponse, res
|
1109
1056
|
|
1110
1057
|
assert_kind_of Net::HTTP::Get, req
|
1111
1058
|
assert_equal '/path', req.path
|
1112
1059
|
assert_equal 'close', req['connection']
|
1113
|
-
|
1060
|
+
assert_nil req['keep-alive']
|
1114
1061
|
|
1115
|
-
assert c.finished?
|
1062
|
+
assert c.http.finished?
|
1116
1063
|
end
|
1117
1064
|
|
1118
1065
|
def test_request_connection_close_response
|
1119
1066
|
c = connection
|
1120
1067
|
|
1121
|
-
class << c
|
1068
|
+
class << c.http
|
1122
1069
|
remove_method :request
|
1123
1070
|
end
|
1124
1071
|
|
1125
|
-
def c.request req
|
1072
|
+
def (c.http).request req
|
1126
1073
|
@req = req
|
1127
1074
|
r = Net::HTTPResponse.allocate
|
1128
1075
|
r.instance_variable_set :@header, {}
|
@@ -1136,7 +1083,7 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1136
1083
|
request = Net::HTTP::Get.new @uri.request_uri
|
1137
1084
|
|
1138
1085
|
res = @http.request @uri, request
|
1139
|
-
req = c.req
|
1086
|
+
req = c.http.req
|
1140
1087
|
|
1141
1088
|
assert_kind_of Net::HTTPResponse, res
|
1142
1089
|
|
@@ -1145,53 +1092,33 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1145
1092
|
assert_equal 'keep-alive', req['connection']
|
1146
1093
|
assert_equal '30', req['keep-alive']
|
1147
1094
|
|
1148
|
-
assert c.finished?
|
1095
|
+
assert c.http.finished?
|
1149
1096
|
end
|
1150
1097
|
|
1151
1098
|
def test_request_exception
|
1152
1099
|
c = basic_connection
|
1153
|
-
def c.request(*a)
|
1100
|
+
def (c.http).request(*a)
|
1101
|
+
raise Exception, "very bad things happened"
|
1102
|
+
end
|
1154
1103
|
|
1155
1104
|
assert_raises Exception do
|
1156
1105
|
@http.request @uri
|
1157
1106
|
end
|
1158
1107
|
|
1159
|
-
assert_equal 0,
|
1160
|
-
assert c.finished?
|
1108
|
+
assert_equal 0, c.requests
|
1109
|
+
assert c.http.finished?
|
1161
1110
|
end
|
1162
1111
|
|
1163
1112
|
def test_request_invalid
|
1164
1113
|
c = basic_connection
|
1165
|
-
def c.request(*a) raise Errno::EINVAL, "write" end
|
1114
|
+
def (c.http).request(*a) raise Errno::EINVAL, "write" end
|
1166
1115
|
|
1167
|
-
e = assert_raises
|
1116
|
+
e = assert_raises Errno::EINVAL do
|
1168
1117
|
@http.request @uri
|
1169
1118
|
end
|
1170
1119
|
|
1171
|
-
assert_equal 0,
|
1172
|
-
assert_match %r%
|
1173
|
-
end
|
1174
|
-
|
1175
|
-
def test_request_invalid_retry
|
1176
|
-
c = basic_connection
|
1177
|
-
touts[c.object_id] = Time.now
|
1178
|
-
|
1179
|
-
def c.request(*a)
|
1180
|
-
if defined? @called then
|
1181
|
-
r = Net::HTTPResponse.allocate
|
1182
|
-
r.instance_variable_set :@header, {}
|
1183
|
-
def r.http_version() '1.1' end
|
1184
|
-
r
|
1185
|
-
else
|
1186
|
-
@called = true
|
1187
|
-
raise Errno::EINVAL, "write"
|
1188
|
-
end
|
1189
|
-
end
|
1190
|
-
|
1191
|
-
@http.request @uri
|
1192
|
-
|
1193
|
-
assert c.reset?
|
1194
|
-
assert c.finished?
|
1120
|
+
assert_equal 0, c.requests
|
1121
|
+
assert_match %r%Invalid argument - write%, e.message
|
1195
1122
|
end
|
1196
1123
|
|
1197
1124
|
def test_request_post
|
@@ -1200,96 +1127,11 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1200
1127
|
post = Net::HTTP::Post.new @uri.path
|
1201
1128
|
|
1202
1129
|
@http.request @uri, post
|
1203
|
-
req = c.req
|
1130
|
+
req = c.http.req
|
1204
1131
|
|
1205
1132
|
assert_same post, req
|
1206
1133
|
end
|
1207
1134
|
|
1208
|
-
def test_request_reset
|
1209
|
-
c = basic_connection
|
1210
|
-
def c.request(*a) raise Errno::ECONNRESET end
|
1211
|
-
|
1212
|
-
e = assert_raises Net::HTTP::Persistent::Error do
|
1213
|
-
@http.request @uri
|
1214
|
-
end
|
1215
|
-
|
1216
|
-
assert_equal 0, reqs[c.object_id]
|
1217
|
-
assert_match %r%too many connection resets%, e.message
|
1218
|
-
end
|
1219
|
-
|
1220
|
-
if RUBY_1 then
|
1221
|
-
def test_request_reset_retry
|
1222
|
-
c = basic_connection
|
1223
|
-
touts[c.object_id] = Time.now
|
1224
|
-
def c.request(*a)
|
1225
|
-
if defined? @called then
|
1226
|
-
r = Net::HTTPResponse.allocate
|
1227
|
-
r.instance_variable_set :@header, {}
|
1228
|
-
def r.http_version() '1.1' end
|
1229
|
-
r
|
1230
|
-
else
|
1231
|
-
@called = true
|
1232
|
-
raise Errno::ECONNRESET
|
1233
|
-
end
|
1234
|
-
end
|
1235
|
-
|
1236
|
-
@http.request @uri
|
1237
|
-
|
1238
|
-
assert c.reset?
|
1239
|
-
assert c.finished?
|
1240
|
-
end
|
1241
|
-
else
|
1242
|
-
def test_request_reset_retry
|
1243
|
-
c = basic_connection
|
1244
|
-
touts[c.object_id] = Time.now
|
1245
|
-
|
1246
|
-
def c.request(*a)
|
1247
|
-
raise Errno::ECONNRESET
|
1248
|
-
end
|
1249
|
-
|
1250
|
-
assert_raises Net::HTTP::Persistent::Error do
|
1251
|
-
@http.request @uri
|
1252
|
-
end
|
1253
|
-
|
1254
|
-
refute c.reset?
|
1255
|
-
assert c.finished?
|
1256
|
-
end
|
1257
|
-
end
|
1258
|
-
|
1259
|
-
def test_request_reset_unsafe
|
1260
|
-
c = basic_connection
|
1261
|
-
def c.request(*a)
|
1262
|
-
if instance_variable_defined? :@request then
|
1263
|
-
raise 'POST must not be retried'
|
1264
|
-
else
|
1265
|
-
@request = true
|
1266
|
-
raise Errno::ECONNRESET
|
1267
|
-
end
|
1268
|
-
end
|
1269
|
-
|
1270
|
-
e = assert_raises Net::HTTP::Persistent::Error do
|
1271
|
-
@http.request @uri, Net::HTTP::Post.new(@uri.path)
|
1272
|
-
end
|
1273
|
-
|
1274
|
-
assert_equal 0, reqs[c.object_id]
|
1275
|
-
assert_match %r%too many connection resets%, e.message
|
1276
|
-
end
|
1277
|
-
|
1278
|
-
def test_request_ssl_error
|
1279
|
-
skip 'OpenSSL is missing' unless HAVE_OPENSSL
|
1280
|
-
|
1281
|
-
uri = URI.parse 'https://example.com/path'
|
1282
|
-
c = @http.connection_for uri
|
1283
|
-
def c.request(*)
|
1284
|
-
raise OpenSSL::SSL::SSLError, "SSL3_WRITE_PENDING:bad write retry"
|
1285
|
-
end
|
1286
|
-
|
1287
|
-
e = assert_raises Net::HTTP::Persistent::Error do
|
1288
|
-
@http.request uri
|
1289
|
-
end
|
1290
|
-
assert_match %r%bad write retry%, e.message
|
1291
|
-
end
|
1292
|
-
|
1293
1135
|
def test_request_setup
|
1294
1136
|
@http.override_headers['user-agent'] = 'test ua'
|
1295
1137
|
@http.headers['accept'] = 'text/*'
|
@@ -1308,59 +1150,51 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1308
1150
|
assert_equal '30', req['keep-alive']
|
1309
1151
|
end
|
1310
1152
|
|
1311
|
-
def
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1153
|
+
def test_request_string
|
1154
|
+
@http.override_headers['user-agent'] = 'test ua'
|
1155
|
+
@http.headers['accept'] = 'text/*'
|
1156
|
+
c = connection
|
1315
1157
|
|
1316
|
-
|
1317
|
-
|
1318
|
-
end
|
1158
|
+
res = @http.request @uri.to_s
|
1159
|
+
req = c.http.req
|
1319
1160
|
|
1320
|
-
|
1321
|
-
c = basic_connection
|
1322
|
-
reqs[c.object_id] = 1
|
1323
|
-
touts[c.object_id] = Time.now
|
1161
|
+
assert_kind_of Net::HTTPResponse, res
|
1324
1162
|
|
1325
|
-
|
1163
|
+
assert_kind_of Net::HTTP::Get, req
|
1164
|
+
assert_equal '/path', req.path
|
1326
1165
|
|
1327
|
-
|
1328
|
-
|
1329
|
-
rescue => original
|
1330
|
-
end
|
1166
|
+
assert_equal 1, c.requests
|
1167
|
+
end
|
1331
1168
|
|
1332
|
-
|
1333
|
-
|
1334
|
-
e = assert_raises Net::HTTP::Persistent::Error do
|
1335
|
-
@http.request_failed original, req, c
|
1336
|
-
end
|
1169
|
+
def test_request_setup_uri
|
1170
|
+
uri = @uri + '?a=b'
|
1337
1171
|
|
1338
|
-
|
1339
|
-
e.message
|
1172
|
+
req = @http.request_setup uri
|
1340
1173
|
|
1341
|
-
|
1174
|
+
assert_kind_of Net::HTTP::Get, req
|
1175
|
+
assert_equal '/path?a=b', req.path
|
1342
1176
|
end
|
1343
1177
|
|
1344
1178
|
def test_reset
|
1345
1179
|
c = basic_connection
|
1346
|
-
c.start
|
1347
|
-
|
1348
|
-
|
1180
|
+
c.http.start
|
1181
|
+
c.last_use = Time.now
|
1182
|
+
c.requests = 5
|
1349
1183
|
|
1350
1184
|
@http.reset c
|
1351
1185
|
|
1352
|
-
assert c.started?
|
1353
|
-
assert c.finished?
|
1354
|
-
assert c.reset?
|
1355
|
-
assert_equal 0,
|
1356
|
-
assert_equal Net::HTTP::Persistent::EPOCH,
|
1186
|
+
assert c.http.started?
|
1187
|
+
assert c.http.finished?
|
1188
|
+
assert c.http.reset?
|
1189
|
+
assert_equal 0, c.requests
|
1190
|
+
assert_equal Net::HTTP::Persistent::EPOCH, c.last_use
|
1357
1191
|
end
|
1358
1192
|
|
1359
1193
|
def test_reset_host_down
|
1360
1194
|
c = basic_connection
|
1361
|
-
|
1362
|
-
def c.start; raise Errno::EHOSTDOWN end
|
1363
|
-
|
1195
|
+
c.last_use = Time.now
|
1196
|
+
def (c.http).start; raise Errno::EHOSTDOWN end
|
1197
|
+
c.requests = 5
|
1364
1198
|
|
1365
1199
|
e = assert_raises Net::HTTP::Persistent::Error do
|
1366
1200
|
@http.reset c
|
@@ -1372,20 +1206,20 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1372
1206
|
|
1373
1207
|
def test_reset_io_error
|
1374
1208
|
c = basic_connection
|
1375
|
-
|
1376
|
-
|
1209
|
+
c.last_use = Time.now
|
1210
|
+
c.requests = 5
|
1377
1211
|
|
1378
1212
|
@http.reset c
|
1379
1213
|
|
1380
|
-
assert c.started?
|
1381
|
-
assert c.finished?
|
1214
|
+
assert c.http.started?
|
1215
|
+
assert c.http.finished?
|
1382
1216
|
end
|
1383
1217
|
|
1384
1218
|
def test_reset_refused
|
1385
1219
|
c = basic_connection
|
1386
|
-
|
1387
|
-
def c.start; raise Errno::ECONNREFUSED end
|
1388
|
-
|
1220
|
+
c.last_use = Time.now
|
1221
|
+
def (c.http).start; raise Errno::ECONNREFUSED end
|
1222
|
+
c.requests = 5
|
1389
1223
|
|
1390
1224
|
e = assert_raises Net::HTTP::Persistent::Error do
|
1391
1225
|
@http.reset c
|
@@ -1395,167 +1229,39 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1395
1229
|
assert_match __FILE__, e.backtrace.first
|
1396
1230
|
end
|
1397
1231
|
|
1398
|
-
def test_retry_change_requests_equals
|
1399
|
-
get = Net::HTTP::Get.new('/')
|
1400
|
-
post = Net::HTTP::Post.new('/')
|
1401
|
-
|
1402
|
-
refute @http.retry_change_requests
|
1403
|
-
|
1404
|
-
if RUBY_1 then
|
1405
|
-
assert @http.can_retry?(get)
|
1406
|
-
else
|
1407
|
-
assert @http.can_retry?(get)
|
1408
|
-
end
|
1409
|
-
refute @http.can_retry?(get, true)
|
1410
|
-
refute @http.can_retry?(post)
|
1411
|
-
|
1412
|
-
@http.retry_change_requests = true
|
1413
|
-
|
1414
|
-
assert @http.retry_change_requests
|
1415
|
-
|
1416
|
-
if RUBY_1 then
|
1417
|
-
assert @http.can_retry?(get)
|
1418
|
-
else
|
1419
|
-
assert @http.can_retry?(get)
|
1420
|
-
refute @http.can_retry?(get, true)
|
1421
|
-
end
|
1422
|
-
|
1423
|
-
assert @http.can_retry?(post)
|
1424
|
-
end
|
1425
|
-
|
1426
1232
|
def test_shutdown
|
1427
|
-
ssl_conns
|
1428
1233
|
c = connection
|
1429
|
-
rs = reqs
|
1430
|
-
ts = touts
|
1431
1234
|
|
1432
1235
|
orig = @http
|
1433
|
-
@http = Net::HTTP::Persistent.new 'name'
|
1236
|
+
@http = Net::HTTP::Persistent.new name: 'name'
|
1434
1237
|
c2 = connection
|
1435
1238
|
|
1436
1239
|
orig.shutdown
|
1437
1240
|
|
1438
1241
|
@http = orig
|
1439
1242
|
|
1440
|
-
assert c.finished?, 'last-generation connection must be finished'
|
1441
|
-
refute c2.finished?, 'present generation connection must not be finished'
|
1442
|
-
|
1443
|
-
refute_same rs, reqs
|
1444
|
-
refute_same ts, touts
|
1445
|
-
|
1446
|
-
assert_empty conns
|
1447
|
-
assert_empty ssl_conns
|
1448
|
-
|
1449
|
-
assert_empty reqs
|
1450
|
-
assert_empty touts
|
1243
|
+
assert c.http.finished?, 'last-generation connection must be finished'
|
1244
|
+
refute c2.http.finished?, 'present generation connection must not be finished'
|
1451
1245
|
end
|
1452
1246
|
|
1453
|
-
def
|
1454
|
-
conns
|
1455
|
-
ssl_conns
|
1456
|
-
|
1457
|
-
t = Thread.new do
|
1458
|
-
c = connection
|
1459
|
-
ssl_conns
|
1460
|
-
conns
|
1461
|
-
reqs
|
1462
|
-
|
1463
|
-
Thread.stop
|
1464
|
-
|
1465
|
-
c
|
1466
|
-
end
|
1467
|
-
|
1468
|
-
Thread.pass until t.status == 'sleep'
|
1469
|
-
|
1470
|
-
c = connection
|
1471
|
-
|
1472
|
-
assert_nil @http.shutdown_in_all_threads
|
1473
|
-
|
1474
|
-
assert c.finished?, 'connection in same thread must be finished'
|
1475
|
-
|
1476
|
-
assert_empty Thread.current[@http.generation_key]
|
1477
|
-
|
1478
|
-
assert_nil Thread.current[@http.request_key]
|
1479
|
-
|
1480
|
-
t.run
|
1481
|
-
assert t.value.finished?, 'connection in other thread must be finished'
|
1482
|
-
|
1483
|
-
assert_empty t[@http.generation_key]
|
1484
|
-
|
1485
|
-
assert_nil t[@http.request_key]
|
1486
|
-
end
|
1487
|
-
|
1488
|
-
def test_shutdown_no_connections
|
1489
|
-
@http.shutdown
|
1490
|
-
|
1491
|
-
assert_nil Thread.current[@http.generation_key]
|
1492
|
-
assert_nil Thread.current[@http.ssl_generation_key]
|
1493
|
-
|
1494
|
-
assert_nil Thread.current[@http.request_key]
|
1495
|
-
assert_nil Thread.current[@http.timeout_key]
|
1496
|
-
end
|
1497
|
-
|
1498
|
-
def test_shutdown_not_started
|
1499
|
-
ssl_conns
|
1500
|
-
|
1501
|
-
c = basic_connection
|
1502
|
-
def c.finish() raise IOError end
|
1503
|
-
|
1504
|
-
conns[0]["#{@uri.host}:#{@uri.port}"] = c
|
1505
|
-
|
1506
|
-
@http.shutdown
|
1507
|
-
|
1508
|
-
assert_empty Thread.current[@http.generation_key]
|
1509
|
-
assert_empty Thread.current[@http.ssl_generation_key]
|
1510
|
-
|
1511
|
-
assert_nil Thread.current[@http.request_key]
|
1512
|
-
assert_nil Thread.current[@http.timeout_key]
|
1513
|
-
end
|
1514
|
-
|
1515
|
-
def test_shutdown_ssl
|
1247
|
+
def test_ssl
|
1516
1248
|
skip 'OpenSSL is missing' unless HAVE_OPENSSL
|
1517
1249
|
|
1518
|
-
@
|
1519
|
-
|
1520
|
-
@http.connection_for @uri
|
1521
|
-
|
1522
|
-
@http.shutdown
|
1523
|
-
|
1524
|
-
assert_empty ssl_conns
|
1525
|
-
end
|
1526
|
-
|
1527
|
-
def test_shutdown_thread
|
1528
|
-
t = Thread.new do
|
1529
|
-
c = connection
|
1530
|
-
conns
|
1531
|
-
ssl_conns
|
1532
|
-
|
1533
|
-
reqs
|
1534
|
-
|
1535
|
-
Thread.stop
|
1536
|
-
|
1537
|
-
c
|
1538
|
-
end
|
1539
|
-
|
1540
|
-
Thread.pass until t.status == 'sleep'
|
1541
|
-
|
1542
|
-
c = connection
|
1543
|
-
|
1544
|
-
@http.shutdown t
|
1250
|
+
@http.verify_callback = :callback
|
1251
|
+
c = Net::HTTP.new 'localhost', 80
|
1545
1252
|
|
1546
|
-
|
1253
|
+
@http.ssl c
|
1547
1254
|
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
assert_nil t[@http.request_key]
|
1553
|
-
assert_nil t[@http.timeout_key]
|
1255
|
+
assert c.use_ssl?
|
1256
|
+
assert_equal OpenSSL::SSL::VERIFY_PEER, c.verify_mode
|
1257
|
+
assert_kind_of OpenSSL::X509::Store, c.cert_store
|
1258
|
+
assert_nil c.verify_callback
|
1554
1259
|
end
|
1555
1260
|
|
1556
|
-
def
|
1261
|
+
def test_ssl_ca_file
|
1557
1262
|
skip 'OpenSSL is missing' unless HAVE_OPENSSL
|
1558
1263
|
|
1264
|
+
@http.ca_file = 'ca_file'
|
1559
1265
|
@http.verify_callback = :callback
|
1560
1266
|
c = Net::HTTP.new 'localhost', 80
|
1561
1267
|
|
@@ -1563,14 +1269,13 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1563
1269
|
|
1564
1270
|
assert c.use_ssl?
|
1565
1271
|
assert_equal OpenSSL::SSL::VERIFY_PEER, c.verify_mode
|
1566
|
-
|
1567
|
-
assert_nil c.verify_callback
|
1272
|
+
assert_equal :callback, c.verify_callback
|
1568
1273
|
end
|
1569
1274
|
|
1570
|
-
def
|
1275
|
+
def test_ssl_ca_path
|
1571
1276
|
skip 'OpenSSL is missing' unless HAVE_OPENSSL
|
1572
1277
|
|
1573
|
-
@http.
|
1278
|
+
@http.ca_path = 'ca_path'
|
1574
1279
|
@http.verify_callback = :callback
|
1575
1280
|
c = Net::HTTP.new 'localhost', 80
|
1576
1281
|
|
@@ -1667,34 +1372,37 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1667
1372
|
end
|
1668
1373
|
end
|
1669
1374
|
|
1670
|
-
def
|
1671
|
-
|
1672
|
-
|
1673
|
-
uri1 = URI.parse 'https://one.example'
|
1375
|
+
def test_ssl_timeout_equals
|
1376
|
+
@http.ssl_timeout = :ssl_timeout
|
1674
1377
|
|
1675
|
-
|
1378
|
+
assert_equal :ssl_timeout, @http.ssl_timeout
|
1379
|
+
assert_equal 1, @http.ssl_generation
|
1380
|
+
end
|
1676
1381
|
|
1677
|
-
|
1678
|
-
|
1382
|
+
def test_ssl_version_equals
|
1383
|
+
@http.ssl_version = :ssl_version
|
1679
1384
|
|
1680
|
-
@http.
|
1385
|
+
assert_equal :ssl_version, @http.ssl_version
|
1386
|
+
assert_equal 1, @http.ssl_generation
|
1387
|
+
end
|
1681
1388
|
|
1682
|
-
|
1389
|
+
def test_min_version_equals
|
1390
|
+
@http.min_version = :min_version
|
1683
1391
|
|
1684
|
-
|
1685
|
-
|
1686
|
-
assert_empty reqs # sanity check, performed by #finish
|
1392
|
+
assert_equal :min_version, @http.min_version
|
1393
|
+
assert_equal 1, @http.ssl_generation
|
1687
1394
|
end
|
1688
1395
|
|
1689
|
-
def
|
1690
|
-
@http.
|
1396
|
+
def test_max_version_equals
|
1397
|
+
@http.max_version = :max_version
|
1691
1398
|
|
1692
|
-
assert_equal :
|
1399
|
+
assert_equal :max_version, @http.max_version
|
1693
1400
|
assert_equal 1, @http.ssl_generation
|
1694
|
-
end
|
1401
|
+
end
|
1695
1402
|
|
1696
1403
|
def test_start
|
1697
1404
|
c = basic_connection
|
1405
|
+
c = c.http
|
1698
1406
|
|
1699
1407
|
@http.socket_options << [Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1]
|
1700
1408
|
@http.debug_output = $stderr
|
@@ -1722,6 +1430,13 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1722
1430
|
assert_equal 1, @http.ssl_generation
|
1723
1431
|
end
|
1724
1432
|
|
1433
|
+
def test_verify_depth_equals
|
1434
|
+
@http.verify_depth = :verify_depth
|
1435
|
+
|
1436
|
+
assert_equal :verify_depth, @http.verify_depth
|
1437
|
+
assert_equal 1, @http.ssl_generation
|
1438
|
+
end
|
1439
|
+
|
1725
1440
|
def test_verify_mode_equals
|
1726
1441
|
@http.verify_mode = :verify_mode
|
1727
1442
|
|
@@ -1729,5 +1444,15 @@ class TestNetHttpPersistent < Minitest::Test
|
|
1729
1444
|
assert_equal 1, @http.ssl_generation
|
1730
1445
|
end
|
1731
1446
|
|
1447
|
+
def test_connection_pool_after_fork
|
1448
|
+
# ConnectionPool 2.4+ calls `checkin(force: true)` after fork
|
1449
|
+
@http.pool.checkin(force: true)
|
1450
|
+
|
1451
|
+
@http.pool.checkout ['example.com', 80, nil, nil, nil, nil]
|
1452
|
+
@http.pool.checkin(force: true)
|
1453
|
+
@http.pool.reload do |connection|
|
1454
|
+
connection.close
|
1455
|
+
end
|
1456
|
+
end
|
1732
1457
|
end
|
1733
1458
|
|