net-http-persistent 2.7 → 2.8

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.
data.tar.gz.sig CHANGED
Binary file
@@ -1,3 +1,26 @@
1
+ === 2.8 / 2012-10-17
2
+
3
+ * Minor enhancements
4
+ * Added Net::HTTP::Persistent::detect_idle_timeout which can be used to
5
+ determine the idle timeout for a host.
6
+ * The read timeout may now be updated for every request. Issue #33 by
7
+ Mislav Marohnić
8
+ * Added NO_PROXY support. Pull Request #31 by Laurence Rowe.
9
+ * Added #cert and #key aliases for Net::HTTP compatibility. Pull request
10
+ #26 by dlee.
11
+ * The artifice gem now disables SSL session reuse to prevent breakage of
12
+ testing frameworks. Pull Request #29 by Christopher Cooke.
13
+ * Disabled Net::HTTP::Persistent::SSLReuse on Ruby 2+. This feature is now
14
+ built-in to Net::HTTP.
15
+ * Bug fixes
16
+ * Socket options are set again following connection reset. Pull request #28
17
+ by cmaion.
18
+ * #shutdown now works even if no connections were made. Pull Request #24 by
19
+ James Tucker.
20
+ * Updated test RSA key size to 1024 bits. Bug #25 by Gunnar Wolf.
21
+ * The correct host:port are shown in the exception when a proxy connection
22
+ fails. Bug #30 by glebtv.
23
+
1
24
  === 2.7 / 2012-06-06
2
25
 
3
26
  * Minor enhancement
@@ -176,7 +176,7 @@ class Net::HTTP::Persistent
176
176
  ##
177
177
  # The version of Net::HTTP::Persistent you are using
178
178
 
179
- VERSION = '2.7'
179
+ VERSION = '2.8'
180
180
 
181
181
  ##
182
182
  # Error class for errors raised by Net::HTTP::Persistent. Various
@@ -185,11 +185,61 @@ class Net::HTTP::Persistent
185
185
 
186
186
  class Error < StandardError; end
187
187
 
188
+ ##
189
+ # Use this method to detect the idle timeout of the host at +uri+. The
190
+ # value returned can be used to configure #idle_timeout. +max+ controls the
191
+ # maximum idle timeout to detect.
192
+ #
193
+ # After
194
+ #
195
+ # Idle timeout detection is performed by creating a connection then
196
+ # performing a HEAD request in a loop until the connection terminates
197
+ # waiting one additional second per loop.
198
+ #
199
+ # NOTE: This may not work on ruby > 1.9.
200
+
201
+ def self.detect_idle_timeout uri, max = 10
202
+ uri = URI uri unless URI::Generic === uri
203
+ uri += '/'
204
+
205
+ req = Net::HTTP::Head.new uri.request_uri
206
+
207
+ http = new 'net-http-persistent detect_idle_timeout'
208
+
209
+ connection = http.connection_for uri
210
+
211
+ sleep_time = 0
212
+
213
+ loop do
214
+ response = connection.request req
215
+
216
+ $stderr.puts "HEAD #{uri} => #{response.code}" if $DEBUG
217
+
218
+ unless Net::HTTPOK === response then
219
+ raise Error, "bad response code #{response.code} detecting idle timeout"
220
+ end
221
+
222
+ break if sleep_time >= max
223
+
224
+ sleep_time += 1
225
+
226
+ $stderr.puts "sleeping #{sleep_time}" if $DEBUG
227
+ sleep sleep_time
228
+ end
229
+ ensure
230
+ http.shutdown
231
+
232
+ return sleep_time unless $!
233
+ end
234
+
188
235
  ##
189
236
  # This client's OpenSSL::X509::Certificate
190
237
 
191
238
  attr_reader :certificate
192
239
 
240
+ # For Net::HTTP parity
241
+ alias cert certificate
242
+
193
243
  ##
194
244
  # An SSL certificate authority. Setting this will set verify_mode to
195
245
  # VERIFY_PEER.
@@ -269,11 +319,19 @@ class Net::HTTP::Persistent
269
319
 
270
320
  attr_reader :private_key
271
321
 
322
+ # For Net::HTTP parity
323
+ alias key private_key
324
+
272
325
  ##
273
326
  # The URL through which requests will be proxied
274
327
 
275
328
  attr_reader :proxy_uri
276
329
 
330
+ ##
331
+ # List of host suffixes which will not be proxied
332
+
333
+ attr_reader :no_proxy
334
+
277
335
  ##
278
336
  # Seconds to wait until reading one block. See Net::HTTP#read_timeout
279
337
 
@@ -376,6 +434,7 @@ class Net::HTTP::Persistent
376
434
 
377
435
  @debug_output = nil
378
436
  @proxy_uri = nil
437
+ @no_proxy = []
379
438
  @headers = {}
380
439
  @override_headers = {}
381
440
  @http_versions = {}
@@ -420,6 +479,9 @@ class Net::HTTP::Persistent
420
479
  reconnect_ssl
421
480
  end
422
481
 
482
+ # For Net::HTTP parity
483
+ alias cert= certificate=
484
+
423
485
  ##
424
486
  # Sets the SSL certificate authority file.
425
487
 
@@ -450,6 +512,8 @@ class Net::HTTP::Persistent
450
512
  timeouts = thread[@timeout_key]
451
513
 
452
514
  (0...generation).each do |old_generation|
515
+ next unless thread[generation_key]
516
+
453
517
  conns = thread[generation_key].delete old_generation
