glebtv-httpclient 3.2.7 → 3.2.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,58 +4,61 @@
4
4
  # (MIT Licensed). Thanks!
5
5
 
6
6
  require "lru_redux"
7
+ require 'thread'
7
8
 
8
- # Not thread-safe!
9
9
  class HTTPClient
10
10
  class LRUCache
11
11
 
12
12
  attr_reader :max_size, :ttl, :soft_ttl, :retry_delay
13
13
 
14
14
  def initialize(opts={})
15
+ @mutex = Mutex.new
16
+
15
17
  @max_size = Integer(opts[:max_size] || 100)
16
18
  @ttl = Float(opts[:ttl] || 0)
17
19
  @soft_ttl = Float(opts[:soft_ttl] || 0)
18
20
  @retry_delay = Float(opts[:retry_delay] || 0)
21
+
19
22
  raise "max_size must not be negative" if @max_size < 0
20
23
  raise "ttl must not be negative" if @ttl < 0
21
24
  raise "soft_ttl must not be negative" if @soft_ttl < 0
22
25
  raise "retry_delay must not be negative" if @retry_delay < 0
23
26
 
27
+ # we don't use thread safe variant, as we're doing thread safety ourselves
24
28
  @data = LruRedux::Cache.new(@max_size)
25
29
  end
26
30
 
27
- def store(key, value)
28
- expiration = Time.now + @ttl
29
- soft_expiration = Time.now + @soft_ttl
30
- @data[key] = Datum.new(value, expiration, soft_expiration)
31
- value
32
- end
33
-
34
- alias :[]= :store
35
-
36
31
  def fetch(key)
37
- datum = @data[key]
38
- if datum.nil?
39
- store(key, value = yield)
40
- elsif datum.expired?
41
- @data.delete(key)
42
- store(key, value = yield)
43
- elsif datum.soft_expired?
44
- begin
32
+ # for now, this means that DNS resolving is single-threaded
33
+ @mutex.synchronize do
34
+ datum = @data[key]
35
+ if datum.nil?
45
36
  store(key, value = yield)
46
- rescue RuntimeError => e
47
- datum.soft_expiration = (Time.now + retry_delay) if retry_delay > 0
37
+ elsif datum.expired?
38
+ @data.delete(key)
39
+ store(key, value = yield)
40
+ elsif datum.soft_expired?
41
+ begin
42
+ store(key, value = yield)
43
+ rescue RuntimeError => e
44
+ datum.soft_expiration = (Time.now + retry_delay) if retry_delay > 0
45
+ datum.value
46
+ end
47
+ else
48
48
  datum.value
49
49
  end
50
- else
51
- datum.value
52
50
  end
53
51
  end
54
52
 
55
- alias :[] :fetch
56
-
57
53
  private
58
54
 
55
+ def store(key, value)
56
+ expiration = Time.now + @ttl
57
+ soft_expiration = Time.now + @soft_ttl
58
+ @data[key] = Datum.new(value, expiration, soft_expiration)
59
+ value
60
+ end
61
+
59
62
  class Datum
60
63
  attr_reader :value, :expiration, :soft_expiration
61
64
  attr_writer :soft_expiration
@@ -123,9 +123,9 @@ class HTTPClient
123
123
  # use client_key=.
124
124
  #
125
125
  # Calling this method resets all existing sessions.
126
- def set_client_cert_file(cert_file, key_file)
126
+ def set_client_cert_file(cert_file, key_file, pass = nil)
127
127
  @client_cert = X509::Certificate.new(File.open(cert_file) { |f| f.read })
128
- @client_key = PKey::RSA.new(File.open(key_file) { |f| f.read })
128
+ @client_key = PKey::RSA.new(File.open(key_file) { |f| f.read }, pass)
129
129
  change_notify
130
130
  end
131
131
 
@@ -392,6 +392,7 @@ class HTTPClient
392
392
 
393
393
  def change_notify
394
394
  @client.reset_all
395
+ nil
395
396
  end
396
397
 
397
398
  def load_cacerts(cert_store)
@@ -1,3 +1,4 @@
1
1
  class HTTPClient
2
- VERSION = '3.2.7' unless defined?(VERSION)
2
+ VERSION = '3.2.8' unless defined?(VERSION)
3
3
  end
4
+
data/spec/basic_spec.rb CHANGED
@@ -9,7 +9,7 @@ describe HTTPClient do
9
9
  describe 'GET' do
10
10
  it 'performs normal GET' do
