net-http-persistent 2.9.4 → 4.0.1

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.
@@ -0,0 +1,40 @@
1
+ ##
2
+ # A Net::HTTP connection wrapper that holds extra information for managing the
3
+ # connection's lifetime.
4
+
5
+ class Net::HTTP::Persistent::Connection # :nodoc:
6
+
7
+ attr_accessor :http
8
+
9
+ attr_accessor :last_use
10
+
11
+ attr_accessor :requests
12
+
13
+ attr_accessor :ssl_generation
14
+
15
+ def initialize http_class, http_args, ssl_generation
16
+ @http = http_class.new(*http_args)
17
+ @ssl_generation = ssl_generation
18
+
19
+ reset
20
+ end
21
+
22
+ def finish
23
+ @http.finish
24
+ rescue IOError
25
+ ensure
26
+ reset
27
+ end
28
+
29
+ def reset
30
+ @last_use = Net::HTTP::Persistent::EPOCH
31
+ @requests = 0
32
+ end
33
+
34
+ def ressl ssl_generation
35
+ @ssl_generation = ssl_generation
36
+
37
+ finish
38
+ end
39
+
40
+ end
@@ -0,0 +1,53 @@
1
+ class Net::HTTP::Persistent::Pool < ConnectionPool # :nodoc:
2
+
3
+ attr_reader :available # :nodoc:
4
+ attr_reader :key # :nodoc:
5
+
6
+ def initialize(options = {}, &block)
7
+ super
8
+
9
+ @available = Net::HTTP::Persistent::TimedStackMulti.new(@size, &block)
10
+ @key = "current-#{@available.object_id}"
11
+ end
12
+
13
+ def checkin net_http_args
14
+ stack = Thread.current[@key][net_http_args] ||= []
15
+
16
+ raise ConnectionPool::Error, 'no connections are checked out' if
17
+ stack.empty?
18
+
19
+ conn = stack.pop
20
+
21
+ if stack.empty?
22
+ @available.push conn, connection_args: net_http_args
23
+
24
+ Thread.current[@key].delete(net_http_args)
25
+ Thread.current[@key] = nil if Thread.current[@key].empty?
26
+ end
27
+
28
+ nil
29
+ end
30
+
31
+ def checkout net_http_args
32
+ stacks = Thread.current[@key] ||= {}
33
+ stack = stacks[net_http_args] ||= []
34
+
35
+ if stack.empty? then
36
+ conn = @available.pop connection_args: net_http_args
37
+ else
38
+ conn = stack.last
39
+ end
40
+
41
+ stack.push conn
42
+
43
+ conn
44
+ end
45
+
46
+ def shutdown
47
+ Thread.current[@key] = nil
48
+ super
49
+ end
50
+ end
51
+
52
+ require_relative 'timed_stack_multi'
53
+
@@ -0,0 +1,79 @@
1
+ class Net::HTTP::Persistent::TimedStackMulti < ConnectionPool::TimedStack # :nodoc:
2
+
3
+ ##
4
+ # Returns a new hash that has arrays for keys
5
+ #
6
+ # Using a class method to limit the bindings referenced by the hash's
7
+ # default_proc
8
+
9
+ def self.hash_of_arrays # :nodoc:
10
+ Hash.new { |h,k| h[k] = [] }
11
+ end
12
+
13
+ def initialize(size = 0, &block)
14
+ super
15
+
16
+ @enqueued = 0
17
+ @ques = self.class.hash_of_arrays
18
+ @lru = {}
19
+ @key = :"connection_args-#{object_id}"
20
+ end
21
+
22
+ def empty?
23
+ (@created - @enqueued) >= @max
24
+ end
25
+
26
+ def length
27
+ @max - @created + @enqueued
28
+ end
29
+
30
+ private
31
+
32
+ def connection_stored? options = {} # :nodoc:
33
+ !@ques[options[:connection_args]].empty?
34
+ end
35
+
36
+ def fetch_connection options = {} # :nodoc:
37
+ connection_args = options[:connection_args]
38
+
39
+ @enqueued -= 1
40
+ lru_update connection_args
41
+ @ques[connection_args].pop
42
+ end
43
+
44
+ def lru_update connection_args # :nodoc:
45
+ @lru.delete connection_args
46
+ @lru[connection_args] = true
47
+ end
48
+
49
+ def shutdown_connections # :nodoc:
50
+ @ques.each_key do |key|
51
+ super connection_args: key
52
+ end
53
+ end
54
+
55
+ def store_connection obj, options = {} # :nodoc:
56
+ @ques[options[:connection_args]].push obj
57
+ @enqueued += 1
58
+ end
59
+
60
+ def try_create options = {} # :nodoc:
61
+ connection_args = options[:connection_args]
62
+
63
+ if @created >= @max && @enqueued >= 1
64
+ oldest, = @lru.first
65
+ @lru.delete oldest
66
+ @ques[oldest].pop
67
+
68
+ @created -= 1
69
+ end
70
+
71
+ if @created < @max
72
+ @created += 1
73
+ lru_update connection_args
74
+ return @create_block.call(connection_args)
75
+ end
76
+ end
77
+
78
+ end
79
+
@@ -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 = URI.parse 'http://example.com/path'
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
- c = BasicConnection.new
134
- conns[0]["#{@uri.host}:#{@uri.port}"] = c
135
- c
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
- c = basic_connection
140
- touts[c.object_id] = Time.now
136
+ def connection uri = @uri
137
+ @uri = uri
138
+
139
+ connection = basic_connection
140
+ connection.last_use = Time.now
141
141
 
142
- def c.request(req)
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
- c
152
+ connection
153
153
  end
154
154
 
155
- def conns
156
- Thread.current[@http.generation_key] ||= Hash.new { |h,k| h[k] = {} }
157
- end
155
+ def ssl_connection
156
+ raise "#{@uri} is not HTTPS" unless @uri.scheme.downcase == 'https'
158
157
 