454
518
 
455
519
  conns.each_value do |conn|
@@ -488,7 +552,7 @@ class Net::HTTP::Persistent
488
552
  net_http_args = [uri.host, uri.port]
489
553
  connection_id = net_http_args.join ':'
490
554
 
491
- if @proxy_uri then
555
+ if @proxy_uri and not proxy_bypass? uri.host, uri.port then
492
556
  connection_id << @proxy_connection_id
493
557
  net_http_args.concat @proxy_args
494
558
  end
@@ -503,27 +567,21 @@ class Net::HTTP::Persistent
503
567
  reset connection if expired? connection
504
568
  end
505
569
 
506
- unless connection.started? then
507
- connection.set_debug_output @debug_output if @debug_output
508
- connection.open_timeout = @open_timeout if @open_timeout
509
- connection.read_timeout = @read_timeout if @read_timeout
570
+ start connection unless connection.started?
510
571
 
511
- connection.start
512
-
513
- socket = connection.instance_variable_get :@socket
514
-
515
- if socket then # for fakeweb
516
- @socket_options.each do |option|
517
- socket.io.setsockopt(*option)
518
- end
519
- end
520
- end
572
+ connection.read_timeout = @read_timeout if @read_timeout
521
573
 
522
574
  connection
523
575
  rescue Errno::ECONNREFUSED
524
- raise Error, "connection refused: #{connection.address}:#{connection.port}"
576
+ address = connection.proxy_address || connection.address
577
+ port = connection.proxy_port || connection.port
578
+
579
+ raise Error, "connection refused: #{address}:#{port}"
525
580
  rescue Errno::EHOSTDOWN
526
- raise Error, "host down: #{connection.address}:#{connection.port}"
581
+ address = connection.proxy_address || connection.address
582
+ port = connection.proxy_port || connection.port
583
+
584
+ raise Error, "host down: #{address}:#{port}"
527
585
  end
528
586
 
529
587
  ##
@@ -560,6 +618,24 @@ class Net::HTTP::Persistent
560
618
  Time.now - last_used > @idle_timeout
561
619
  end
562
620
 
621
+ ##
622
+ # Starts the Net::HTTP +connection+
623
+
624
+ def start connection
625
+ connection.set_debug_output @debug_output if @debug_output
626
+ connection.open_timeout = @open_timeout if @open_timeout
627
+
628
+ connection.start
629
+
630
+ socket = connection.instance_variable_get :@socket
631
+
632
+ if socket then # for fakeweb
633
+ @socket_options.each do |option|
634
+ socket.io.setsockopt(*option)
635
+ end
636
+ end
637
+ end
638
+
563
639
  ##
564
640
  # Finishes the Net::HTTP +connection+
565
641
 
@@ -573,8 +649,11 @@ class Net::HTTP::Persistent
573
649
  end
574
650
 
575
651
  def http_class # :nodoc:
576
- if [:FakeWeb, :WebMock].any? { |klass| Object.const_defined?(klass) } or
577
- not @reuse_ssl_sessions then
652
+ if RUBY_VERSION > '2.0' then
653
+ Net::HTTP
654
+ elsif [:Artifice, :FakeWeb, :WebMock].any? { |klass|
655
+ Object.const_defined?(klass)
656
+ } or not @reuse_ssl_sessions then
578
657
  Net::HTTP
579
658
  else
580
659
  Net::HTTP::Persistent::SSLReuse
@@ -680,6 +759,9 @@ class Net::HTTP::Persistent
680
759
  reconnect_ssl
681
760
  end
682
761
 
762
+ # For Net::HTTP parity
763
+ alias key= private_key=
764
+
683
765
  ##
684
766
  # Sets the proxy server. The +proxy+ may be the URI of the proxy server,
685
767
  # the symbol +:ENV+ which will read the proxy from the environment or nil to
@@ -689,8 +771,10 @@ class Net::HTTP::Persistent
689
771
  # If the proxy URI is set after requests have been made, the next request
690
772
  # will shut-down and re-open all connections.
691
773
  #
692
- # If you are making some requests through a proxy and others without a proxy
693
- # use separate Net::Http::Persistent instances.
774
+ # The +no_proxy+ query parameter can be used to specify hosts which shouldn't
775
+ # be reached via proxy; if set it should be a comma separated list of
776
+ # hostname suffixes, optionally with +:port+ appended, for example
777
+ # <tt>example.com,some.host:8080</tt>.
694
778
 
695
779
  def proxy= proxy
696
780
  @proxy_uri = case proxy
@@ -700,6 +784,8 @@ class Net::HTTP::Persistent
700
784
  else raise ArgumentError, 'proxy must be :ENV or a URI::HTTP'
701
785
  end
702
786
 
787
+ @no_proxy.clear
788
+
703
789
  if @proxy_uri then
704
790
  @proxy_args = [
705
791
  @proxy_uri.host,
@@ -709,6 +795,10 @@ class Net::HTTP::Persistent
709
795
  ]
710
796
 
711
797
  @proxy_connection_id = [nil, *@proxy_args].join ':'
798
+
799
+ if @proxy_uri.query then
800
+ @no_proxy = CGI.parse(@proxy_uri.query)['no_proxy'].join(',').downcase.split(',').map { |x| x.strip }.reject { |x| x.empty? }
801
+ end
712
802
  end
713
803
 
714
804
  reconnect
