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 +0 -0
- data/History.txt +23 -0
- data/lib/net/http/persistent.rb +143 -23
- data/test/test_net_http_persistent.rb +208 -37
- data/test/test_net_http_persistent_ssl_reuse.rb +10 -5
- metadata +105 -101
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/History.txt
CHANGED
@@ -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
|
data/lib/net/http/persistent.rb
CHANGED
@@ -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.
|
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?
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
577
|
-
|
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
|
-
#
|
693
|
-
#
|
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
|
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
|
-
|
8
|
-
|
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
|
34
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
1122
|
-
|
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
|
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
|
-
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
54
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
55
|
none: false
|
61
|
-
requirements:
|
56
|
+
requirements:
|
62
57
|
- - ~>
|
63
|
-
- !ruby/object:Gem::Version
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
75
71
|
none: false
|
76
|
-
requirements:
|
72
|
+
requirements:
|
77
73
|
- - ~>
|
78
|
-
- !ruby/object:Gem::Version
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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
|
-
|
97
|
-
|
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
|
-
|
134
|
-
|
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
|
-
|
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.
|
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
|
153
|
-
|
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
|