159
- def reqs
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
- def ssl_conns
164
- Thread.current[@http.ssl_generation_key] ||= Hash.new { |h,k| h[k] = {} }
165
- end
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
- def ssl_connection generation = 0
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
- def touts
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 nil, proxy_uri
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 test_can_retry_eh_change_requests
228
- post = Net::HTTP::Post.new '/'
219
+ def test_ca_path_equals
220
+ @http.ca_path = :ca_path
229
221
 
230
- refute @http.can_retry? post
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,162 @@ 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
- c = @http.connection_for @uri
251
+ @http.max_retries = 5
279
252
 
280
- assert_kind_of @http_class, c
253
+ used = @http.connection_for @uri do |c|
254
+ assert_kind_of Net::HTTP, c.http
281
255
 
282
- assert c.started?
283
- refute c.proxy?
256
+ assert c.http.started?
257
+ refute c.http.proxy?
284
258
 
285
- assert_equal 123, c.open_timeout
286
- assert_equal 321, c.read_timeout
287
- assert_equal 42, c.keep_alive_timeout unless RUBY_1
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
- assert_includes conns[0].keys, 'example.com:80'
290
- assert_same c, conns[0]['example.com:80']
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
- c = @http.connection_for @uri
301
-
302
- assert c.started?
278
+ @http.connection_for @uri do |c|
279
+ assert c.http.started?
303
280
 
304
- assert_equal 5, c.read_timeout
281
+ assert_equal 5, c.http.read_timeout
305
282
 
306
- assert_same cached, c
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
- assert_includes conns.keys, 'example.com:80'
324
- assert_same c, conns[0]['example.com:80']
296
+ @http.connection_for @uri do |c|
297
+ assert c.http.started?
325
298
 
326
- socket = c.instance_variable_get :@socket
299
+ socket = c.http.instance_variable_get :@socket
327
300
 
328
- refute_includes socket.io.instance_variables, :@setsockopt
329
- refute_includes socket.io.instance_variables, '@setsockopt'
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
- c = @http.connection_for @uri
337
-
338
- assert c.started?
339
- assert_equal io, c.instance_variable_get(:@debug_output)
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
- conns[0]['example.com:80'] = cached
349
- reqs[cached.object_id] = 10
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
- c = @http.connection_for @uri
355
-
356
- assert c.started?
324
+ @http.connection_for @uri do |c|
325
+ assert c.http.started?
357
326
 
358
- assert_same cached, c
327
+ assert_same cached, c
359
328
 
360
- assert_equal 0, reqs[cached.object_id],
361
- 'connection reset due to timeout'
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
- conns[0]['example.com:80'] = cached
368
- reqs[cached.object_id] = 10
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
- c = @http.connection_for @uri
374
-
375
- assert c.started?
341
+ @http.connection_for @uri do |c|
342
+ assert c.http.started?
376
343
 
377
- assert_same cached, c
344
+ assert_same cached, c
378
345
 
379
- assert_equal 10, reqs[cached.object_id],
380
- 'connection reset despite no timeout'
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
- conns[0]['example.com:80'] = cached
387
- reqs[cached.object_id] = 10
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
- assert_same cached, c
395
- assert_equal 0, reqs[cached.object_id],
396
- 'connection not reset due to timeout'
397
- end
356
+ @http.connection_for @uri do |c|
357
+ assert c.http.started?
398
358
 
399
- def test_connection_for_refused
400
- Net::HTTP.use_connect :refused_connect
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
411
365
  skip 'OpenSSL is missing' unless HAVE_OPENSSL
412
366
 
413
367
  uri = URI.parse 'https://example.com/path'
414
- c = @http.connection_for uri
415
368
 
416
- assert c.started?
417
- assert c.use_ssl?
369
+ @http.connection_for uri do |c|
370
+ assert c.http.started?
371
+ assert c.http.use_ssl?
418
372
 
419
- @http.finish c
373
+ @http.finish c
420
374
 
421
- refute c.started?
375
+ refute c.http.started?
376
+ end
422
377
 
423
- c2 = @http.connection_for uri
378
+ @http.connection_for uri do |c2|
379
+ assert c2.http.started?
380
+ end
381
+ end
424
382
 
425
- assert c2.started?
383
+ def test_connection_for_ipv6
384
+ @http.connection_for @uri_v6 do |c|
385
+ assert_equal '2001:db8::1', c.http.address
386
+ end
426
387
  end
427
388
 
428
389
  def test_connection_for_host_down
429
- cached = basic_connection
430
- def cached.start; raise Errno::EHOSTDOWN end
431
- def cached.started?; false end
432
- conns[0]['example.com:80'] = cached
390
+ c = basic_connection
391
+ def (c.http).start; raise Errno::EHOSTDOWN end
392
+ def (c.http).started?; false end
433
393
 
434
394
  e = assert_raises Net::HTTP::Persistent::Error do
435
- @http.connection_for @uri
395
+ @http.connection_for @uri do end
436
396
  end
437
397
 
438
398
  assert_equal 'host down: example.com:80', e.message
@@ -440,8 +400,10 @@ class TestNetHttpPersistent < Minitest::Test
440
400
 
441
401
  def test_connection_for_http_class_with_fakeweb
442
402
  Object.send :const_set, :FakeWeb, nil
443
- c = @http.connection_for @uri
444
- assert_instance_of Net::HTTP, c
403
+
404
+ @http.connection_for @uri do |c|
405
+ assert_instance_of Net::HTTP, c.http
406
+ end
445
407
  ensure
446
408
  if Object.const_defined?(:FakeWeb) then
447
409
  Object.send :remove_const, :FakeWeb