@@ -724,6 +814,12 @@ class Net::HTTP::Persistent
724
814
  # indicated user and password unless HTTP_PROXY contains either of these in
725
815
  # the URI.
726
816
  #
817
+ # The +NO_PROXY+ ENV variable can be used to specify hosts which shouldn't
818
+ # be reached via proxy; if set it should be a comma separated list of
819
+ # hostname suffixes, optionally with +:port+ appended, for example
820
+ # <tt>example.com,some.host:8080</tt>. When set to <tt>*</tt> no proxy will
821
+ # be returned.
822
+ #
727
823
  # For Windows users, lowercase ENV variables are preferred over uppercase ENV
728
824
  # variables.
729
825
 
@@ -734,6 +830,15 @@ class Net::HTTP::Persistent
734
830
 
735
831
  uri = URI normalize_uri env_proxy
736
832
 
833
+ env_no_proxy = ENV['no_proxy'] || ENV['NO_PROXY']
834
+
835
+ # '*' is special case for always bypass
836
+ return nil if env_no_proxy == '*'
837
+
838
+ if env_no_proxy then
839
+ uri.query = "no_proxy=#{escape(env_no_proxy)}"
840
+ end
841
+
737
842
  unless uri.user or uri.password then
738
843
  uri.user = escape ENV['http_proxy_user'] || ENV['HTTP_PROXY_USER']
739
844
  uri.password = escape ENV['http_proxy_pass'] || ENV['HTTP_PROXY_PASS']
@@ -742,6 +847,21 @@ class Net::HTTP::Persistent
742
847
  uri
743
848
  end
744
849
 
850
+ ##
851
+ # Returns true when proxy should by bypassed for host.
852
+
853
+ def proxy_bypass? host, port
854
+ host = host.downcase
855
+ host_port = [host, port].join ':'
856
+
857
+ @no_proxy.each do |name|
858
+ return true if host[-name.length, name.length] == name or
859
+ host_port[-name.length, name.length] == name
860
+ end
861
+
862
+ false
863
+ end
864
+
745
865
  ##
746
866
  # Forces reconnection of HTTP connections.
747
867
 
@@ -765,7 +885,7 @@ class Net::HTTP::Persistent
765
885
 
766
886
  finish connection
767
887
 
768
- connection.start
888
+ start connection
769
889
  rescue Errno::ECONNREFUSED
770
890
  raise Error, "connection refused: #{connection.address}:#{connection.port}"
771
891
  rescue Errno::EHOSTDOWN
@@ -4,8 +4,19 @@ require 'net/http/persistent'
4
4
  require 'openssl'
5
5
  require 'stringio'
6
6
 
7
- class Net::HTTP::Persistent::SSLReuse
8
- alias orig_connect connect
7
+ module Net::HTTP::Persistent::TestConnect
8
+ def self.included mod
9
+ mod.send :alias_method, :orig_connect, :connect
10
+
11
+ def mod.use_connect which
12
+ self.send :remove_method, :connect
13
+ self.send :alias_method, :connect, which
14
+ end
15
+ end
16
+
17
+ def host_down_connect
18
+ raise Errno::EHOSTDOWN
19
+ end
9
20
 
10
21
  def test_connect
11
22
  unless use_ssl? then
@@ -30,16 +41,30 @@ class Net::HTTP::Persistent::SSLReuse
30
41
  @socket = Net::BufferedIO.new s
31
42
  end
32
43
 
33
- def self.use_connect which
34
- self.send :remove_method, :connect
35
- self.send :alias_method, :connect, which
44
+ def refused_connect
45
+ raise Errno::ECONNREFUSED
36
46
  end
37
47
  end
38
48
 
49
+ class Net::HTTP
50
+ include Net::HTTP::Persistent::TestConnect
51
+ end
52
+
53
+ class Net::HTTP::Persistent::SSLReuse
54
+ include Net::HTTP::Persistent::TestConnect
55
+ end
56
+
39
57
  class TestNetHttpPersistent < MiniTest::Unit::TestCase
40
58
 
41
59
  def setup
60
+ @http_class = if RUBY_VERSION > '2.0' then
61
+ Net::HTTP
62
+ else
63
+ Net::HTTP::Persistent::SSLReuse
64
+ end
65
+
42
66
  @http = Net::HTTP::Persistent.new
67
+
43
68
  @uri = URI.parse 'http://example.com/path'
44
69
 
45
70
  ENV.delete 'http_proxy'
@@ -48,7 +73,10 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
48
73
  ENV.delete 'HTTP_PROXY_USER'
49
74
  ENV.delete 'http_proxy_pass'
50
75
  ENV.delete 'HTTP_PROXY_PASS'
76
+ ENV.delete 'no_proxy'
77
+ ENV.delete 'NO_PROXY'
51
78
 
79
+ Net::HTTP.use_connect :test_connect
52
80
  Net::HTTP::Persistent::SSLReuse.use_connect :test_connect
53
81
  end
54
82
 
@@ -57,12 +85,14 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
57
85
  Thread.current[key] = nil
58
86
  end
59
87
 
88
+ Net::HTTP.use_connect :orig_connect
60
89
  Net::HTTP::Persistent::SSLReuse.use_connect :orig_connect
61
90
  end
62
91
 
63
92
  class BasicConnection
64
- attr_accessor :started, :finished, :address, :port
65
- attr_reader :req
93
+ attr_accessor :started, :finished, :address, :port,
94
+ :read_timeout, :open_timeout
95
+ attr_reader :req, :debug_output
66
96
  def initialize