11
11
  HTTPClient.new.get(@srv.u('servlet')) do |s|
12
- s.should eq 'get'
12
+ expect(s).to eq 'get'
13
13
  end
14
14
  end
15
15
 
@@ -21,13 +21,13 @@ describe HTTPClient do
21
21
  it 'writes to file' do
22
22
  file = Tempfile.new('httpcl')
23
23
  HTTPClient.new.download_file(@srv.u('largebody'), file.path)
24
- file.read.length.should eq 1_000_000
24
+ expect(file.read.length).to eq 1_000_000
25
25
  end
26
26
 
27
27
  it 'compressed' do
28
28
  file = Tempfile.new('httpcl')
29
29
  @client.download_file(@srv.u('compressed?enc=gzip'), file.path)
30
- file.read.length.should eq 25
30
+ expect(file.read.length).to eq 25
31
31
  end
32
32
 
33
33
  it 'compressed transparent' do
@@ -36,13 +36,13 @@ describe HTTPClient do
36
36
  file = Tempfile.new('httpcl')
37
37
  @client.download_file(@srv.u('compressed?enc=gzip'), file.path)
38
38
  cnt = file.read
39
- cnt.length.should eq 5
40
- cnt.should eq 'hello'
39
+ expect(cnt.length).to eq 5
40
+ expect(cnt).to eq 'hello'
41
41
 
42
42
  @client.download_file(@srv.u('compressed?enc=deflate'), file.path)
43
43
  cnt = file.read
44
- cnt.length.should eq 5
45
- cnt.should eq 'hello'
44
+ expect(cnt.length).to eq 5
45
+ expect(cnt).to eq 'hello'
46
46
  end
47
47
 
48
48
  it 'compressed large' do
@@ -50,25 +50,25 @@ describe HTTPClient do
50
50
  @client.transparent_gzip_decompression = true
51
51
 
52
52
  content = @client.download_file(@srv.u('compressed_large?enc=gzip'), file.path)
53
- file.read.should eq LARGE_STR
53
+ expect(file.read).to eq LARGE_STR
54
54
 
55
55
  content = @client.download_file(@srv.u('compressed_large?enc=deflate'), file.path)
56
- file.read.should eq LARGE_STR
56
+ expect(file.read).to eq LARGE_STR
57
57
  end
58
58
  end
59
59
 
60
60
  describe '#get_content' do
61
61
  it 'normal' do
62
- @client.get_content(@srv.u('hello')).should eq 'hello'
63
- @client.get_content(@srv.u('redirect1')).should eq 'hello'
64
- @client.get_content(@srv.u('redirect2')).should eq 'hello'
62
+ expect(@client.get_content(@srv.u('hello'))).to eq 'hello'
63
+ expect(@client.get_content(@srv.u('redirect1'))).to eq 'hello'
64
+ expect(@client.get_content(@srv.u('redirect2'))).to eq 'hello'
65
65
  end
66
66
 
67
67
  it '127.0.0.1' do
68
68
  url = @srv.u.sub(/localhost/, '127.0.0.1')
69
- @client.get_content(url + 'hello').should eq 'hello'
70
- @client.get_content(url + 'redirect1').should eq 'hello'
71
- @client.get_content(url + 'redirect2').should eq 'hello'
69
+ expect(@client.get_content(url + 'hello')).to eq 'hello'
70
+ expect(@client.get_content(url + 'redirect1')).to eq 'hello'
71
+ expect(@client.get_content(url + 'redirect2')).to eq 'hello'
72
72
  end
73
73
 
74
74
  it 'redirect callback' do
@@ -79,8 +79,8 @@ describe HTTPClient do
79
79
  newuri
80
80
  }
81
81
 
82
- @client.get_content(@srv.u('relative_redirect')).should eq 'hello'
83
- called.should be_true
82
+ expect(@client.get_content(@srv.u('relative_redirect'))).to eq 'hello'
83
+ expect(called).to be_truthy
84
84
  end
85
85
 
86
86
  it 'errors' do
@@ -95,13 +95,13 @@ describe HTTPClient do
95
95
 
96
96
  it 'with block' do
97
97
  @client.get_content(@srv.u 'hello') do |str|
98
- str.should eq 'hello'
98
+ expect(str).to eq 'hello'
99
99
  end
100
100
  @client.get_content(@srv.u + 'redirect1') do |str|
101
- str.should eq 'hello'
101
+ expect(str).to eq 'hello'
102
102
  end
103
103
  @client.get_content(@srv.u + 'redirect2') do |str|