@@ -450,8 +412,9 @@ class TestNetHttpPersistent < Minitest::Test
450
412
 
451
413
  def test_connection_for_http_class_with_webmock
452
414
  Object.send :const_set, :WebMock, nil
453
- c = @http.connection_for @uri
454
- assert_instance_of Net::HTTP, c
415
+ @http.connection_for @uri do |c|
416
+ assert_instance_of Net::HTTP, c.http
417
+ end
455
418
  ensure
456
419
  if Object.const_defined?(:WebMock) then
457
420
  Object.send :remove_const, :WebMock
@@ -460,8 +423,9 @@ class TestNetHttpPersistent < Minitest::Test
460
423
 
461
424
  def test_connection_for_http_class_with_artifice
462
425
  Object.send :const_set, :Artifice, nil
463
- c = @http.connection_for @uri
464
- assert_instance_of Net::HTTP, c
426
+ @http.connection_for @uri do |c|
427
+ assert_instance_of Net::HTTP, c.http
428
+ end
465
429
  ensure
466
430
  if Object.const_defined?(:Artifice) then
467
431
  Object.send :remove_const, :Artifice
@@ -469,23 +433,12 @@ class TestNetHttpPersistent < Minitest::Test
469
433
  end
470
434
 
471
435
  def test_connection_for_name
472
- http = Net::HTTP::Persistent.new 'name'
436
+ http = Net::HTTP::Persistent.new name: 'name'
473
437
  uri = URI.parse 'http://example/'
474
438
 
475
- c = http.connection_for uri
476
-
477
- assert c.started?
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
439
+ http.connection_for uri do |c|
440
+ assert c.http.started?
441
+ end
489
442
  end
490
443
 
491
444
  def test_connection_for_proxy
@@ -493,16 +446,20 @@ class TestNetHttpPersistent < Minitest::Test
493
446
  uri.user = 'johndoe'
494
447
  uri.password = 'muffins'
495
448
 
496
- http = Net::HTTP::Persistent.new nil, uri
449
+ http = Net::HTTP::Persistent.new proxy: uri
497
450
 
498
- c = http.connection_for @uri
451
+ used = http.connection_for @uri do |c|
452
+ assert c.http.started?
453
+ assert c.http.proxy?
499
454
 
500
- assert c.started?
501
- assert c.proxy?
455
+ c
456
+ end
502
457
 
503
- assert_includes conns[1].keys,
504
- 'example.com:80:proxy.example:80:johndoe:muffins'
505
- assert_same c, conns[1]['example.com:80:proxy.example:80:johndoe:muffins']
458
+ stored = http.pool.checkout ['example.com', 80,
459
+ 'proxy.example', 80,
460
+ 'johndoe', 'muffins']
461
+
462
+ assert_same used, stored
506
463
  end
507
464
 
508
465
  def test_connection_for_proxy_unescaped
@@ -511,25 +468,28 @@ class TestNetHttpPersistent < Minitest::Test
511
468
  uri.password = 'muf%3Afins'
512
469
  uri.freeze
513
470
 
514
- http = Net::HTTP::Persistent.new nil, uri
515
- c = http.connection_for @uri
471
+ http = Net::HTTP::Persistent.new proxy: uri
472
+
473
+ http.connection_for @uri do end
474
+
475
+ stored = http.pool.checkout ['example.com', 80,
476
+ 'proxy.example', 80,
477
+ 'john@doe', 'muf:fins']
516
478
 
517
- assert_includes conns[1].keys,
518
- 'example.com:80:proxy.example:80:john@doe:muf:fins'
479
+ assert stored
519
480
  end
520
481
 
521
482
  def test_connection_for_proxy_host_down
522
483
  Net::HTTP.use_connect :host_down_connect
523
- Net::HTTP::Persistent::SSLReuse.use_connect :host_down_connect
524
484
 
525
485
  uri = URI.parse 'http://proxy.example'
526
486
  uri.user = 'johndoe'
527
487
  uri.password = 'muffins'
528
488
 
529
- http = Net::HTTP::Persistent.new nil, uri
489
+ http = Net::HTTP::Persistent.new proxy: uri
530
490
 
531
491
  e = assert_raises Net::HTTP::Persistent::Error do
532
- http.connection_for @uri
492
+ http.connection_for @uri do end
533
493
  end
534
494
 
535
495
  assert_equal 'host down: proxy.example:80', e.message
@@ -537,16 +497,15 @@ class TestNetHttpPersistent < Minitest::Test
537
497
 
538
498
  def test_connection_for_proxy_refused
539
499
  Net::HTTP.use_connect :refused_connect
540
- Net::HTTP::Persistent::SSLReuse.use_connect :refused_connect
541
500
 
542
501
  uri = URI.parse 'http://proxy.example'
543
502
  uri.user = 'johndoe'
544
503
  uri.password = 'muffins'
545
504
 
546
- http = Net::HTTP::Persistent.new nil, uri
505
+ http = Net::HTTP::Persistent.new proxy: uri
547
506
 
548
507
  e = assert_raises Net::HTTP::Persistent::Error do
549
- http.connection_for @uri
508
+ http.connection_for @uri do end
550
509
  end
551
510
 
552
511
  assert_equal 'connection refused: proxy.example:80', e.message
@@ -558,38 +517,52 @@ class TestNetHttpPersistent < Minitest::Test
558
517
  uri.password = 'muffins'
559
518
  uri.query = 'no_proxy=example.com'
560
519
 
561
- http = Net::HTTP::Persistent.new nil, uri
520
+ http = Net::HTTP::Persistent.new proxy: uri
562
521
 
563
- c = http.connection_for @uri
522
+ http.connection_for @uri do |c|
523
+ assert c.http.started?
524
+ refute c.http.proxy?
525
+ end
564
526
 