67
97
  @started, @finished = 0, 0
68
98
  @address, @port = 'example.com', 80
@@ -80,6 +110,9 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
80
110
  def reset?
81
111
  @started == @finished + 1
82
112
  end
113
+ def set_debug_output io
114
+ @debug_output = io
115
+ end
83
116
  def start
84
117
  @started += 1
85
118
  io = Object.new
@@ -142,6 +175,8 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
142
175
  def test_initialize
143
176
  assert_nil @http.proxy_uri
144
177
 
178
+ assert_empty @http.no_proxy
179
+
145
180
  ssl_session_exists = OpenSSL::SSL.const_defined? :Session
146
181
 
147
182
  assert_equal ssl_session_exists, @http.reuse_ssl_sessions
@@ -201,7 +236,7 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
201
236
  @http.read_timeout = 321
202
237
  c = @http.connection_for @uri
203
238
 
204
- assert_kind_of Net::HTTP::Persistent::SSLReuse, c
239
+ assert_kind_of @http_class, c
205
240
 
206
241
  assert c.started?
207
242
  refute c.proxy?
@@ -211,15 +246,6 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
211
246
 
212
247
  assert_includes conns[0].keys, 'example.com:80'
213
248
  assert_same c, conns[0]['example.com:80']
214
-
215
- socket = c.instance_variable_get :@socket
216
- expected = if Socket.const_defined? :TCP_NODELAY then
217
- [[Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1]]
218
- else
219
- []
220
- end
221
-
222
- assert_equal expected, socket.io.instance_variable_get(:@setsockopts)
223
249
  end
224
250
 
225
251
  def test_connection_for_cached
@@ -227,10 +253,14 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
227
253
  cached.start
228
254
  conns[0]['example.com:80'] = cached
229
255
 
256
+ @http.read_timeout = 5
257
+
230
258
  c = @http.connection_for @uri
231
259
 
232
260
  assert c.started?
233
261
 
262
+ assert_equal 5, c.read_timeout
263
+
234
264
  assert_same cached, c
235
265
  end
236
266
 
@@ -324,6 +354,17 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
324
354
  'connection not reset due to timeout'
325
355
  end
326
356
 
357
+ def test_connection_for_refused
358
+ Net::HTTP.use_connect :refused_connect
359
+ Net::HTTP::Persistent::SSLReuse.use_connect :refused_connect
360
+
361
+ e = assert_raises Net::HTTP::Persistent::Error do
362
+ @http.connection_for @uri
363
+ end
364
+
365
+ assert_equal 'connection refused: example.com:80', e.message
366
+ end
367
+
327
368
  def test_connection_for_finished_ssl
328
369
  uri = URI.parse 'https://example.com/path'
329
370
  c = @http.connection_for uri
@@ -350,7 +391,7 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
350
391
  @http.connection_for @uri
351
392
  end
352
393
 
353
- assert_match %r%host down%, e.message
394
+ assert_equal 'host down: example.com:80', e.message
354
395
  end
355
396
 
356
397
  def test_connection_for_http_class_with_fakeweb
@@ -373,6 +414,16 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
373
414
  end
374
415
  end
375
416
 
417
+ def test_connection_for_http_class_with_artifice
418
+ Object.send :const_set, :Artifice, nil
419
+ c = @http.connection_for @uri
420
+ assert_instance_of Net::HTTP, c
421
+ ensure
422
+ if Object.const_defined?(:Artifice) then
423
+ Object.send :remove_const, :Artifice
424
+ end
425
+ end
426
+
376
427
  def test_connection_for_name
377
428
  http = Net::HTTP::Persistent.new 'name'
378
429
  uri = URI.parse 'http://example/'
@@ -410,6 +461,57 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
410
461
  assert_same c, conns[1]['example.com:80:proxy.example:80:johndoe:muffins']
411
462
  end
412
463
 
464
+ def test_connection_for_proxy_host_down
465
+ Net::HTTP.use_connect :host_down_connect
466
+ Net::HTTP::Persistent::SSLReuse.use_connect :host_down_connect
467
+
468
+ uri = URI.parse 'http://proxy.example'
469
+ uri.user = 'johndoe'
470
+ uri.password = 'muffins'
471
+
472
+ http = Net::HTTP::Persistent.new nil, uri
473
+
474
+ e = assert_raises Net::HTTP::Persistent::Error do
475
+ http.connection_for @uri
476
+ end
477
+
478
+ assert_equal 'host down: proxy.example:80', e.message
479
+ end
480
+
481
+ def test_connection_for_proxy_refused
482
+ Net::HTTP.use_connect :refused_connect
483
+ Net::HTTP::Persistent::SSLReuse.use_connect :refused_connect
484
+
485
+ uri = URI.parse 'http://proxy.example'
486
+ uri.user = 'johndoe'
487
+ uri.password = 'muffins'
488
+
489
+ http = Net::HTTP::Persistent.new nil, uri
490
+
491
+ e = assert_raises Net::HTTP::Persistent::Error do
492
+ http.connection_for @uri
493
+ end
494
+
495
+ assert_equal 'connection refused: proxy.example:80', e.message
496
+ end
497
+
498
+ def test_connection_for_no_proxy
499
+ uri = URI.parse 'http://proxy.example'
500
+ uri.user = 'johndoe'
501
+ uri.password = 'muffins'
502
+ uri.query = 'no_proxy=example.com'
503
+
504
+ http = Net::HTTP::Persistent.new nil, uri
505
+
506
+ c = http.connection_for @uri
507
+
508
+ assert c.started?
509
+ refute c.proxy?
510
+
511
+ assert_includes conns[1].keys, 'example.com:80'
512
+ assert_same c, conns[1]['example.com:80']
513
+ end
514
+
413
515
  def test_connection_for_refused
