net-http-persistent 2.7 → 2.8

Sign up to get free protection for your applications and to get access to all the features.
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