565
- assert c.started?
566
- refute c.proxy?
527
+ stored = http.pool.checkout ['example.com', 80]
567
528
 
568
- assert_includes conns[1].keys, 'example.com:80'
569
- assert_same c, conns[1]['example.com:80']
529
+ assert stored
530
+ end
531
+
532
+ def test_connection_for_no_proxy_from_env
533
+ ENV['http_proxy'] = 'proxy.example'
534
+ ENV['no_proxy'] = 'localhost, example.com,'
535
+ ENV['proxy_user'] = 'johndoe'
536
+ ENV['proxy_password'] = 'muffins'
537
+
538
+ http = Net::HTTP::Persistent.new proxy: :ENV
539
+
540
+ http.connection_for @uri do |c|
541
+ assert c.http.started?
542
+ refute c.http.proxy?
543
+ refute c.http.proxy_from_env?
544
+ end
570
545
  end
571
546
 
572
547
  def test_connection_for_refused
573
- cached = basic_connection
574
- def cached.start; raise Errno::ECONNREFUSED end
575
- def cached.started?; false end
576
- conns[0]['example.com:80'] = cached
548
+ Net::HTTP.use_connect :refused_connect
577
549
 
578
550
  e = assert_raises Net::HTTP::Persistent::Error do
579
- @http.connection_for @uri
551
+ @http.connection_for @uri do end
580
552
  end
581
553
 
582
- assert_match %r%connection refused%, e.message
554
+ assert_equal 'connection refused: example.com:80', e.message
583
555
  end
584
556
 
585
557
  def test_connection_for_ssl
586
558
  skip 'OpenSSL is missing' unless HAVE_OPENSSL
587
559
 
588
560
  uri = URI.parse 'https://example.com/path'
589
- c = @http.connection_for uri
590
561
 
591
- assert c.started?
592
- assert c.use_ssl?
562
+ @http.connection_for uri do |c|
563
+ assert c.http.started?
564
+ assert c.http.use_ssl?
565
+ end
593
566
  end
594
567
 
595
568
  def test_connection_for_ssl_cached
@@ -597,11 +570,11 @@ class TestNetHttpPersistent < Minitest::Test
597
570
 
598
571
  @uri = URI.parse 'https://example.com/path'
599
572
 
600
- cached = ssl_connection 0
601
-
602
- c = @http.connection_for @uri
573
+ cached = ssl_connection
603
574
 
604
- assert_same cached, c
575
+ @http.connection_for @uri do |c|
576
+ assert_same cached, c
577
+ end
605
578
  end
606
579
 
607
580
  def test_connection_for_ssl_cached_reconnect
@@ -611,46 +584,38 @@ class TestNetHttpPersistent < Minitest::Test
611
584
 
612
585
  cached = ssl_connection
613
586
 
614
- @http.reconnect_ssl
587
+ ssl_generation = @http.ssl_generation
615
588
 
616
- c = @http.connection_for @uri
589
+ @http.reconnect_ssl
617
590
 
618
- refute_same cached, c
591
+ @http.connection_for @uri do |c|
592
+ assert_same cached, c
593
+ refute_equal ssl_generation, c.ssl_generation
594
+ end
619
595
  end
620
596
 
621
597
  def test_connection_for_ssl_case
622
598
  skip 'OpenSSL is missing' unless HAVE_OPENSSL
623
599
 
624
600
  uri = URI.parse 'HTTPS://example.com/path'
625
- c = @http.connection_for uri
626
-
627
- assert c.started?
628
- assert c.use_ssl?
601
+ @http.connection_for uri do |c|
602
+ assert c.http.started?
603
+ assert c.http.use_ssl?
604
+ end
629
605
  end
630
606
 
631
607
  def test_connection_for_timeout
632
608
  cached = basic_connection
633
- cached.start
634
- reqs[cached.object_id] = 10
635
- touts[cached.object_id] = Time.now - 6
636
- conns[0]['example.com:80'] = cached
609
+ cached.http.start
610
+ cached.requests = 10
611
+ cached.last_use = Time.now - 6
637
612
 
638
- c = @http.connection_for @uri
639
-
640
- assert c.started?
641
- assert_equal 0, reqs[c.object_id]
642
-
643
- assert_same cached, c
644
- end
613
+ @http.connection_for @uri do |c|
614
+ assert c.http.started?
615
+ assert_equal 0, c.requests
645
616
 
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
617
+ assert_same cached, c
618
+ end
654
619
  end
655
620
 
656
621
  def test_escape
@@ -667,8 +632,8 @@ class TestNetHttpPersistent < Minitest::Test
667
632
 
668
633
  def test_expired_eh
669
634
  c = basic_connection
670
- reqs[c.object_id] = 0
671
- touts[c.object_id] = Time.now - 11
635
+ c.requests = 0
636
+ c.last_use = Time.now - 11
672
637
 
673
638
  @http.idle_timeout = 0
674
639
  assert @http.expired? c
@@ -688,41 +653,59 @@ class TestNetHttpPersistent < Minitest::Test
688
653
 
689
654
  def test_expired_due_to_max_requests
690
655
  c = basic_connection
691
- reqs[c.object_id] = 0
692
- touts[c.object_id] = Time.now
656
+ c.requests = 0
657
+ c.last_use = Time.now
693
658
 
694
659
  refute @http.expired? c
695
660
 
696
- reqs[c.object_id] = 10
661
+ c.requests = 10
697
662
  refute @http.expired? c
698
663
 
699
664
  @http.max_requests = 10
700
665
  assert @http.expired? c
701
666
 
702
- reqs[c.object_id] = 9
667
+ c.requests = 9
703
668
  refute @http.expired? c
704
669
  end
705
670
 
706
671
  def test_finish
707
672
  c = basic_connection