414
516
  cached = basic_connection
415
517
  def cached.start; raise Errno::ECONNREFUSED end
@@ -423,20 +525,6 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
423
525
  assert_match %r%connection refused%, e.message
424
526
  end
425
527
 
426
- def test_connection_for_socket_options
427
- @http.socket_options << [Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1]
428
- c = @http.connection_for @uri
429
-
430
- socket = c.instance_variable_get :@socket
431
-
432
- expected = []
433
- expected << [Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1] if
434
- Socket.const_defined? :TCP_NODELAY
435
- expected << [Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1]
436
-
437
- assert_equal expected, socket.io.instance_variable_get(:@setsockopts)
438
- end
439
-
440
528
  def test_connection_for_ssl
441
529
  uri = URI.parse 'https://example.com/path'
442
530
  c = @http.connection_for uri
@@ -642,12 +730,14 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
642
730
  ENV['HTTP_PROXY'] = 'proxy.example'
643
731
  ENV['HTTP_PROXY_USER'] = 'johndoe'
644
732
  ENV['HTTP_PROXY_PASS'] = 'muffins'
733
+ ENV['NO_PROXY'] = 'localhost,example.com'
645
734
 
646
735
  uri = @http.proxy_from_env
647
736
 
648
737
  expected = URI.parse 'http://proxy.example'
649
738
  expected.user = 'johndoe'
650
739
  expected.password = 'muffins'
740
+ expected.query = 'no_proxy=localhost%2Cexample.com'
651
741
 
652
742
  assert_equal expected, uri
653
743
  end
@@ -656,12 +746,14 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
656
746
  ENV['http_proxy'] = 'proxy.example'
657
747
  ENV['http_proxy_user'] = 'johndoe'
658
748
  ENV['http_proxy_pass'] = 'muffins'
749
+ ENV['no_proxy'] = 'localhost,example.com'
659
750
 
660
751
  uri = @http.proxy_from_env
661
752
 
662
753
  expected = URI.parse 'http://proxy.example'
663
754
  expected.user = 'johndoe'
664
755
  expected.password = 'muffins'
756
+ expected.query = 'no_proxy=localhost%2Cexample.com'
665
757
 
666
758
  assert_equal expected, uri
667
759
  end
@@ -678,6 +770,66 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
678
770
  assert_nil uri
679
771
  end
680
772
 
773
+ def test_proxy_from_env_no_proxy_star
774
+ uri = @http.proxy_from_env
775
+
776
+ assert_nil uri
777
+
778
+ ENV['HTTP_PROXY'] = 'proxy.example'
779
+ ENV['NO_PROXY'] = '*'
780
+
781
+ uri = @http.proxy_from_env
782
+
783
+ assert_nil uri
784
+ end
785
+
786
+ def test_proxy_bypass
787
+ ENV['HTTP_PROXY'] = 'proxy.example'
788
+ ENV['NO_PROXY'] = 'localhost,example.com:80'
789
+
790
+ @http.proxy = :ENV
791
+
792
+ assert @http.proxy_bypass? 'localhost', 80
793
+ assert @http.proxy_bypass? 'localhost', 443
794
+ assert @http.proxy_bypass? 'LOCALHOST', 80
795
+ assert @http.proxy_bypass? 'example.com', 80
796
+ refute @http.proxy_bypass? 'example.com', 443
797
+ assert @http.proxy_bypass? 'www.example.com', 80
798
+ refute @http.proxy_bypass? 'www.example.com', 443
799
+ assert @http.proxy_bypass? 'endingexample.com', 80
800
+ refute @http.proxy_bypass? 'example.org', 80
801
+ end
802
+
803
+ def test_proxy_bypass_space
804
+ ENV['HTTP_PROXY'] = 'proxy.example'
805
+ ENV['NO_PROXY'] = 'localhost, example.com'
806
+
807
+ @http.proxy = :ENV
808
+
809
+ assert @http.proxy_bypass? 'example.com', 80
810
+ refute @http.proxy_bypass? 'example.org', 80
811
+ end
812
+
813
+ def test_proxy_bypass_trailing
814
+ ENV['HTTP_PROXY'] = 'proxy.example'
815
+ ENV['NO_PROXY'] = 'localhost,example.com,'
816
+
817
+ @http.proxy = :ENV
818
+
819
+ assert @http.proxy_bypass? 'example.com', 80
820
+ refute @http.proxy_bypass? 'example.org', 80
821
+ end
822
+
823
+ def test_proxy_bypass_double_comma
824
+ ENV['HTTP_PROXY'] = 'proxy.example'
825
+ ENV['NO_PROXY'] = 'localhost,,example.com'
826
+
827
+ @http.proxy = :ENV
828
+
829
+ assert @http.proxy_bypass? 'example.com', 80
830
+ refute @http.proxy_bypass? 'example.org', 80
831
+ end
832
+
681
833
  def test_reconnect
682
834
  result = @http.reconnect
683
835
 
@@ -1113,13 +1265,10 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
1113
1265
  end
1114
1266
 
1115
1267
  def test_shutdown_no_connections