104
- str.should eq 'hello'
104
+ expect(str).to eq 'hello'
105
105
  end
106
106
  end
107
107
 
@@ -109,25 +109,25 @@ describe HTTPClient do
109
109
  @client.transparent_gzip_decompression = false
110
110
 
111
111
  content = @client.get_content(@srv.u 'compressed?enc=gzip')
112
- content.should_not eq 'hello'
113
- content.should eq GZIP_CONTENT
112
+ expect(content).not_to eq 'hello'
113
+ expect(content).to eq GZIP_CONTENT
114
114
  @client.transparent_gzip_decompression = true
115
115
 
116
116
  content = @client.get_content(@srv.u 'compressed?enc=gzip')
117
- content.should eq 'hello'
117
+ expect(content).to eq 'hello'
118
118
 
119
119
  content = @client.get_content(@srv.u 'compressed?enc=deflate')
120
- content.should eq 'hello'
120
+ expect(content).to eq 'hello'
121
121
  end
122
122
 
123
123
  it 'compressed large' do
124
124
  @client.transparent_gzip_decompression = true
125
125
 
126
126
  content = @client.get_content(@srv.u 'compressed_large?enc=gzip')
127
- content.should eq LARGE_STR
127
+ expect(content).to eq LARGE_STR
128
128
 
129
129
  content = @client.get_content(@srv.u 'compressed_large?enc=deflate')
130
- content.should eq LARGE_STR
130
+ expect(content).to eq LARGE_STR
131
131
  end
132
132
  end
133
133
  end
@@ -135,13 +135,13 @@ describe HTTPClient do
135
135
  describe 'get with block' do
136
136
  it 'works with filter_block: true' do
137
137
  @client.request(:get, @srv.u('hello')) do |str|
138
- str.should eq 'hello'
138
+ expect(str).to eq 'hello'
139
139
  end
140
140
  end
141
141
  it 'works with filter_block: false' do
142
142
  @client.request(:get, @srv.u('hello'), filter_block: false) do |req, str|
143
- req.class.name.should eq 'HTTP::Message'
144
- str.should eq 'hello'
143
+ expect(req.class.name).to eq 'HTTP::Message'
144
+ expect(str).to eq 'hello'
145
145
  end
146
146
  end
147
147
  end
@@ -152,8 +152,8 @@ describe HTTPClient do
152
152
  @client.debug_dev = str
153
153
  @client.get(@srv.u)
154
154
  lines = str.split(/(?:\r?\n)+/)
155
- lines[0].should eq '= Request'
156
- lines[4].should eq "User-Agent: HTTPClient #{HTTPClient::VERSION}"
155
+ expect(lines[0]).to eq '= Request'
156
+ expect(lines[4]).to eq "User-Agent: HTTPClient #{HTTPClient::VERSION}"
157
157
  end
158
158
 
159
159
  it 'custom' do
@@ -162,8 +162,8 @@ describe HTTPClient do
162
162
  client.debug_dev = str
163
163
  client.get(@srv.u)
164
164
  lines = str.split(/(?:\r?\n)+/)
165
- lines[0].should eq '= Request'
166
- lines[4].should eq 'User-Agent: agent_name_foo'
165
+ expect(lines[0]).to eq '= Request'
166
+ expect(lines[4]).to eq 'User-Agent: agent_name_foo'
167
167
  end
168
168
  end
169
169
 
@@ -173,62 +173,62 @@ describe HTTPClient do
173
173
  @client.debug_dev = str = ''
174
174
  @client.test_loopback_http_response << "hello\nworld\n"
175
175
  res = @client.get(@srv.u 'hello')
176
- res.http_version.should eq '0.9'
177
- res.status.should be_nil
178
- res.reason.should be_nil
179
- res.content.should eq "hello\nworld\n"
176
+ expect(res.http_version).to eq '0.9'
177
+ expect(res.status).to be_nil
178
+ expect(res.reason).to be_nil
179
+ expect(res.content).to eq "hello\nworld\n"
180
180
  lines = str.split(/(?:\r?\n)+/)