708
- reqs[c.object_id] = 5
673
+ c.requests = 5
674
+ c.http.instance_variable_set(:@last_communicated, Process.clock_gettime(Process::CLOCK_MONOTONIC))
709
675
 
710
676
  @http.finish c
711
677
 
712
- refute c.started?
713
- assert c.finished?
714
- assert_equal 0, reqs[c.object_id]
678
+ refute c.http.started?
679
+ assert c.http.finished?
680
+
681
+ assert_equal 0, c.requests
682
+ assert_equal Net::HTTP::Persistent::EPOCH, c.last_use
683
+ assert_nil c.http.instance_variable_get(:@last_communicated)
715
684
  end
716
685
 
717
686
  def test_finish_io_error
718
687
  c = basic_connection
719
- def c.finish; @finished += 1; raise IOError end
720
- reqs[c.object_id] = 5
688
+ def (c.http).finish; @finished += 1; raise IOError end
689
+ c.requests = 5
690
+
691
+ @http.finish c
692
+
693
+ refute c.http.started?
694
+ assert c.http.finished?
695
+ end
696
+
697
+ def test_finish_ssl_no_session_reuse
698
+ http = Net::HTTP.new 'localhost', 443, ssl: true
699
+ http.instance_variable_set :@ssl_session, :something
700
+
701
+ c = Net::HTTP::Persistent::Connection.allocate
702
+ c.instance_variable_set :@http, http
703
+
704
+ @http.reuse_ssl_sessions = false
721
705
 
722
706
  @http.finish c
723
707
 
724
- refute c.started?
725
- assert c.finished?
708
+ assert_nil c.http.instance_variable_get :@ssl_session
726
709
  end
727
710
 
728
711
  def test_http_version
@@ -735,23 +718,21 @@ class TestNetHttpPersistent < Minitest::Test
735
718
  assert_equal '1.1', @http.http_version(@uri)
736
719
  end
737
720
 
738
- def test_idempotent_eh
739
- assert @http.idempotent? Net::HTTP::Delete.new '/'
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 '/'
721
+ def test_http_version_IPv6
722
+ assert_nil @http.http_version @uri_v6
745
723
 
746
- refute @http.idempotent? Net::HTTP::Post.new '/'
747
- end
724
+ connection @uri_v6
748
725
 
749
- def test_max_age
750
- assert_in_delta Time.now - 5, @http.max_age
726
+ @http.request @uri_v6
751
727
 
752
- @http.idle_timeout = nil
728
+ assert_equal '1.1', @http.http_version(@uri_v6)
729
+ end
730
+
731
+ def test_max_retries_equals
732
+ @http.max_retries = 5
753
733
 
754
- assert_in_delta Time.now + 1, @http.max_age
734
+ assert_equal 5, @http.max_retries
735
+ assert_equal 1, @http.generation
755
736
  end
756
737
 
757
738
  def test_normalize_uri
@@ -774,8 +755,7 @@ class TestNetHttpPersistent < Minitest::Test
774
755
  skip 'net-http-pipeline not installed' unless defined?(Net::HTTP::Pipeline)
775
756
 
776
757
  cached = basic_connection
777
- cached.start
778
- conns['example.com:80'] = cached
758
+ cached.http.start
779
759
 