1116
- conns
1117
- ssl_conns
1118
-
1119
1268
  @http.shutdown
1120
1269
 
1121
- assert_empty Thread.current[@http.generation_key]
1122
- assert_empty Thread.current[@http.ssl_generation_key]
1270
+ assert_nil Thread.current[@http.generation_key]
1271
+ assert_nil Thread.current[@http.ssl_generation_key]
1123
1272
 
1124
1273
  assert_nil Thread.current[@http.request_key]
1125
1274
  assert_nil Thread.current[@http.timeout_key]
@@ -1303,6 +1452,28 @@ class TestNetHttpPersistent < MiniTest::Unit::TestCase
1303
1452
  assert_equal 1, @http.ssl_generation
1304
1453
  end if RUBY_VERSION > '1.9'
1305
1454
 
1455
+ def test_start
1456
+ c = basic_connection
1457
+
1458
+ @http.socket_options << [Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1]
1459
+ @http.debug_output = $stderr
1460
+ @http.open_timeout = 6
1461
+
1462
+ @http.start c
1463
+
1464
+ assert_equal $stderr, c.debug_output
1465
+ assert_equal 6, c.open_timeout
1466
+
1467
+ socket = c.instance_variable_get :@socket
1468
+
1469
+ expected = []
1470
+ expected << [Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1] if
1471
+ Socket.const_defined? :TCP_NODELAY
1472
+ expected << [Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1]
1473
+
1474
+ assert_equal expected, socket.io.instance_variable_get(:@setsockopts)
1475
+ end
1476
+
1306
1477
  def test_verify_callback_equals
1307
1478
  @http.verify_callback = :verify_callback
1308
1479
 
@@ -19,9 +19,9 @@ class TestNetHttpPersistentSSLReuse < MiniTest::Unit::TestCase
19
19
  end
20
20
 
21
21
  def setup
22
- @name = OpenSSL::X509::Name.parse 'CN=localhost'
22
+ @name = OpenSSL::X509::Name.parse 'CN=localhost/DC=localdomain'
23
23
 
24
- @key = OpenSSL::PKey::RSA.new 512
24
+ @key = OpenSSL::PKey::RSA.new 1024
25
25
 
26
26
  @cert = OpenSSL::X509::Certificate.new
27
27
  @cert.version = 2
@@ -30,6 +30,9 @@ class TestNetHttpPersistentSSLReuse < MiniTest::Unit::TestCase
30
30
  @cert.not_after = Time.now + 300
31
31
  @cert.public_key = @key.public_key
32
32
  @cert.subject = @name
33
+ @cert.issuer = @name
34
+
35
+ @cert.sign @key, OpenSSL::Digest::SHA1.new
33
36
 
34
37
  @host = 'localhost'
35
38
  @port = 10082
@@ -73,12 +76,14 @@ class TestNetHttpPersistentSSLReuse < MiniTest::Unit::TestCase
73
76
  end
74
77
 
75
78
  def test_ssl_connection_reuse
79
+ store = OpenSSL::X509::Store.new
80
+ store.add_cert @cert
81
+
76
82
  @http = Net::HTTP::Persistent::SSLReuse.new @host, @port
83
+ @http.cert_store = store
84
+ @http.ssl_version = :SSLv3 if @http.respond_to? :ssl_version=
77
85
  @http.use_ssl = true
78
86
  @http.verify_mode = OpenSSL::SSL::VERIFY_PEER
79
- @http.verify_callback = proc do |_, store_ctx|
80
- store_ctx.current_cert.to_der == @cert.to_der
81
- end
82
87
 
83
88
  @http.start
84
89
  @http.get '/'
metadata CHANGED
@@ -1,110 +1,121 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: net-http-persistent
3
- version: !ruby/object:Gem::Version
4
- hash: 13
3
+ version: !ruby/object:Gem::Version
4
+ version: '2.8'
5
5
  prerelease:
6
- segments:
7
- - 2
8
- - 7
9
- version: "2.7"
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Eric Hodel
13
9
  autorequire:
14
10
  bindir: bin
