net-http-persistent 1.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig ADDED
Binary file
data/.autotest ADDED
@@ -0,0 +1,7 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ Autotest.add_hook :initialize do |at|
6
+ at.testlib = 'minitest/unit'
7
+ end
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2010-05-04
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,8 @@
1
+ .autotest
2
+ History.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ lib/net/http/faster.rb
7
+ lib/net/http/persistent.rb
8
+ test/test_net_http_persistent.rb
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,13 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ Hoe.plugin :git
7
+
8
+ Hoe.spec 'net-http-persistent' do |p|
9
+ self.rubyforge_name = 'seattlerb'
10
+ developer 'Eric Hodel', 'drbrain@segment7.net'
11
+ end
12
+
13
+ # vim: syntax=Ruby
@@ -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