780
760
  requests = [
781
761
  Net::HTTP::Get.new((@uri + '1').request_uri),
@@ -810,7 +790,7 @@ class TestNetHttpPersistent < Minitest::Test
810
790
  def test_proxy_equals_nil
811
791
  @http.proxy = nil
812
792
 
813
- assert_equal nil, @http.proxy_uri
793
+ assert_nil @http.proxy_uri
814
794
 
815
795
  assert_equal 1, @http.generation, 'generation'
816
796
  assert_equal 1, @http.ssl_generation, 'ssl_generation'
@@ -824,6 +804,14 @@ class TestNetHttpPersistent < Minitest::Test
824
804
  assert_equal proxy_uri, @http.proxy_uri
825
805
  end
826
806
 
807
+ def test_proxy_equals_uri_IPv6
808
+ proxy_uri = @uri_v6
809
+
810
+ @http.proxy = proxy_uri
811
+
812
+ assert_equal proxy_uri, @http.proxy_uri
813
+ end
814
+
827
815
  def test_proxy_from_env
828
816
  ENV['http_proxy'] = 'proxy.example'
829
817
  ENV['http_proxy_user'] = 'johndoe'
@@ -935,18 +923,47 @@ class TestNetHttpPersistent < Minitest::Test
935
923
  end
936
924
 
937
925
  def test_reconnect_ssl
938
- result = @http.reconnect_ssl
926
+ skip 'OpenSSL is missing' unless HAVE_OPENSSL
939
927
 
940
- assert_equal 1, result
928
+ @uri = URI 'https://example.com'
929
+ now = Time.now
930
+
931
+ ssl_http = ssl_connection
932
+
933
+ def (ssl_http.http).finish
934
+ @started = 0
935
+ end
936
+
937
+ used1 = @http.connection_for @uri do |c|
938
+ c.requests = 1
939
+ c.last_use = now
940
+ c
941
+ end
942
+
943
+ assert_equal OpenSSL::SSL::VERIFY_PEER, used1.http.verify_mode
944
+
945
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
946
+ @http.reconnect_ssl
947
+
948
+ used2 = @http.connection_for @uri do |c|
949
+ c
950
+ end
951
+
952
+ assert_same used1, used2
953
+
954
+ assert_equal OpenSSL::SSL::VERIFY_NONE, used2.http.verify_mode,
955
+ 'verify mode must change'
956
+ assert_equal 0, used2.requests
957
+ assert_equal Net::HTTP::Persistent::EPOCH, used2.last_use
941
958
  end
942
959
 
943
- def test_request
960
+ def test_requestx
944
961
  @http.override_headers['user-agent'] = 'test ua'
945
962
  @http.headers['accept'] = 'text/*'
946
963
  c = connection
947
964
 
948
965
  res = @http.request @uri
949
- req = c.req
966
+ req = c.http.req
950
967
 
951
968
  assert_kind_of Net::HTTPResponse, res
952
969
 
@@ -959,86 +976,9 @@ class TestNetHttpPersistent < Minitest::Test
959
976
  assert_equal 'keep-alive', req['connection']
960
977
  assert_equal '30', req['keep-alive']
961
978
 
962
- assert_in_delta Time.now, touts[c.object_id]
963
-
964
- assert_equal 1, reqs[c.object_id]
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?
1009
- 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
979
+ assert_in_delta Time.now, c.last_use
1020
980
 
1021
- assert c.finished?
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
981
+ assert_equal 1, c.requests
1042
982
  end
1043
983
 
1044
984
  def test_request_block
@@ -1050,7 +990,7 @@ class TestNetHttpPersistent < Minitest::Test
1050
990
  body = r.read_body
1051
991
  end
1052
992
 
1053
- req = c.req
993
+ req = c.http.req
1054
994
 
1055
995
  assert_kind_of Net::HTTPResponse, res
1056
996
  refute_nil body
@@ -1061,17 +1001,17 @@ class TestNetHttpPersistent < Minitest::Test
1061
1001
  assert_equal '30', req['keep-alive']
1062
1002
  assert_match %r%test ua%, req['user-agent']
1063
1003
 
1064
- assert_equal 1, reqs[c.object_id]
1004
+ assert_equal 1, c.requests
1065
1005
  end
1066
1006
 
1067
1007
  def test_request_close_1_0
1068
1008
  c = connection
1069
1009
 
1070
- class << c
1010
+ class << c.http
1071
1011
  remove_method :request
1072
1012
  end
1073
1013
 
1074
- def c.request req
1014
+ def (c.http).request req
1075
1015
  @req = req
1076
1016
  r = Net::HTTPResponse.allocate
1077
1017
  r.instance_variable_set :@header, {}
@@ -1084,7 +1024,7 @@ class TestNetHttpPersistent < Minitest::Test
1084
1024
  request = Net::HTTP::Get.new @uri.request_uri
1085
1025
 
1086
1026
  res = @http.request @uri, request
1087
- req = c.req
1027
+ req = c.http.req
1088
1028
 
1089
1029
  assert_kind_of Net::HTTPResponse, res
1090
1030
 
@@ -1093,7 +1033,7 @@ class TestNetHttpPersistent < Minitest::Test
1093
1033
  assert_equal 'keep-alive', req['connection']
1094
1034
  assert_equal '30', req['keep-alive']
1095
1035
 
1096
- assert c.finished?
1036
+ assert c.http.finished?
1097
1037
  end
1098
1038
 
1099
1039
  def test_request_connection_close_request
@@ -1103,26 +1043,26 @@ class TestNetHttpPersistent < Minitest::Test
1103
1043
  request['connection'] = 'close'
1104
1044
 
1105
1045
  res = @http.request @uri, request
1106
- req = c.req
1046
+ req = c.http.req
1107
1047
 
1108
1048
  assert_kind_of Net::HTTPResponse, res
1109
1049
 
1110
1050
  assert_kind_of Net::HTTP::Get, req
1111
1051
  assert_equal '/path', req.path
1112
1052
  assert_equal 'close', req['connection']
1113
- assert_equal nil, req['keep-alive']
1053
+ assert_nil req['keep-alive']
1114
1054
 
1115
- assert c.finished?
1055
+ assert c.http.finished?
1116
1056
  end
1117
1057
 
1118
1058
  def test_request_connection_close_response
1119
1059
  c = connection
1120
1060
 
1121
- class << c
1061
+ class << c.http
1122
1062
  remove_method :request
1123
1063
  end
1124
1064
 
1125
- def c.request req
1065
+ def (c.http).request req
1126
1066
  @req = req
1127
1067
  r = Net::HTTPResponse.allocate
1128
1068
  r.instance_variable_set :@header, {}
@@ -1136,7 +1076,7 @@ class TestNetHttpPersistent < Minitest::Test
1136
1076
  request = Net::HTTP::Get.new @uri.request_uri
1137
1077
 
1138
1078
  res = @http.request @uri, request
1139
- req = c.req
1079
+ req = c.http.req
1140
1080
 
1141
1081
  assert_kind_of Net::HTTPResponse, res
1142
1082
 
@@ -1145,53 +1085,33 @@ class TestNetHttpPersistent < Minitest::Test
1145
1085
  assert_equal 'keep-alive', req['connection']
1146
1086
  assert_equal '30', req['keep-alive']
1147
1087
 
1148
- assert c.finished?
1088
+ assert c.http.finished?
1149
1089
  end
1150
1090
 
1151
1091
  def test_request_exception
1152
1092
  c = basic_connection
1153
- def c.request(*a) raise Exception, "very bad things happened" end
1093
+ def (c.http).request(*a)
1094
+ raise Exception, "very bad things happened"
1095
+ end
1154
1096
 
1155
1097
  assert_raises Exception do
1156
1098
  @http.request @uri
1157
1099
  end
1158
1100
 
1159
- assert_equal 0, reqs[c.object_id]
1160
- assert c.finished?
1101
+ assert_equal 0, c.requests
1102
+ assert c.http.finished?
1161
1103
  end
1162
1104
 
1163
1105
  def test_request_invalid
1164
1106
  c = basic_connection
1165
- def c.request(*a) raise Errno::EINVAL, "write" end
1107
+ def (c.http).request(*a) raise Errno::EINVAL, "write" end
1166
1108
 
1167
- e = assert_raises Net::HTTP::Persistent::Error do
1109
+ e = assert_raises Errno::EINVAL do
1168
1110
  @http.request @uri
1169
1111
  end
1170
1112
 
1171
- assert_equal 0, reqs[c.object_id]
1172
- assert_match %r%too many connection resets%, e.message
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?
1113
+ assert_equal 0, c.requests
1114
+ assert_match %r%Invalid argument - write%, e.message
1195
1115
  end
1196
1116
 
1197
1117
  def test_request_post
@@ -1200,96 +1120,11 @@ class TestNetHttpPersistent < Minitest::Test
1200
1120
  post = Net::HTTP::Post.new @uri.path
1201
1121
 
1202
1122
  @http.request @uri, post
1203
- req = c.req
1123
+ req = c.http.req
1204
1124
 
1205
1125
  assert_same post, req
1206
1126
  end
1207
1127
 
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
1128
  def test_request_setup
1294
1129
  @http.override_headers['user-agent'] = 'test ua'
1295
1130
  @http.headers['accept'] = 'text/*'
@@ -1308,59 +1143,51 @@ class TestNetHttpPersistent < Minitest::Test
1308
1143
  assert_equal '30', req['keep-alive']
1309
1144
  end
1310
1145
 
1311
- def test_request_setup_uri
1312
- uri = @uri + '?a=b'
1313
-
1314
- req = @http.request_setup uri
1146
+ def test_request_string
1147
+ @http.override_headers['user-agent'] = 'test ua'
1148
+ @http.headers['accept'] = 'text/*'
1149
+ c = connection
1315
1150
 
1316
- assert_kind_of Net::HTTP::Get, req
1317
- assert_equal '/path?a=b', req.path
1318
- end
1151
+ res = @http.request @uri.to_s
1152
+ req = c.http.req
1319
1153
 
1320
- def test_request_failed
1321
- c = basic_connection
1322
- reqs[c.object_id] = 1
1323
- touts[c.object_id] = Time.now
1154
+ assert_kind_of Net::HTTPResponse, res
1324
1155
 
1325
- original = nil
1156
+ assert_kind_of Net::HTTP::Get, req
1157
+ assert_equal '/path', req.path
1326
1158
 
1327
- begin
1328
- raise 'original'
1329
- rescue => original
1330
- end
1159
+ assert_equal 1, c.requests
1160
+ end
1331
1161
 
1332
- req = Net::HTTP::Get.new '/'
1333
-
1334
- e = assert_raises Net::HTTP::Persistent::Error do
1335
- @http.request_failed original, req, c
1336
- end
1162
+ def test_request_setup_uri
1163
+ uri = @uri + '?a=b'
1337
1164
 
1338
- assert_match "too many connection resets (due to original - RuntimeError)",
1339
- e.message
1165
+ req = @http.request_setup uri
1340
1166
 
1341
- assert_equal original.backtrace, e.backtrace
1167
+ assert_kind_of Net::HTTP::Get, req
1168
+ assert_equal '/path?a=b', req.path
1342
1169
  end
1343
1170
 
1344
1171
  def test_reset
1345
1172
  c = basic_connection
1346
- c.start
1347
- touts[c.object_id] = Time.now
1348
- reqs[c.object_id] = 5
1173
+ c.http.start
1174
+ c.last_use = Time.now
1175
+ c.requests = 5
1349
1176
 
1350
1177
  @http.reset c
1351
1178
 
1352
- assert c.started?
1353
- assert c.finished?
1354
- assert c.reset?
1355
- assert_equal 0, reqs[c.object_id]
1356
- assert_equal Net::HTTP::Persistent::EPOCH, touts[c.object_id]
1179
+ assert c.http.started?
1180
+ assert c.http.finished?
1181
+ assert c.http.reset?
1182
+ assert_equal 0, c.requests
1183
+ assert_equal Net::HTTP::Persistent::EPOCH, c.last_use
1357
1184
  end
1358
1185
 
1359
1186
  def test_reset_host_down
1360
1187
  c = basic_connection
1361
- touts[c.object_id] = Time.now
1362
- def c.start; raise Errno::EHOSTDOWN end
1363
- reqs[c.object_id] = 5
1188
+ c.last_use = Time.now
1189
+ def (c.http).start; raise Errno::EHOSTDOWN end
1190
+ c.requests = 5
1364
1191
 
1365
1192
  e = assert_raises Net::HTTP::Persistent::Error do
1366
1193
  @http.reset c
@@ -1372,20 +1199,20 @@ class TestNetHttpPersistent < Minitest::Test
1372
1199
 
1373
1200
  def test_reset_io_error
1374
1201
  c = basic_connection
1375
- touts[c.object_id] = Time.now
1376
- reqs[c.object_id] = 5
1202
+ c.last_use = Time.now
1203
+ c.requests = 5
1377
1204
 
1378
1205
  @http.reset c
1379
1206
 
1380
- assert c.started?
1381
- assert c.finished?
1207
+ assert c.http.started?
1208
+ assert c.http.finished?
1382
1209
  end
1383
1210
 
1384
1211
  def test_reset_refused
1385
1212
  c = basic_connection
1386
- touts[c.object_id] = Time.now
1387
- def c.start; raise Errno::ECONNREFUSED end
1388
- reqs[c.object_id] = 5
1213
+ c.last_use = Time.now
1214
+ def (c.http).start; raise Errno::ECONNREFUSED end
1215
+ c.requests = 5
1389
1216
 
1390
1217
  e = assert_raises Net::HTTP::Persistent::Error do
1391
1218
  @http.reset c
@@ -1395,167 +1222,39 @@ class TestNetHttpPersistent < Minitest::Test
1395
1222
  assert_match __FILE__, e.backtrace.first
1396
1223
  end
1397
1224
 
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
1225
  def test_shutdown
1427
- ssl_conns
1428
1226
  c = connection
1429
- rs = reqs
1430
- ts = touts
1431
1227
 
1432
1228
  orig = @http
1433
- @http = Net::HTTP::Persistent.new 'name'
1229
+ @http = Net::HTTP::Persistent.new name: 'name'
1434
1230
  c2 = connection
1435
1231
 
1436
1232
  orig.shutdown
1437
1233
 
1438
1234
  @http = orig
1439
1235
 
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
1451
- end
1452
-
1453
- def test_shutdown_in_all_threads
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]
1236
+ assert c.http.finished?, 'last-generation connection must be finished'
1237
+ refute c2.http.finished?, 'present generation connection must not be finished'
1513
1238
  end