15
- cert_chain:
16
- - |
17
- -----BEGIN CERTIFICATE-----
18
- MIIDeDCCAmCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy
19
- YWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZFgNu
20
- ZXQwHhcNMTIwMjI4MTc1NDI1WhcNMTMwMjI3MTc1NDI1WjBBMRAwDgYDVQQDDAdk
21
- cmJyYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZ
22
- FgNuZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbbgLrGLGIDE76
23
- LV/cvxdEzCuYuS3oG9PrSZnuDweySUfdp/so0cDq+j8bqy6OzZSw07gdjwFMSd6J
24
- U5ddZCVywn5nnAQ+Ui7jMW54CYt5/H6f2US6U0hQOjJR6cpfiymgxGdfyTiVcvTm
25
- Gj/okWrQl0NjYOYBpDi+9PPmaH2RmLJu0dB/NylsDnW5j6yN1BEI8MfJRR+HRKZY
26
- mUtgzBwF1V4KIZQ8EuL6I/nHVu07i6IkrpAgxpXUfdJQJi0oZAqXurAV3yTxkFwd
27
- g62YrrW26mDe+pZBzR6bpLE+PmXCzz7UxUq3AE0gPHbiMXie3EFE0oxnsU3lIduh
28
- sCANiQ8BAgMBAAGjezB5MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
29
- BBS5k4Z75VSpdM0AclG2UvzFA/VW5DAfBgNVHREEGDAWgRRkcmJyYWluQHNlZ21l
30
- bnQ3Lm5ldDAfBgNVHRIEGDAWgRRkcmJyYWluQHNlZ21lbnQ3Lm5ldDANBgkqhkiG
31
- 9w0BAQUFAAOCAQEAPeWzFnrcvC6eVzdlhmjUub2s6qieBkongKRDHQz5MEeQv4LS
32
- SARnoHY+uCAVL/1xGAhmpzqQ3fJGWK9eBacW/e8E5GF9xQcV3mE1bA0WNaiDlX5j
33
- U2aI+ZGSblqvHUCxKBHR1s7UMHsbz1saOmgdRTyPx0juJs68ocbUTeYBLWu9V4KP
34
- zdGAG2JXO2gONg3b4tYDvpBLbry+KOX27iAJulUaH9TiTOULL4ITJVFsK0mYVqmR
35
- Q8Tno9S3e4XGGP1ZWfLrTWEJbavFfhGHut2iMRwfC7s/YILAHNATopaJdH9DNpd1
36
- U81zGHMUBOvz/VGT6wJwYJ3emS2nfA2NOHFfgA==
37
- -----END CERTIFICATE-----
38
-
39
- date: 2012-06-06 00:00:00 Z
40
- dependencies:
41
- - !ruby/object:Gem::Dependency
11
+ cert_chain:
12
+ - !binary |-
13
+ LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURlRENDQW1DZ0F3SUJB
14
+ Z0lCQVRBTkJna3Foa2lHOXcwQkFRVUZBREJCTVJBd0RnWURWUVFEREFka2Nt
15
+ SnkKWVdsdU1SZ3dGZ1lLQ1pJbWlaUHlMR1FCR1JZSWMyVm5iV1Z1ZERjeEV6
16
+ QVJCZ29Ka2lhSmsvSXNaQUVaRmdOdQpaWFF3SGhjTk1USXdNakk0TVRjMU5E
17
+ STFXaGNOTVRNd01qSTNNVGMxTkRJMVdqQkJNUkF3RGdZRFZRUUREQWRrCmNt
18
+ SnlZV2x1TVJnd0ZnWUtDWkltaVpQeUxHUUJHUllJYzJWbmJXVnVkRGN4RXpB
19
+ UkJnb0praWFKay9Jc1pBRVoKRmdOdVpYUXdnZ0VpTUEwR0NTcUdTSWIzRFFF
20
+ QkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDYmJnTHJHTEdJREU3NgpMVi9jdnhk
21
+ RXpDdVl1UzNvRzlQclNabnVEd2V5U1VmZHAvc28wY0RxK2o4YnF5Nk96WlN3
22
+ MDdnZGp3Rk1TZDZKClU1ZGRaQ1Z5d241bm5BUStVaTdqTVc1NENZdDUvSDZm
23
+ MlVTNlUwaFFPakpSNmNwZml5bWd4R2RmeVRpVmN2VG0KR2ovb2tXclFsME5q
24
+ WU9ZQnBEaSs5UFBtYUgyUm1MSnUwZEIvTnlsc0RuVzVqNnlOMUJFSThNZkpS
25
+ UitIUktaWQptVXRnekJ3RjFWNEtJWlE4RXVMNkkvbkhWdTA3aTZJa3JwQWd4
26
+ cFhVZmRKUUppMG9aQXFYdXJBVjN5VHhrRndkCmc2MllyclcyNm1EZStwWkJ6
27
+ UjZicExFK1BtWEN6ejdVeFVxM0FFMGdQSGJpTVhpZTNFRkUwb3huc1UzbElk
28
+ dWgKc0NBTmlROEJBZ01CQUFHamV6QjVNQWtHQTFVZEV3UUNNQUF3Q3dZRFZS
29
+ MFBCQVFEQWdTd01CMEdBMVVkRGdRVwpCQlM1azRaNzVWU3BkTTBBY2xHMlV2
30
+ ekZBL1ZXNURBZkJnTlZIUkVFR0RBV2dSUmtjbUp5WVdsdVFITmxaMjFsCmJu
31
+ UTNMbTVsZERBZkJnTlZIUklFR0RBV2dSUmtjbUp5WVdsdVFITmxaMjFsYm5R
32
+ M0xtNWxkREFOQmdrcWhraUcKOXcwQkFRVUZBQU9DQVFFQVBlV3pGbnJjdkM2
33
+ ZVZ6ZGxobWpVdWIyczZxaWVCa29uZ0tSREhRejVNRWVRdjRMUwpTQVJub0hZ
34
+ K3VDQVZMLzF4R0FobXB6cVEzZkpHV0s5ZUJhY1cvZThFNUdGOXhRY1YzbUUx
35
+ YkEwV05haURsWDVqClUyYUkrWkdTYmxxdkhVQ3hLQkhSMXM3VU1Ic2J6MXNh
36
+ T21nZFJUeVB4MGp1SnM2OG9jYlVUZVlCTFd1OVY0S1AKemRHQUcySlhPMmdP
37
+ TmczYjR0WUR2cEJMYnJ5K0tPWDI3aUFKdWxVYUg5VGlUT1VMTDRJVEpWRnNL
38
+ MG1ZVnFtUgpROFRubzlTM2U0WEdHUDFaV2ZMclRXRUpiYXZGZmhHSHV0MmlN
39
+ UndmQzdzL1lJTEFITkFUb3BhSmRIOUROcGQxClU4MXpHSE1VQk92ei9WR1Q2
40
+ d0p3WUozZW1TMm5mQTJOT0hGZmdBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUt
41
+ LS0tLQo=
42
+ date: 2012-10-18 00:00:00.000000000 Z
43
+ dependencies:
44
+ - !ruby/object:Gem::Dependency
42
45
  name: minitest
