net-http-persistent 1.0
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 +0 -0
- data/.autotest +7 -0
- data/History.txt +6 -0
- data/Manifest.txt +8 -0
- data/README.txt +44 -0
- data/Rakefile +13 -0
- data/lib/net/http/faster.rb +27 -0
- data/lib/net/http/persistent.rb +215 -0
- data/test/test_net_http_persistent.rb +244 -0
- metadata +147 -0
- metadata.gz.sig +0 -0
data.tar.gz.sig
ADDED
Binary file
|
data/.autotest
ADDED
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
= net_http_persistent
|
2
|
+
|
3
|
+
* http://seattlerb.rubyforge.org/net-http-persistent
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Persistent connections using Net::HTTP plus a speed fix for 1.8. It's
|
8
|
+
thread-safe too!
|
9
|
+
|
10
|
+
== FEATURES/PROBLEMS:
|
11
|
+
|
12
|
+
* Supports SSL
|
13
|
+
* Thread-safe
|
14
|
+
* Pure ruby
|
15
|
+
* Timeout-less speed boost for 1.8 (by Aaron Patterson)
|
16
|
+
|
17
|
+
== INSTALL:
|
18
|
+
|
19
|
+
gem install net-http-persistent
|
20
|
+
|
21
|
+
== LICENSE:
|
22
|
+
|
23
|
+
(The MIT License)
|
24
|
+
|
25
|
+
Copyright (c) 2010 Eric Hodel, Aaron Patterson
|
26
|
+
|
27
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
28
|
+
a copy of this software and associated documentation files (the
|
29
|
+
'Software'), to deal in the Software without restriction, including
|
30
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
31
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
32
|
+
permit persons to whom the Software is furnished to do so, subject to
|
33
|
+
the following conditions:
|
34
|
+
|
35
|
+
The above copyright notice and this permission notice shall be
|
36
|
+
included in all copies or substantial portions of the Software.
|
37
|
+
|
38
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
39
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
40
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
41
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
42
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
43
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
44
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'net/protocol'
|
2
|
+
|
3
|
+
##
|
4
|
+
# Aaron Patterson's monkeypatch (accepted into 1.9.1) to fix Net::HTTP's speed
|
5
|
+
# problems.
|
6
|
+
#
|
7
|
+
# http://gist.github.com/251244
|
8
|
+
|
9
|
+
class Net::BufferedIO #:nodoc:
|
10
|
+
alias :old_rbuf_fill :rbuf_fill
|
11
|
+
|
12
|
+
def rbuf_fill
|
13
|
+
if @io.respond_to? :read_nonblock then
|
14
|
+
begin
|
15
|
+
@rbuf << @io.read_nonblock(65536)
|
16
|
+
rescue Errno::EWOULDBLOCK => e
|
17
|
+
retry if IO.select [@io], nil, nil, @read_timeout
|
18
|
+
raise Timeout::Error, e.message
|
19
|
+
end
|
20
|
+
else # SSL sockets do not have read_nonblock
|
21
|
+
timeout @read_timeout do
|
22
|
+
@rbuf << @io.sysread(65536)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,215 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/http/faster'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
##
|
6
|
+
# Persistent connections for Net::HTTP
|
7
|
+
#
|
8
|
+
# Net::HTTP::Persistent maintains persistent connections across all the
|
9
|
+
# servers you wish to talk to. For each host:port you communicate with a
|
10
|
+
# single persistent connection is created.
|
11
|
+
#
|
12
|
+
# Multiple Net::HTTP::Persistent objects will share the same set of
|
13
|
+
# connections.
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
#
|
17
|
+
# uri = URI.parse 'http://example.com/awesome/web/service'
|
18
|
+
# http = Net::HTTP::Persistent
|
19
|
+
# stuff = http.request uri # performs a GET
|
20
|
+
#
|
21
|
+
# # perform a POST
|
22
|
+
# post_uri = uri + 'create'
|
23
|
+
# post = Net::HTTP::Post.new uri.path
|
24
|
+
# post.set_form_data 'some' => 'cool data'
|
25
|
+
# http.request post_uri, post # URI is always required
|
26
|
+
|
27
|
+
class Net::HTTP::Persistent
|
28
|
+
|
29
|
+
##
|
30
|
+
# The version of Net::HTTP::Persistent use are using
|
31
|
+
|
32
|
+
VERSION = '1.0'
|
33
|
+
|
34
|
+
##
|
35
|
+
# Error class for errors raised by Net::HTTP::Persistent. Various
|
36
|
+
# SystemCallErrors are re-raised with a human-readable message under this
|
37
|
+
# class.
|
38
|
+
|
39
|
+
class Error < StandardError; end
|
40
|
+
|
41
|
+
##
|
42
|
+
# This client's OpenSSL::X509::Certificate
|
43
|
+
|
44
|
+
attr_accessor :certificate
|
45
|
+
|
46
|
+
##
|
47
|
+
# An SSL certificate authority. Setting this will set verify_mode to
|
48
|
+
# VERIFY_PEER.
|
49
|
+
|
50
|
+
attr_accessor :ca_file
|
51
|
+
|
52
|
+
##
|
53
|
+
# Headers that are added to every request
|
54
|
+
|
55
|
+
attr_reader :headers
|
56
|
+
|
57
|
+
##
|
58
|
+
# The value sent in the Keep-Alive header. Defaults to 30 seconds
|
59
|
+
|
60
|
+
attr_accessor :keep_alive
|
61
|
+
|
62
|
+
##
|
63
|
+
# This client's SSL private key
|
64
|
+
|
65
|
+
attr_accessor :private_key
|
66
|
+
|
67
|
+
##
|
68
|
+
# SSL verification callback. Used when ca_file is set.
|
69
|
+
|
70
|
+
attr_accessor :verify_callback
|
71
|
+
|
72
|
+
##
|
73
|
+
# HTTPS verify mode. Set to OpenSSL::SSL::VERIFY_NONE to ignore certificate
|
74
|
+
# problems.
|
75
|
+
#
|
76
|
+
# You can use +verify_mode+ to override any default values.
|
77
|
+
|
78
|
+
attr_accessor :verify_mode
|
79
|
+
|
80
|
+
def initialize # :nodoc:
|
81
|
+
@keep_alive = 30
|
82
|
+
@headers = {}
|
83
|
+
|
84
|
+
@certificate = nil
|
85
|
+
@ca_file = nil
|
86
|
+
@private_key = nil
|
87
|
+
@verify_callback = nil
|
88
|
+
@verify_mode = nil
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# Creates a new connection for +uri+
|
93
|
+
|
94
|
+
def connection_for uri
|
95
|
+
Thread.current[:net_http_persistent_connections] ||= {}
|
96
|
+
connections = Thread.current[:net_http_persistent_connections]
|
97
|
+
|
98
|
+
connection_id = [uri.host, uri.port].join ':'
|
99
|
+
|
100
|
+
connections[connection_id] ||= Net::HTTP.new uri.host, uri.port
|
101
|
+
connection = connections[connection_id]
|
102
|
+
|
103
|
+
ssl connection if uri.scheme == 'https' and not connection.started?
|
104
|
+
|
105
|
+
connection.start unless connection.started?
|
106
|
+
|
107
|
+
connection
|
108
|
+
rescue Errno::ECONNREFUSED
|
109
|
+
raise Error, "connection refused: #{connection.address}:#{connection.port}"
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Returns an error message containing the number of requests performed on
|
114
|
+
# this connection
|
115
|
+
|
116
|
+
def error_message connection
|
117
|
+
requests =
|
118
|
+
Thread.current[:net_http_persistent_requests][connection.object_id]
|
119
|
+
|
120
|
+
"after #{requests} requests on #{connection.object_id}"
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Finishes then restarts the Net::HTTP +connection+
|
125
|
+
|
126
|
+
def reset connection
|
127
|
+
Thread.current[:net_http_persistent_requests].delete connection.object_id
|
128
|
+
|
129
|
+
begin
|
130
|
+
connection.finish
|
131
|
+
rescue IOError
|
132
|
+
end
|
133
|
+
|
134
|
+
connection.start
|
135
|
+
rescue Errno::ECONNREFUSED
|
136
|
+
raise Error, "connection refused: #{connection.address}:#{connection.port}"
|
137
|
+
rescue Errno::EHOSTDOWN
|
138
|
+
raise Error, "host down: #{connection.address}:#{connection.port}"
|
139
|
+
end
|
140
|
+
|
141
|
+
##
|
142
|
+
# Makes a request on +uri+. If +req+ is nil a Net::HTTP::Get is performed
|
143
|
+
# against +uri+.
|
144
|
+
#
|
145
|
+
# +req+ must be a Net::HTTPRequest subclass (see Net::HTTP for a list).
|
146
|
+
|
147
|
+
def request uri, req = nil
|
148
|
+
Thread.current[:net_http_persistent_requests] ||= Hash.new 0
|
149
|
+
retried = false
|
150
|
+
bad_response = false
|
151
|
+
|
152
|
+
req = Net::HTTP::Get.new uri.request_uri unless req
|
153
|
+
|
154
|
+
headers.each do |pair|
|
155
|
+
req.add_field(*pair)
|
156
|
+
end
|
157
|
+
|
158
|
+
req.add_field 'Connection', 'keep-alive'
|
159
|
+
req.add_field 'Keep-Alive', @keep_alive
|
160
|
+
|
161
|
+
connection = connection_for uri
|
162
|
+
connection_id = connection.object_id
|
163
|
+
|
164
|
+
begin
|
165
|
+
count = Thread.current[:net_http_persistent_requests][connection_id] += 1
|
166
|
+
response = connection.request req
|
167
|
+
|
168
|
+
rescue Net::HTTPBadResponse => e
|
169
|
+
message = error_message connection
|
170
|
+
|
171
|
+
reset connection
|
172
|
+
|
173
|
+
raise Error, "too many bad responses #{message}" if bad_response
|
174
|
+
|
175
|
+
bad_response = true
|
176
|
+
retry
|
177
|
+
rescue IOError, EOFError, Timeout::Error,
|
178
|
+
Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EPIPE => e
|
179
|
+
due_to = "(due to #{e.message} - #{e.class})"
|
180
|
+
message = error_message connection
|
181
|
+
|
182
|
+
reset connection
|
183
|
+
|
184
|
+
raise Error, "too many connection resets #{due_to} #{message}" if retried
|
185
|
+
|
186
|
+
retried = true
|
187
|
+
retry
|
188
|
+
end
|
189
|
+
|
190
|
+
response
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Enables SSL on +connection+
|
195
|
+
|
196
|
+
def ssl connection
|
197
|
+
require 'net/https'
|
198
|
+
connection.use_ssl = true
|
199
|
+
|
200
|
+
if @ca_file then
|
201
|
+
connection.ca_file = @ca_file
|
202
|
+
connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
203
|
+
connection.verify_callback = @verify_callback if @verify_callback
|
204
|
+
end
|
205
|
+
|
206
|
+
if @certificate and @private_key then
|
207
|
+
connection.cert = @certificate
|
208
|
+
connection.key = @private_key
|
209
|
+
end
|
210
|
+
|
211
|
+
connection.verify_mode = @verify_mode if @verify_mode
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
|
@@ -0,0 +1,244 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'net/http/persistent'
|
3
|
+
require 'openssl'
|
4
|
+
|
5
|
+
class TestNetHttpPersistent < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@http = Net::HTTP::Persistent.new
|
9
|
+
@uri = URI.parse 'http://example.com/path'
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
Thread.current[:net_http_persistent_connections] = nil
|
14
|
+
Thread.current[:net_http_persistent_requests] = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def connection
|
18
|
+
c = Object.new
|
19
|
+
# Net::HTTP
|
20
|
+
def c.finish; @finish = true end
|
21
|
+
def c.request(req) @req = req; :response end
|
22
|
+
def c.reset; @reset = true end
|
23
|
+
def c.start; end
|
24
|
+
|
25
|
+
# util
|
26
|
+
def c.req() @req; end
|
27
|
+
def c.reset?; @reset end
|
28
|
+
def c.started?; true end
|
29
|
+
conns["#{@uri.host}:#{@uri.port}"] = c
|
30
|
+
c
|
31
|
+
end
|
32
|
+
|
33
|
+
def conns
|
34
|
+
Thread.current[:net_http_persistent_connections] ||= {}
|
35
|
+
end
|
36
|
+
|
37
|
+
def reqs
|
38
|
+
Thread.current[:net_http_persistent_requests] ||= {}
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_connection_for
|
42
|
+
c = @http.connection_for @uri
|
43
|
+
|
44
|
+
assert c.started?
|
45
|
+
|
46
|
+
assert_includes conns.keys, 'example.com:80'
|
47
|
+
assert_same c, conns['example.com:80']
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_connection_for_cached
|
51
|
+
cached = Object.new
|
52
|
+
def cached.started?; true end
|
53
|
+
conns['example.com:80'] = cached
|
54
|
+
|
55
|
+
c = @http.connection_for @uri
|
56
|
+
|
57
|
+
assert c.started?
|
58
|
+
|
59
|
+
assert_same cached, c
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_connection_for_refused
|
63
|
+
cached = Object.new
|
64
|
+
def cached.address; 'example.com' end
|
65
|
+
def cached.port; 80 end
|
66
|
+
def cached.start; raise Errno::ECONNREFUSED end
|
67
|
+
def cached.started?; false end
|
68
|
+
conns['example.com:80'] = cached
|
69
|
+
|
70
|
+
e = assert_raises Net::HTTP::Persistent::Error do
|
71
|
+
@http.connection_for @uri
|
72
|
+
end
|
73
|
+
|
74
|
+
assert_match %r%connection refused%, e
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_error_message
|
78
|
+
c = Object.new
|
79
|
+
reqs[c.object_id] = 5
|
80
|
+
|
81
|
+
assert_equal "after 5 requests on #{c.object_id}", @http.error_message(c)
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_reset
|
85
|
+
c = Object.new
|
86
|
+
def c.finish; @finished = true end
|
87
|
+
def c.finished?; @finished end
|
88
|
+
def c.start; @started = true end
|
89
|
+
def c.started?; @started end
|
90
|
+
reqs[c.object_id] = 5
|
91
|
+
|
92
|
+
@http.reset c
|
93
|
+
|
94
|
+
assert c.started?
|
95
|
+
assert c.finished?
|
96
|
+
assert_nil reqs[c.object_id]
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_reset_io_error
|
100
|
+
c = Object.new
|
101
|
+
def c.finish; @finished = true; raise IOError end
|
102
|
+
def c.finished?; @finished end
|
103
|
+
def c.start; @started = true end
|
104
|
+
def c.started?; @started end
|
105
|
+
reqs[c.object_id] = 5
|
106
|
+
|
107
|
+
@http.reset c
|
108
|
+
|
109
|
+
assert c.started?
|
110
|
+
assert c.finished?
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_reset_host_down
|
114
|
+
c = Object.new
|
115
|
+
def c.address; 'example.com' end
|
116
|
+
def c.finish; end
|
117
|
+
def c.port; 80 end
|
118
|
+
def c.start; raise Errno::EHOSTDOWN end
|
119
|
+
reqs[c.object_id] = 5
|
120
|
+
|
121
|
+
e = assert_raises Net::HTTP::Persistent::Error do
|
122
|
+
@http.reset c
|
123
|
+
end
|
124
|
+
|
125
|
+
assert_match %r%host down%, e
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_reset_refused
|
129
|
+
c = Object.new
|
130
|
+
def c.address; 'example.com' end
|
131
|
+
def c.finish; end
|
132
|
+
def c.port; 80 end
|
133
|
+
def c.start; raise Errno::ECONNREFUSED end
|
134
|
+
reqs[c.object_id] = 5
|
135
|
+
|
136
|
+
e = assert_raises Net::HTTP::Persistent::Error do
|
137
|
+
@http.reset c
|
138
|
+
end
|
139
|
+
|
140
|
+
assert_match %r%connection refused%, e
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_request
|
144
|
+
@http.headers['user-agent'] = 'test ua'
|
145
|
+
c = connection
|
146
|
+
|
147
|
+
res = @http.request @uri
|
148
|
+
req = c.req
|
149
|
+
|
150
|
+
assert_equal :response, res
|
151
|
+
|
152
|
+
assert_kind_of Net::HTTP::Get, req
|
153
|
+
assert_equal '/path', req.path
|
154
|
+
assert_equal 'keep-alive', req['connection']
|
155
|
+
assert_equal '30', req['keep-alive']
|
156
|
+
assert_equal 'test ua', req['user-agent']
|
157
|
+
|
158
|
+
assert_equal 1, reqs[c.object_id]
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_request_bad_response
|
162
|
+
c = connection
|
163
|
+
def c.request(*a) raise Net::HTTPBadResponse end
|
164
|
+
|
165
|
+
e = assert_raises Net::HTTP::Persistent::Error do
|
166
|
+
@http.request @uri
|
167
|
+
end
|
168
|
+
|
169
|
+
assert_equal 0, reqs[c.object_id]
|
170
|
+
assert_match %r%too many bad responses%, e.message
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_request_reset
|
174
|
+
c = connection
|
175
|
+
def c.request(*a) raise Errno::ECONNRESET end
|
176
|
+
|
177
|
+
e = assert_raises Net::HTTP::Persistent::Error do
|
178
|
+
@http.request @uri
|
179
|
+
end
|
180
|
+
|
181
|
+
assert_equal 0, reqs[c.object_id]
|
182
|
+
assert_match %r%too many connection resets%, e.message
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_request_post
|
186
|
+
c = connection
|
187
|
+
|
188
|
+
post = Net::HTTP::Post.new @uri.path
|
189
|
+
|
190
|
+
res = @http.request @uri, post
|
191
|
+
req = c.req
|
192
|
+
|
193
|
+
assert_equal :response, res
|
194
|
+
|
195
|
+
assert_same post, req
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_ssl
|
199
|
+
@http.verify_callback = :callback
|
200
|
+
c = Net::HTTP.new 'localhost', 80
|
201
|
+
|
202
|
+
@http.ssl c
|
203
|
+
|
204
|
+
assert c.use_ssl?
|
205
|
+
assert_nil c.verify_mode
|
206
|
+
assert_nil c.verify_callback
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_ssl_ca_file
|
210
|
+
@http.ca_file = 'ca_file'
|
211
|
+
@http.verify_callback = :callback
|
212
|
+
c = Net::HTTP.new 'localhost', 80
|
213
|
+
|
214
|
+
@http.ssl c
|
215
|
+
|
216
|
+
assert c.use_ssl?
|
217
|
+
assert_equal OpenSSL::SSL::VERIFY_PEER, c.verify_mode
|
218
|
+
assert_equal :callback, c.verify_callback
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_ssl_certificate
|
222
|
+
@http.certificate = :cert
|
223
|
+
@http.private_key = :key
|
224
|
+
c = Net::HTTP.new 'localhost', 80
|
225
|
+
|
226
|
+
@http.ssl c
|
227
|
+
|
228
|
+
assert c.use_ssl?
|
229
|
+
assert_equal :cert, c.cert
|
230
|
+
assert_equal :key, c.key
|
231
|
+
end
|
232
|
+
|
233
|
+
def test_ssl_verify_mode
|
234
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
235
|
+
c = Net::HTTP.new 'localhost', 80
|
236
|
+
|
237
|
+
@http.ssl c
|
238
|
+
|
239
|
+
assert c.use_ssl?
|
240
|
+
assert_equal OpenSSL::SSL::VERIFY_NONE, c.verify_mode
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
244
|
+
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: net-http-persistent
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: "1.0"
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Eric Hodel
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain:
|
16
|
+
- |
|
17
|
+
-----BEGIN CERTIFICATE-----
|
18
|
+
MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy
|
19
|
+
YWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZFgNu
|
20
|
+
ZXQwHhcNMDcxMjIxMDIwNDE0WhcNMDgxMjIwMDIwNDE0WjBBMRAwDgYDVQQDDAdk
|
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
|
+
sCANiQ8BAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
|
29
|
+
BBS5k4Z75VSpdM0AclG2UvzFA/VW5DANBgkqhkiG9w0BAQUFAAOCAQEAHagT4lfX
|
30
|
+
kP/hDaiwGct7XPuVGbrOsKRVD59FF5kETBxEc9UQ1clKWngf8JoVuEoKD774dW19
|
31
|
+
bU0GOVWO+J6FMmT/Cp7nuFJ79egMf/gy4gfUfQMuvfcr6DvZUPIs9P/TlK59iMYF
|
32
|
+
DIOQ3DxdF3rMzztNUCizN4taVscEsjCcgW6WkUJnGdqlu3OHWpQxZBJkBTjPCoc6
|
33
|
+
UW6on70SFPmAy/5Cq0OJNGEWBfgD9q7rrs/X8GGwUWqXb85RXnUVi/P8Up75E0ag
|
34
|
+
14jEc90kN+C7oI/AGCBN0j6JnEtYIEJZibjjDJTSMWlUKKkj30kq7hlUC2CepJ4v
|
35
|
+
x52qPcexcYZR7w==
|
36
|
+
-----END CERTIFICATE-----
|
37
|
+
|
38
|
+
date: 2010-05-04 00:00:00 -07:00
|
39
|
+
default_executable:
|
40
|
+
dependencies:
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubyforge
|
43
|
+
prerelease: false
|
44
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
hash: 9
|
50
|
+
segments:
|
51
|
+
- 2
|
52
|
+
- 0
|
53
|
+
- 3
|
54
|
+
version: 2.0.3
|
55
|
+
type: :development
|
56
|
+
version_requirements: *id001
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: gemcutter
|
59
|
+
prerelease: false
|
60
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
hash: 11
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
- 5
|
69
|
+
- 0
|
70
|
+
version: 0.5.0
|
71
|
+
type: :development
|
72
|
+
version_requirements: *id002
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: hoe
|
75
|
+
prerelease: false
|
76
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 27
|
82
|
+
segments:
|
83
|
+
- 2
|
84
|
+
- 5
|
85
|
+
- 0
|
86
|
+
version: 2.5.0
|
87
|
+
type: :development
|
88
|
+
version_requirements: *id003
|
89
|
+
description: |-
|
90
|
+
Persistent connections using Net::HTTP plus a speed fix for 1.8. It's
|
91
|
+
thread-safe too!
|
92
|
+
email:
|
93
|
+
- drbrain@segment7.net
|
94
|
+
executables: []
|
95
|
+
|
96
|
+
extensions: []
|
97
|
+
|
98
|
+
extra_rdoc_files:
|
99
|
+
- History.txt
|
100
|
+
- Manifest.txt
|
101
|
+
- README.txt
|
102
|
+
files:
|
103
|
+
- .autotest
|
104
|
+
- History.txt
|
105
|
+
- Manifest.txt
|
106
|
+
- README.txt
|
107
|
+
- Rakefile
|
108
|
+
- lib/net/http/faster.rb
|
109
|
+
- lib/net/http/persistent.rb
|
110
|
+
- test/test_net_http_persistent.rb
|
111
|
+
has_rdoc: true
|
112
|
+
homepage: http://seattlerb.rubyforge.org/net-http-persistent
|
113
|
+
licenses: []
|
114
|
+
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options:
|
117
|
+
- --main
|
118
|
+
- README.txt
|
119
|
+
require_paths:
|
120
|
+
- lib
|
121
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
hash: 3
|
127
|
+
segments:
|
128
|
+
- 0
|
129
|
+
version: "0"
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
none: false
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
hash: 3
|
136
|
+
segments:
|
137
|
+
- 0
|
138
|
+
version: "0"
|
139
|
+
requirements: []
|
140
|
+
|
141
|
+
rubyforge_project: seattlerb
|
142
|
+
rubygems_version: 1.3.7.pre.1
|
143
|
+
signing_key:
|
144
|
+
specification_version: 3
|
145
|
+
summary: Persistent connections using Net::HTTP plus a speed fix for 1.8
|
146
|
+
test_files:
|
147
|
+
- test/test_net_http_persistent.rb
|
metadata.gz.sig
ADDED
Binary file
|