181
- lines[0].should eq "= Request"
182
- lines[2].should eq "! CONNECTION ESTABLISHED"
183
- lines[3].should eq "GET /hello HTTP/0.9"
184
- lines[7].should eq "Connection: close"
185
- lines[8].should eq "= Response"
186
- lines[9].should match /^hello$/
187
- lines[10].should match /^world$/
181
+ expect(lines[0]).to eq "= Request"
182
+ expect(lines[2]).to eq "! CONNECTION ESTABLISHED"
183
+ expect(lines[3]).to eq "GET /hello HTTP/0.9"
184
+ expect(lines[7]).to eq "Connection: close"
185
+ expect(lines[8]).to eq "= Response"
186
+ expect(lines[9]).to match /^hello$/
187
+ expect(lines[10]).to match /^world$/
188
188
  end
189
189
 
190
190
  it '1.0' do
191
- @client.protocol_version.should be_nil
191
+ expect(@client.protocol_version).to be_nil
192
192
  @client.protocol_version = 'HTTP/1.0'
193
- @client.protocol_version.should eq 'HTTP/1.0'
193
+ expect(@client.protocol_version).to eq 'HTTP/1.0'
194
194
  str = ""
195
195
  @client.debug_dev = str
196
196
  @client.get(@srv.u 'hello')
197
197
  lines = str.split(/(?:\r?\n)+/)
198
- lines[0].should eq "= Request"
199
- lines[2].should eq "! CONNECTION ESTABLISHED"
200
- lines[3].should eq "GET /hello HTTP/1.0"
201
- lines[7].should eq "Connection: close"
202
- lines[8].should eq "= Response"
198
+ expect(lines[0]).to eq "= Request"
199
+ expect(lines[2]).to eq "! CONNECTION ESTABLISHED"
200
+ expect(lines[3]).to eq "GET /hello HTTP/1.0"
201
+ expect(lines[7]).to eq "Connection: close"
202
+ expect(lines[8]).to eq "= Response"
203
203
  end
204
204
 
205
205
  it '1.1' do
206
- @client.protocol_version.should be_nil
206
+ expect(@client.protocol_version).to be_nil
207
207
  str = ""
208
208
  @client.debug_dev = str
209
209
  @client.get(@srv.u)
210
210
  lines = str.split(/(?:\r?\n)+/)
211
- lines[0].should eq "= Request"
212
- lines[2].should eq "! CONNECTION ESTABLISHED"
213
- lines[3].should eq "GET / HTTP/1.1"
214
- lines[7].should eq "Host: localhost:#{@srv.port}"
211
+ expect(lines[0]).to eq "= Request"
212
+ expect(lines[2]).to eq "! CONNECTION ESTABLISHED"
213
+ expect(lines[3]).to eq "GET / HTTP/1.1"
214
+ expect(lines[7]).to eq "Host: localhost:#{@srv.port}"
215
215
  @client.protocol_version = 'HTTP/1.1'
216
- @client.protocol_version.should eq 'HTTP/1.1'
216
+ expect(@client.protocol_version).to eq 'HTTP/1.1'
217
217
  str = ""
218
218
  @client.debug_dev = str
219
219
  @client.get(@srv.u)
220
220
  lines = str.split(/(?:\r?\n)+/)
221
- lines[0].should eq "= Request"
222
- lines[2].should eq "! CONNECTION ESTABLISHED"
223
- lines[3].should eq "GET / HTTP/1.1"
221
+ expect(lines[0]).to eq "= Request"
222
+ expect(lines[2]).to eq "! CONNECTION ESTABLISHED"
223
+ expect(lines[3]).to eq "GET / HTTP/1.1"
224
224
  @client.protocol_version = 'HTTP/1.0'
225
225
  str = ""
226
226
  @client.debug_dev = str
227
227
  @client.get(@srv.u)
228
228
  lines = str.split(/(?:\r?\n)+/)
229
- lines[0].should eq "= Request"
230
- lines[2].should eq "! CONNECTION ESTABLISHED"
231
- lines[3].should eq "GET / HTTP/1.0"
229
+ expect(lines[0]).to eq "= Request"
230
+ expect(lines[2]).to eq "! CONNECTION ESTABLISHED"
231
+ expect(lines[3]).to eq "GET / HTTP/1.0"
232
232
  end
233
233
  end
234
234
 
@@ -238,7 +238,7 @@ describe HTTPClient do
238
238
  @client.debug_dev = str
239
239
  @client.get(@srv.u)
240
240
  lines = str.split(/(?:\r?\n)+/)
241
- lines[5].should eq "Accept: */*"
241
+ expect(lines[5]).to eq "Accept: */*"
242
242
  end
243
243
 
244
244
  it 'sets properly' do
@@ -246,9 +246,9 @@ describe HTTPClient do
246
246
  @client.debug_dev = str