43
- prerelease: false
44
- requirement: &id001 !ruby/object:Gem::Requirement
46
+ requirement: !ruby/object:Gem::Requirement
45
47
  none: false
46
- requirements:
48
+ requirements:
47
49
  - - ~>
48
- - !ruby/object:Gem::Version
49
- hash: 21
50
- segments:
51
- - 2
52
- - 11
53
- version: "2.11"
50
+ - !ruby/object:Gem::Version
51
+ version: '3.4'
54
52
  type: :development
55
- version_requirements: *id001
56
- - !ruby/object:Gem::Dependency
57
- name: rdoc
58
53
  prerelease: false
59
- requirement: &id002 !ruby/object:Gem::Requirement
54
+ version_requirements: !ruby/object:Gem::Requirement
60
55
  none: false
61
- requirements:
56
+ requirements:
62
57
  - - ~>
63
- - !ruby/object:Gem::Version
64
- hash: 19
65
- segments:
66
- - 3
67
- - 10
68
- version: "3.10"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.4'
60
+ - !ruby/object:Gem::Dependency
61
+ name: rdoc
62
+ requirement: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: '3.10'
69
68
  type: :development
70
- version_requirements: *id002
71
- - !ruby/object:Gem::Dependency
72
- name: hoe
73
69
  prerelease: false
74
- requirement: &id003 !ruby/object:Gem::Requirement
70
+ version_requirements: !ruby/object:Gem::Requirement
75
71
  none: false
76
- requirements:
72
+ requirements:
77
73
  - - ~>
78
- - !ruby/object:Gem::Version
79
- hash: 7
80
- segments:
81
- - 3
82
- - 0
83
- version: "3.0"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.10'
76
+ - !ruby/object:Gem::Dependency
77
+ name: hoe
78
+ requirement: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ~>
82
+ - !ruby/object:Gem::Version
83
+ version: '3.0'
84
84
  type: :development
85
- version_requirements: *id003
86
- description: |-
87
- Manages persistent connections using Net::HTTP plus a speed fix for Ruby 1.8.
88
- It's thread-safe too!
89
-
85
+ prerelease: false
86
+ version_requirements: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ~>
90
+ - !ruby/object:Gem::Version
91
+ version: '3.0'
92
+ description: ! 'Manages persistent connections using Net::HTTP plus a speed fix for
93
+ Ruby 1.8.
94
+
95
+ It''s thread-safe too!
96
+
97
+
90
98
  Using persistent HTTP connections can dramatically increase the speed of HTTP.
99
+
91
100
  Creating a new HTTP connection for every request involves an extra TCP
101
+
92
102
  round-trip and causes TCP congestion avoidance negotiation to start over.
93
-
103
+
104
+
94
105
  Net::HTTP supports persistent connections with some API methods but does not
106
+
95
107
  handle reconnection gracefully. Net::HTTP::Persistent supports reconnection
96
- and retry according to RFC 2616.
97
- email:
108
+
109
+ and retry according to RFC 2616.'
110
+ email:
98
111
  - drbrain@segment7.net
99
112
  executables: []
100
-
101
113
  extensions: []
102
-
103
- extra_rdoc_files:
114
+ extra_rdoc_files:
104
115
  - History.txt
105
116
  - Manifest.txt
106
117
  - README.rdoc
107
- files:
118
+ files:
108
119
  - .autotest
109
120
  - .gemtest
110
121
  - History.txt
@@ -118,38 +129,31 @@ files:
118
129
  - test/test_net_http_persistent_ssl_reuse.rb
119
130
  homepage: http://docs.seattlerb.org/net-http-persistent
120
131
  licenses: []
121
-
122
132
  post_install_message:
123
- rdoc_options:
133
+ rdoc_options:
124
134
  - --main
125
135
  - README.rdoc
126
- require_paths:
136
+ require_paths:
127
137
  - lib
128
- required_ruby_version: !ruby/object:Gem::Requirement
138
+ required_ruby_version: !ruby/object:Gem::Requirement
129
139
  none: false
130
- requirements:
131
- - - ">="
132
- - !ruby/object:Gem::Version
133
- hash: 3
134
- segments:
135
- - 0
136
- version: "0"
137
- required_rubygems_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
145
  none: false
139
- requirements:
140
- - - ">="
141
- - !ruby/object:Gem::Version
142
- hash: 3
143
- segments:
144
- - 0
145
- version: "0"
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
146
150
  requirements: []
147
-
148
151
  rubyforge_project: net-http-persistent
149
- rubygems_version: 1.8.21
152
+ rubygems_version: 1.8.24
150
153
  signing_key:
151
154
  specification_version: 3
152
- summary: Manages persistent connections using Net::HTTP plus a speed fix for Ruby 1.8
153
- test_files:
155
+ summary: Manages persistent connections using Net::HTTP plus a speed fix for Ruby
156
+ 1.8
157
+ test_files:
154
158
  - test/test_net_http_persistent.rb
155
159
  - test/test_net_http_persistent_ssl_reuse.rb
metadata.gz.sig CHANGED
Binary file