1514
1239
 
1515
- def test_shutdown_ssl
1240
+ def test_ssl
1516
1241
  skip 'OpenSSL is missing' unless HAVE_OPENSSL
1517
1242
 
1518
- @uri = URI 'https://example'
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
1243
+ @http.verify_callback = :callback
1244
+ c = Net::HTTP.new 'localhost', 80
1545
1245
 
1546
- refute c.finished?
1246
+ @http.ssl c
1547
1247
 
1548
- t.run
1549
- assert t.value.finished?
1550
- assert_empty t[@http.generation_key]
1551
- assert_empty t[@http.ssl_generation_key]
1552
- assert_nil t[@http.request_key]
1553
- assert_nil t[@http.timeout_key]
1248
+ assert c.use_ssl?
1249
+ assert_equal OpenSSL::SSL::VERIFY_PEER, c.verify_mode
1250
+ assert_kind_of OpenSSL::X509::Store, c.cert_store
1251
+ assert_nil c.verify_callback
1554
1252
  end
1555
1253
 
1556
- def test_ssl
1254
+ def test_ssl_ca_file
1557
1255
  skip 'OpenSSL is missing' unless HAVE_OPENSSL
1558
1256
 
1257
+ @http.ca_file = 'ca_file'
1559
1258
  @http.verify_callback = :callback