247
247
  @client.get(@srv.u, :header => {:Accept => 'text/html'})
248
248
  lines = str.split(/(?:\r?\n)+/)
249
- lines[4].should eq "Accept: text/html"
249
+ expect(lines[4]).to eq "Accept: text/html"
250
250
  lines.each do |line|
251
- line.should_not eq "Accept: */*"
251
+ expect(line).not_to eq "Accept: */*"
252
252
  end
253
253
  end
254
254
  end
@@ -256,9 +256,9 @@ describe HTTPClient do
256
256
  describe 'POST' do
257
257
  describe '#post_content' do
258
258
  it 'works' do
259
- @client.post_content(@srv.u('hello')).should eq 'hello'
260
- @client.post_content(@srv.u("redirect1")).should eq 'hello'
261
- @client.post_content(@srv.u("redirect2")).should eq 'hello'
259
+ expect(@client.post_content(@srv.u('hello'))).to eq 'hello'
260
+ expect(@client.post_content(@srv.u("redirect1"))).to eq 'hello'
261
+ expect(@client.post_content(@srv.u("redirect2"))).to eq 'hello'
262
262
  end
263
263
  end
264
264
 
@@ -269,8 +269,8 @@ describe HTTPClient do
269
269
  called = true
270
270
  newuri
271
271
  }
272
- @client.post_content(@srv.u("relative_redirect")).should eq 'hello'
273
- called.should be_true
272
+ expect(@client.post_content(@srv.u("relative_redirect"))).to eq 'hello'
273
+ expect(called).to be_truthy
274
274
  end
275
275
 
276
276
  it 'errors' do
@@ -287,40 +287,40 @@ describe HTTPClient do
287
287
  describe 'string io' do
288
288
  it do
289
289
  post_body = StringIO.new("1234567890")
290
- @client.post_content(@srv.u("servlet"), post_body).should eq 'post,1234567890'
290
+ expect(@client.post_content(@srv.u("servlet"), post_body)).to eq 'post,1234567890'
291
291
 
292
292
  # all browsers use GET for 302
293
293
  post_body = StringIO.new("1234567890")
294
- @client.post_content(@srv.u("servlet_413"), post_body).should eq '1234567890'
294
+ expect(@client.post_content(@srv.u("servlet_413"), post_body)).to eq '1234567890'
295
295
 
296
- @client.get_content(@srv.u("servlet_redirect_413")).should eq ''
296
+ expect(@client.get_content(@srv.u("servlet_redirect_413"))).to eq ''
297
297
 
298
298
  post_body = StringIO.new("1234567890")
299
- @client.post_content(@srv.u("servlet_redirect_413"), post_body).should eq ''
299
+ expect(@client.post_content(@srv.u("servlet_redirect_413"), post_body)).to eq ''
300
300
 
301
301
  post_body = StringIO.new("1234567890")
302
- @client.post_content(@srv.u("servlet_temporary_redirect"), post_body).should eq 'post,1234567890'
302
+ expect(@client.post_content(@srv.u("servlet_temporary_redirect"), post_body)).to eq 'post,1234567890'
303
303
 
304
304
  post_body = StringIO.new("1234567890")
305
- @client.post_content(@srv.u("servlet_see_other"), post_body).should eq 'get'
305
+ expect(@client.post_content(@srv.u("servlet_see_other"), post_body)).to eq 'get'
306
306
  end
307
307
 
308
308
  it 'doesnt rewind' do
309
309
  post_body = StringIO.new("1234567890")
310
310
  post_body.read(5)
311
- @client.post_content(@srv.u("servlet_temporary_redirect"), post_body).should eq 'post,67890'
311
+ expect(@client.post_content(@srv.u("servlet_temporary_redirect"), post_body)).to eq 'post,67890'
312
312
  end
313
313
  end
314
314
  end
315
315
 
316
316
  describe 'util' do
317
317
  it '#urify' do
318
- urify(nil).should be_nil
318
+ expect(urify(nil)).to be_nil
319
319
  uri = 'http://foo'
320
320
  # urify(uri).class.name.should eq 'HTTPClient::Util::AddressableURI'
321
- urify(uri).should eq urify(uri)
322
- urify(uri).to_s.should eq uri
323
- urify(urify(uri)).should eq urify(uri)
321
+ expect(urify(uri)).to eq urify(uri)
322
+ expect(urify(uri).to_s).to eq uri
323
+ expect(urify(urify(uri))).to eq urify(uri)
324
324
  end
325
325
  end
326
326
  end