1560
1259
  c = Net::HTTP.new 'localhost', 80
1561
1260
 
@@ -1563,14 +1262,13 @@ class TestNetHttpPersistent < Minitest::Test
1563
1262
 
1564
1263
  assert c.use_ssl?
1565
1264
  assert_equal OpenSSL::SSL::VERIFY_PEER, c.verify_mode
1566
- assert_kind_of OpenSSL::X509::Store, c.cert_store
1567
- assert_nil c.verify_callback
1265
+ assert_equal :callback, c.verify_callback
1568
1266
  end
1569
1267
 
1570
- def test_ssl_ca_file
1268
+ def test_ssl_ca_path
1571
1269
  skip 'OpenSSL is missing' unless HAVE_OPENSSL
1572
1270
 
1573
- @http.ca_file = 'ca_file'
1271
+ @http.ca_path = 'ca_path'
1574
1272
  @http.verify_callback = :callback
1575
1273
  c = Net::HTTP.new 'localhost', 80
1576
1274
 
@@ -1667,34 +1365,37 @@ class TestNetHttpPersistent < Minitest::Test
1667
1365
  end
1668
1366
  end
1669
1367
 
1670
- def test_ssl_cleanup
1671
- skip 'OpenSSL is missing' unless HAVE_OPENSSL
1672
-
1673
- uri1 = URI.parse 'https://one.example'
1368
+ def test_ssl_timeout_equals
1369
+ @http.ssl_timeout = :ssl_timeout
1674
1370
 
1675
- c1 = @http.connection_for uri1
1371
+ assert_equal :ssl_timeout, @http.ssl_timeout
1372
+ assert_equal 1, @http.ssl_generation
1373
+ end
1676
1374
 
1677
- touts[c1.object_id] = Time.now
1678
- reqs[c1.object_id] = 5
1375
+ def test_ssl_version_equals
1376
+ @http.ssl_version = :ssl_version
1679
1377
 
1680
- @http.reconnect_ssl
1378
+ assert_equal :ssl_version, @http.ssl_version
1379
+ assert_equal 1, @http.ssl_generation
1380
+ end
1681
1381
 
1682
- @http.ssl_cleanup @http.ssl_generation
1382
+ def test_min_version_equals
1383
+ @http.min_version = :min_version
1683
1384
 
1684
- assert_empty ssl_conns
1685
- assert_empty touts
1686
- assert_empty reqs # sanity check, performed by #finish
1385
+ assert_equal :min_version, @http.min_version
1386
+ assert_equal 1, @http.ssl_generation
1687
1387
  end
1688
1388
 
1689
- def test_ssl_version_equals
1690
- @http.ssl_version = :ssl_version
1389
+ def test_max_version_equals
1390
+ @http.max_version = :max_version
1691
1391
 
1692
- assert_equal :ssl_version, @http.ssl_version
1392
+ assert_equal :max_version, @http.max_version
1693
1393
  assert_equal 1, @http.ssl_generation
1694
- end unless RUBY_1
1394
+ end
1695
1395
 
1696
1396
  def test_start
1697
1397
  c = basic_connection
1398
+ c = c.http
1698
1399
 
1699
1400
  @http.socket_options << [Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1]
1700
1401
  @http.debug_output = $stderr
@@ -1722,6 +1423,13 @@ class TestNetHttpPersistent < Minitest::Test
1722
1423
  assert_equal 1, @http.ssl_generation
1723
1424
  end
1724
1425
 
1426
+ def test_verify_depth_equals
1427
+ @http.verify_depth = :verify_depth
1428
+
1429
+ assert_equal :verify_depth, @http.verify_depth
1430
+ assert_equal 1, @http.ssl_generation
1431
+ end
1432
+
1725
1433
  def test_verify_mode_equals
1726
1434
  @http.verify_mode = :verify_mode
1727
1435