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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 33e7bb7dfb1ddbf876fb650053215d19f03f94a0
4
- data.tar.gz: 4a5f3dea5b97925bf854abbedcaf2fbbe7bce915
3
+ metadata.gz: e431a2b363f87ec472a3c7d50656a1fcd1c054d7
4
+ data.tar.gz: 85a6326b3ba79941dd50b8636a99a423cd581328
5
5
  SHA512:
6
- metadata.gz: 457b76dba4f07d671e03d1a2e93f072d7a45a0722c23ce52051e987daf77d938946d6c67e914ed1e261b3e8bfd872876c0269e92cdd6798fcf818cbaa6180aed
7
- data.tar.gz: 37be025088bf9bcee7da15afa9a7174ceb9b3e740cab9a1a28d7a0a1abb40c622f8d3465939f8d7c6193107c514764333968c6e7e68c7e6ab7a120f215293f10
6
+ metadata.gz: eb3f3735bea1202b763ad5f32eaee8f40a16fdca132b4df1594095c06fc335ec45a7904f03a41b7342794ffde71d48e1440a051b1c2ded6f81e37f2caff9ec18
7
+ data.tar.gz: 7baf041485d74dc7aef7398f96690e43cf56a8e3fb211b41a50cd40ebb3a1e714d3ce9c42a1d621f77bfc2027420adbab2571f4733286f4a35326097320a30d8
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.1.1
1
+ 2.1.2
data/.travis.yml CHANGED
@@ -1,8 +1,8 @@
1
1
  rvm:
2
2
  - 1.9.3
3
3
  - 2.0.0
4
- - 2.1.0
5
- - 2.1.1
4
+ - 2.1.2
6
5
 
7
6
  notifications:
8
7
  email: false
8
+
data/Gemfile CHANGED
@@ -1,12 +1,3 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- platform :jruby do
4
- gem 'jruby-openssl'
5
- end
6
-
7
- platform :rbx do
8
- gem 'rubysl', '~> 2.0'
9
- gem 'rubinius-developer_tools'
10
- end
11
-
12
3
  gemspec
data/Gemfile.lock CHANGED
@@ -1,15 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- glebtv-httpclient (3.2.6)
4
+ glebtv-httpclient (3.2.8)
5
5
  lru_redux
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
9
9
  specs:
10
- activesupport (3.2.17)
11
- i18n (~> 0.6, >= 0.6.4)
12
- multi_json (~> 1.0)
10
+ activesupport (4.1.4)
11
+ i18n (~> 0.6, >= 0.6.9)
12
+ json (~> 1.7, >= 1.7.7)
13
+ minitest (~> 5.1)
14
+ thread_safe (~> 0.1)
15
+ tzinfo (~> 1.1)
13
16
  climate_control (0.0.3)
14
17
  activesupport (>= 3.0)
15
18
  coveralls (0.7.0)
@@ -19,266 +22,44 @@ GEM
19
22
  term-ansicolor
20
23
  thor
21
24
  diff-lcs (1.2.5)
22
- docile (1.1.3)
23
- ffi2-generators (0.1.1)
24
- i18n (0.6.9)
25
+ docile (1.1.5)
26
+ i18n (0.6.11)
25
27
  json (1.8.1)
26
28
  lru_redux (0.8.1)
27
- mime-types (2.2)
28
- multi_json (1.9.2)
29
- rake (10.3.0)
29
+ mime-types (2.3)
30
+ minitest (5.4.0)
31
+ multi_json (1.10.1)
32
+ netrc (0.7.7)
33
+ rake (10.3.2)
30
34
  rdoc (4.1.1)
31
35
  json (~> 1.4)
32
- rest-client (1.6.7)
33
- mime-types (>= 1.16)
34
- rspec (2.14.1)
35
- rspec-core (~> 2.14.0)
36
- rspec-expectations (~> 2.14.0)
37
- rspec-mocks (~> 2.14.0)
38
- rspec-core (2.14.8)
39
- rspec-expectations (2.14.5)
40
- diff-lcs (>= 1.1.3, < 2.0)
41
- rspec-mocks (2.14.6)
42
- rspecify (0.1.7)
43
- activesupport (>= 3.0)
44
- i18n (~> 0.6.0)
45
- ruby_parser (~> 2.3.1)
46
- ruby_scribe (~> 0.1.4)
47
- ruby_transform (~> 0.1.4)
48
- thor (~> 0.13)
49
- rubinius-coverage (2.0.3)
50
- rubinius-debugger (2.0.3)
51
- rubinius-developer_tools (2.0.0)
52
- rubinius-coverage (~> 2.0)
53
- rubinius-debugger (~> 2.0)
54
- rubinius-profiler (~> 2.0)
55
- rubinius-profiler (2.0.1)
56
- ruby_parser (2.3.1)
57
- sexp_processor (~> 3.0)
58
- ruby_scribe (0.1.5)
59
- activesupport (~> 3.0)
60
- i18n (~> 0.6.0)
61
- ruby_parser (~> 2.3.1)
62
- thor (~> 0.13)
63
- ruby_transform (0.1.5)
64
- activesupport (>= 3.0)
65
- i18n (~> 0.6.0)
66
- ruby_parser (~> 2.3.1)
67
- ruby_scribe (~> 0.1.4)
68
- thor (~> 0.13)
69
- rubysl (2.0.15)
70
- rubysl-abbrev (~> 2.0)
71
- rubysl-base64 (~> 2.0)
72
- rubysl-benchmark (~> 2.0)
73
- rubysl-bigdecimal (~> 2.0)
74
- rubysl-cgi (~> 2.0)
75
- rubysl-cgi-session (~> 2.0)
76
- rubysl-cmath (~> 2.0)
77
- rubysl-complex (~> 2.0)
78
- rubysl-continuation (~> 2.0)
79
- rubysl-coverage (~> 2.0)
80
- rubysl-csv (~> 2.0)
81
- rubysl-curses (~> 2.0)
82
- rubysl-date (~> 2.0)
83
- rubysl-delegate (~> 2.0)
84
- rubysl-digest (~> 2.0)
85
- rubysl-drb (~> 2.0)
86
- rubysl-e2mmap (~> 2.0)
87
- rubysl-english (~> 2.0)
88
- rubysl-enumerator (~> 2.0)
89
- rubysl-erb (~> 2.0)
90
- rubysl-etc (~> 2.0)
91
- rubysl-expect (~> 2.0)
92
- rubysl-fcntl (~> 2.0)
93
- rubysl-fiber (~> 2.0)
94
- rubysl-fileutils (~> 2.0)
95
- rubysl-find (~> 2.0)
96
- rubysl-forwardable (~> 2.0)
97
- rubysl-getoptlong (~> 2.0)
98
- rubysl-gserver (~> 2.0)
99
- rubysl-io-console (~> 2.0)
100
- rubysl-io-nonblock (~> 2.0)
101
- rubysl-io-wait (~> 2.0)
102
- rubysl-ipaddr (~> 2.0)
103
- rubysl-irb (~> 2.0)
104
- rubysl-logger (~> 2.0)
105
- rubysl-mathn (~> 2.0)
106
- rubysl-matrix (~> 2.0)
107
- rubysl-mkmf (~> 2.0)
108
- rubysl-monitor (~> 2.0)
109
- rubysl-mutex_m (~> 2.0)
110
- rubysl-net-ftp (~> 2.0)
111
- rubysl-net-http (~> 2.0)
112
- rubysl-net-imap (~> 2.0)
113
- rubysl-net-pop (~> 2.0)
114
- rubysl-net-protocol (~> 2.0)
115
- rubysl-net-smtp (~> 2.0)
116
- rubysl-net-telnet (~> 2.0)
117
- rubysl-nkf (~> 2.0)
118
- rubysl-observer (~> 2.0)
119
- rubysl-open-uri (~> 2.0)
120
- rubysl-open3 (~> 2.0)
121
- rubysl-openssl (~> 2.0)
122
- rubysl-optparse (~> 2.0)
123
- rubysl-ostruct (~> 2.0)
124
- rubysl-pathname (~> 2.0)
125
- rubysl-prettyprint (~> 2.0)
126
- rubysl-prime (~> 2.0)
127
- rubysl-profile (~> 2.0)
128
- rubysl-profiler (~> 2.0)
129
- rubysl-pstore (~> 2.0)
130
- rubysl-pty (~> 2.0)
131
- rubysl-rational (~> 2.0)
132
- rubysl-readline (~> 2.0)
133
- rubysl-resolv (~> 2.0)
134
- rubysl-rexml (~> 2.0)
135
- rubysl-rinda (~> 2.0)
136
- rubysl-rss (~> 2.0)
137
- rubysl-scanf (~> 2.0)
138
- rubysl-securerandom (~> 2.0)
139
- rubysl-set (~> 2.0)
140
- rubysl-shellwords (~> 2.0)
141
- rubysl-singleton (~> 2.0)
142
- rubysl-socket (~> 2.0)
143
- rubysl-stringio (~> 2.0)
144
- rubysl-strscan (~> 2.0)
145
- rubysl-sync (~> 2.0)
146
- rubysl-syslog (~> 2.0)
147
- rubysl-tempfile (~> 2.0)
148
- rubysl-thread (~> 2.0)
149
- rubysl-thwait (~> 2.0)
150
- rubysl-time (~> 2.0)
151
- rubysl-timeout (~> 2.0)
152
- rubysl-tmpdir (~> 2.0)
153
- rubysl-tsort (~> 2.0)
154
- rubysl-un (~> 2.0)
155
- rubysl-uri (~> 2.0)
156
- rubysl-weakref (~> 2.0)
157
- rubysl-webrick (~> 2.0)
158
- rubysl-xmlrpc (~> 2.0)
159
- rubysl-yaml (~> 2.0)
160
- rubysl-zlib (~> 2.0)
161
- rubysl-abbrev (2.0.4)
162
- rubysl-base64 (2.0.0)
163
- rubysl-benchmark (2.0.1)
164
- rubysl-bigdecimal (2.0.2)
165
- rubysl-cgi (2.0.1)
166
- rubysl-cgi-session (2.0.1)
167
- rubysl-cmath (2.0.0)
168
- rubysl-complex (2.0.0)
169
- rubysl-continuation (2.0.0)
170
- rubysl-coverage (2.0.3)
171
- rubysl-csv (2.0.2)
172
- rubysl-english (~> 2.0)
173
- rubysl-curses (2.0.1)
174
- rubysl-date (2.0.6)
175
- rubysl-delegate (2.0.1)
176
- rubysl-digest (2.0.3)
177
- rubysl-drb (2.0.1)
178
- rubysl-e2mmap (2.0.0)
179
- rubysl-english (2.0.0)
180
- rubysl-enumerator (2.0.0)
181
- rubysl-erb (2.0.1)
182
- rubysl-etc (2.0.3)
183
- ffi2-generators (~> 0.1)
184
- rubysl-expect (2.0.0)
185
- rubysl-fcntl (2.0.4)
186
- ffi2-generators (~> 0.1)
187
- rubysl-fiber (2.0.0)
188
- rubysl-fileutils (2.0.3)
189
- rubysl-find (2.0.1)
190
- rubysl-forwardable (2.0.1)
191
- rubysl-getoptlong (2.0.0)
192
- rubysl-gserver (2.0.0)
193
- rubysl-socket (~> 2.0)
194
- rubysl-thread (~> 2.0)
195
- rubysl-io-console (2.0.0)
196
- rubysl-io-nonblock (2.0.0)
197
- rubysl-io-wait (2.0.0)
198
- rubysl-ipaddr (2.0.0)
199
- rubysl-irb (2.0.4)
200
- rubysl-e2mmap (~> 2.0)
201
- rubysl-mathn (~> 2.0)
202
- rubysl-readline (~> 2.0)
203
- rubysl-thread (~> 2.0)
204
- rubysl-logger (2.0.0)
205
- rubysl-mathn (2.0.0)
206
- rubysl-matrix (2.1.0)
207
- rubysl-e2mmap (~> 2.0)
208
- rubysl-mkmf (2.0.1)
209
- rubysl-fileutils (~> 2.0)
210
- rubysl-shellwords (~> 2.0)
211
- rubysl-monitor (2.0.0)
212
- rubysl-mutex_m (2.0.0)
213
- rubysl-net-ftp (2.0.1)
214
- rubysl-net-http (2.0.4)
215
- rubysl-cgi (~> 2.0)
216
- rubysl-erb (~> 2.0)
217
- rubysl-singleton (~> 2.0)
218
- rubysl-net-imap (2.0.1)
219
- rubysl-net-pop (2.0.1)
220
- rubysl-net-protocol (2.0.1)
221
- rubysl-net-smtp (2.0.1)
222
- rubysl-net-telnet (2.0.0)
223
- rubysl-nkf (2.0.1)
224
- rubysl-observer (2.0.0)
225
- rubysl-open-uri (2.0.0)
226
- rubysl-open3 (2.0.0)
227
- rubysl-openssl (2.1.0)
228
- rubysl-optparse (2.0.1)
229
- rubysl-shellwords (~> 2.0)
230
- rubysl-ostruct (2.0.4)
231
- rubysl-pathname (2.0.0)
232
- rubysl-prettyprint (2.0.3)
233
- rubysl-prime (2.0.1)
234
- rubysl-profile (2.0.0)
235
- rubysl-profiler (2.0.1)
236
- rubysl-pstore (2.0.0)
237
- rubysl-pty (2.0.2)
238
- rubysl-rational (2.0.1)
239
- rubysl-readline (2.0.2)
240
- rubysl-resolv (2.1.0)
241
- rubysl-rexml (2.0.2)
242
- rubysl-rinda (2.0.1)
243
- rubysl-rss (2.0.0)
244
- rubysl-scanf (2.0.0)
245
- rubysl-securerandom (2.0.0)
246
- rubysl-set (2.0.1)
247
- rubysl-shellwords (2.0.0)
248
- rubysl-singleton (2.0.0)
249
- rubysl-socket (2.0.1)
250
- rubysl-stringio (2.0.0)
251
- rubysl-strscan (2.0.0)
252
- rubysl-sync (2.0.0)
253
- rubysl-syslog (2.0.1)
254
- ffi2-generators (~> 0.1)
255
- rubysl-tempfile (2.0.1)
256
- rubysl-thread (2.0.2)
257
- rubysl-thwait (2.0.0)
258
- rubysl-time (2.0.3)
259
- rubysl-timeout (2.0.0)
260
- rubysl-tmpdir (2.0.1)
261
- rubysl-tsort (2.0.1)
262
- rubysl-un (2.0.0)
263
- rubysl-fileutils (~> 2.0)
264
- rubysl-optparse (~> 2.0)
265
- rubysl-uri (2.0.0)
266
- rubysl-weakref (2.0.0)
267
- rubysl-webrick (2.0.0)
268
- rubysl-xmlrpc (2.0.0)
269
- rubysl-yaml (2.0.4)
270
- rubysl-zlib (2.0.1)
271
- sexp_processor (3.2.0)
272
- simplecov (0.8.2)
36
+ rest-client (1.7.2)
37
+ mime-types (>= 1.16, < 3.0)
38
+ netrc (~> 0.7)
39
+ rspec (3.0.0)
40
+ rspec-core (~> 3.0.0)
41
+ rspec-expectations (~> 3.0.0)
42
+ rspec-mocks (~> 3.0.0)
43
+ rspec-core (3.0.3)
44
+ rspec-support (~> 3.0.0)
45
+ rspec-expectations (3.0.3)
46
+ diff-lcs (>= 1.2.0, < 2.0)
47
+ rspec-support (~> 3.0.0)
48
+ rspec-mocks (3.0.3)
49
+ rspec-support (~> 3.0.0)
50
+ rspec-support (3.0.3)
51
+ simplecov (0.9.0)
273
52
  docile (~> 1.1.0)
274
53
  multi_json
275
54
  simplecov-html (~> 0.8.0)
276
55
  simplecov-html (0.8.0)
277
56
  term-ansicolor (1.3.0)
278
57
  tins (~> 1.0)
279
- test-unit (2.5.5)
280
58
  thor (0.19.1)
281
- tins (1.1.0)
59
+ thread_safe (0.3.4)
60
+ tins (1.3.0)
61
+ tzinfo (1.2.2)
62
+ thread_safe (~> 0.1)
282
63
 
283
64
  PLATFORMS
284
65
  ruby
@@ -288,11 +69,6 @@ DEPENDENCIES
288
69
  climate_control
289
70
  coveralls
290
71
  glebtv-httpclient!
291
- jruby-openssl
292
72
  rake
293
73
  rdoc
294
74
  rspec
295
- rspecify
296
- rubinius-developer_tools
297
- rubysl (~> 2.0)
298
- test-unit
data/README.md CHANGED
@@ -5,6 +5,7 @@ I just try to make it work properly (as a browser would) for my use cases.
5
5
  [![Build Status](https://travis-ci.org/glebtv/httpclient.png?branch=master)](https://travis-ci.org/glebtv/httpclient)
6
6
  [![Gem Version](https://badge.fury.io/rb/glebtv-httpclient.png)](http://badge.fury.io/rb/glebtv-httpclient)
7
7
  [![Dependency Status](https://www.versioneye.com/user/projects/534eebc9fe0d0784f30008f6/badge.png)](https://www.versioneye.com/user/projects/534eebc9fe0d0784f30008f6)
8
+ [![Dependency Status](https://www.versioneye.com/user/projects/53e73f2b35080d699f000093/badge.svg?style=flat)](https://www.versioneye.com/user/projects/53e73f2b35080d699f000093)
8
9
 
9
10
  If you don't like how something works, please send a PR or use original gem: https://github.com/nahi/httpclient
10
11
 
data/httpclient.gemspec CHANGED
@@ -24,10 +24,9 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_development_dependency 'bundler'
26
26
  spec.add_development_dependency 'rake'
27
- spec.add_development_dependency 'test-unit'
28
27
  spec.add_development_dependency 'rspec'
29
28
  spec.add_development_dependency 'rdoc'
30
29
  spec.add_development_dependency 'coveralls'
31
30
  spec.add_development_dependency 'climate_control'
32
- spec.add_development_dependency 'rspecify'
33
31
  end
32
+
@@ -8,6 +8,7 @@
8
8
 
9
9
  require 'digest/md5'
10
10
  require 'httpclient/session'
11
+ require 'mutex_m'
11
12
 
12
13
 
13
14
  class HTTPClient
@@ -229,40 +230,48 @@ class HTTPClient
229
230
  # Used in WWWAuth and ProxyAuth.
230
231
  class BasicAuth
231
232
  include HTTPClient::Util
233
+ include Mutex_m
232
234
 
233
235
  # Authentication scheme.
234
236
  attr_reader :scheme
235
237
 
236
238
  # Creates new BasicAuth filter.
237
239
  def initialize
240
+ super
238
241
  @cred = nil
239
242
  @set = false
240
243
  @auth = {}
241
- @challengeable = {}
244
+ @challenge = {}
242
245
  @scheme = "Basic"
243
246
  end
244
247
 
245
248
  # Resets challenge state. Do not send '*Authorization' header until the
246
249
  # server sends '*Authentication' again.
247
250
  def reset_challenge
248
- @challengeable.clear
251
+ synchronize {
252
+ @challenge.clear
253
+ }
249
254
  end
250
255
 
251
256
  # Set authentication credential.
252
257
  # uri == nil for generic purpose (allow to use user/password for any URL).
253
258
  def set(uri, user, passwd)
254
- @set = true
255
- if uri.nil?
256
- @cred = ["#{user}:#{passwd}"].pack('m').tr("\n", '')
257
- else
258
- uri = Util.uri_dirname(uri)
259
- @auth[uri] = ["#{user}:#{passwd}"].pack('m').tr("\n", '')
259
+ synchronize do
260
+ if uri.nil?
261
+ @cred = ["#{user}:#{passwd}"].pack('m').tr("\n", '')
262
+ else
263
+ uri = Util.uri_dirname(uri)
264
+ @auth[uri] = ["#{user}:#{passwd}"].pack('m').tr("\n", '')
265
+ end
266
+ @set = true
260
267
  end
261
268
  end
262
269
 
263
270
  # have we marked this as set - ie that it's valid to use in this context?
264
271
  def set?
265
- @set == true
272
+ synchronize {
273
+ @set == true
274
+ }
266
275
  end
267
276
 
268
277
  # Response handler: returns credential.
@@ -271,50 +280,63 @@ class HTTPClient
271
280
  # * child page of defined credential
272
281
  def get(req)
273
282
  target_uri = req.header.request_uri
274
- return nil unless @challengeable.find { |uri, ok|
275
- Util.uri_part_of(target_uri, uri) and ok
276
- }
277
- return @cred if @cred
278
- Util.hash_find_value(@auth) { |uri, cred|
279
- Util.uri_part_of(target_uri, uri)
283
+ synchronize {
284
+ return nil unless @challenge.find { |uri, ok|
285
+ Util.uri_part_of(target_uri, uri) and ok
286
+ }
287
+ return @cred if @cred
288
+ Util.hash_find_value(@auth) { |uri, cred|
289
+ Util.uri_part_of(target_uri, uri)
290
+ }
280
291
  }
281
292
  end
282
293
 
283
294
  # Challenge handler: remember URL for response.
284
295
  def challenge(uri, param_str = nil)
285
- @challengeable[urify(uri)] = true
286
- true
296
+ synchronize {
297
+ @challenge[urify(uri)] = true
298
+ true
299
+ }
287
300
  end
288
301
  end
289
302
 
290
303
  class ProxyBasicAuth < BasicAuth
291
304
 
292
305
  def set(uri, user, passwd)
293
- @set = true
294
- @cred = ["#{user}:#{passwd}"].pack('m').tr("\n", '')
306
+ synchronize do
307
+ @cred = ["#{user}:#{passwd}"].pack('m').tr("\n", '')
308
+ @set = true
309
+ end
295
310
  end
296
311
 
297
312
  def get(req)
298
313
  target_uri = req.header.request_uri
299
- return nil unless @challengeable['challenged']
300
- @cred
314
+ synchronize {
315
+ return nil unless @challenge['challenged']
316
+ @cred
317
+ }
301
318
  end
302
319
 
303
320
  # Challenge handler: remember URL for response.
304
321
  def challenge(uri, param_str = nil)
305
- @challengeable['challenged'] = true
306
- true
322
+ synchronize {
323
+ @challenge['challenged'] = true
324
+ true
325
+ }
307
326
  end
308
327
  end
309
328
 
310
329
  # Authentication filter for handling DigestAuth negotiation.
311
330
  # Used in WWWAuth.
312
331
  class DigestAuth
332
+ include Mutex_m
333
+
313
334
  # Authentication scheme.
314
335
  attr_reader :scheme
315
336
 
316
337
  # Creates new DigestAuth filter.
317
338
  def initialize
339
+ super
318
340
  @auth = {}
319
341
  @challenge = {}
320
342
  @set = false
@@ -325,22 +347,28 @@ class HTTPClient
325
347
  # Resets challenge state. Do not send '*Authorization' header until the
326
348
  # server sends '*Authentication' again.
327
349
  def reset_challenge
328
- @challenge.clear
350
+ synchronize do
351
+ @challenge.clear
352
+ end
329
353
  end
330
354
 
331
355
  # Set authentication credential.
332
356
  # uri == nil is ignored.
333
357
  def set(uri, user, passwd)
334
- @set = true
335
- if uri
336
- uri = Util.uri_dirname(uri)
337
- @auth[uri] = [user, passwd]
358
+ synchronize do
359
+ if uri
360
+ uri = Util.uri_dirname(uri)
361
+ @auth[uri] = [user, passwd]
362
+ end
363
+ @set = true
338
364
  end
339
365
  end
340
366
 
341
367
  # have we marked this as set - ie that it's valid to use in this context?
342
368
  def set?
343
- @set == true
369
+ synchronize {
370
+ @set == true
371
+ }
344
372
  end
345
373
 
346
374
  # Response handler: returns credential.
@@ -349,21 +377,25 @@ class HTTPClient
349
377
  # * child page of defined credential
350
378
  def get(req)
351
379
  target_uri = req.header.request_uri
352
- param = Util.hash_find_value(@challenge) { |uri, v|
353
- Util.uri_part_of(target_uri, uri)
354
- }
355
- return nil unless param
356
- user, passwd = Util.hash_find_value(@auth) { |uri, auth_data|
357
- Util.uri_part_of(target_uri, uri)
380
+ synchronize {
381
+ param = Util.hash_find_value(@challenge) { |uri, v|
382
+ Util.uri_part_of(target_uri, uri)
383
+ }
384
+ return nil unless param
385
+ user, passwd = Util.hash_find_value(@auth) { |uri, auth_data|
386
+ Util.uri_part_of(target_uri, uri)
387
+ }
388
+ return nil unless user
389
+ calc_cred(req, user, passwd, param)
358
390
  }
359
- return nil unless user
360
- calc_cred(req, user, passwd, param)
361
391
  end
362
392
 
363
393
  # Challenge handler: remember URL and challenge token for response.
364
394
  def challenge(uri, param_str)
365
- @challenge[uri] = parse_challenge_param(param_str)
366
- true
395
+ synchronize {
396
+ @challenge[uri] = parse_challenge_param(param_str)
397
+ true
398
+ }
367
399
  end
368
400
 
369
401
  private
@@ -445,8 +477,10 @@ class HTTPClient
445
477
 
446
478
  # overrides DigestAuth#set. sets default user name and password. uri is not used.
447
479
  def set(uri, user, passwd)
448
- @set = true
449
- @auth = [user, passwd]
480
+ synchronize do
481
+ @set = true
482
+ @auth = [user, passwd]
483
+ end
450
484
  end
451
485
 
452
486
  # overrides DigestAuth#get. Uses default user name and password
@@ -454,20 +488,26 @@ class HTTPClient
454
488
  # before
455
489
  def get(req)
456
490
  target_uri = req.header.request_uri
457
- param = @challenge
458
- return nil unless param
459
- user, passwd = @auth
460
- return nil unless user
461
- calc_cred(req, user, passwd, param)
491
+ synchronize {
492
+ param = @challenge
493
+ return nil unless param
494
+ user, passwd = @auth
495
+ return nil unless user
496
+ calc_cred(req, user, passwd, param)
497
+ }
462
498
  end
463
499
 
464
500
  def reset_challenge
465
- @challenge = nil
501
+ synchronize do
502
+ @challenge = nil
503
+ end
466
504
  end
467
505
 
468
506
  def challenge(uri, param_str)
469
- @challenge = parse_challenge_param(param_str)
470
- true
507
+ synchronize {
508
+ @challenge = parse_challenge_param(param_str)
509
+ true
510
+ }
471
511
  end
472
512
 
473
513
  end
@@ -477,6 +517,8 @@ class HTTPClient
477
517
  #
478
518
  # NegotiateAuth depends on 'ruby/ntlm' module.
479
519
  class NegotiateAuth
520
+ include Mutex_m
521
+
480
522
  # Authentication scheme.
481
523
  attr_reader :scheme
482
524
  # NTLM opt for ruby/ntlm. {:ntlmv2 => true} by default.
@@ -484,6 +526,7 @@ class HTTPClient
484
526
 
485
527
  # Creates new NegotiateAuth filter.
486
528
  def initialize(scheme = "Negotiate")
529
+ super()
487
530
  @auth = {}
488
531
  @auth_default = nil
489
532
  @challenge = {}
@@ -497,24 +540,30 @@ class HTTPClient
497
540
  # Resets challenge state. Do not send '*Authorization' header until the
498
541
  # server sends '*Authentication' again.
499
542
  def reset_challenge
500
- @challenge.clear
543
+ synchronize do
544
+ @challenge.clear
545
+ end
501
546
  end
502
547
 
503
548
  # Set authentication credential.
504
549
  # uri == nil for generic purpose (allow to use user/password for any URL).
505
550
  def set(uri, user, passwd)
506
- @set = true
507
- if uri
508
- uri = Util.uri_dirname(uri)
509
- @auth[uri] = [user, passwd]
510
- else
511
- @auth_default = [user, passwd]
551
+ synchronize do
552
+ if uri
553
+ uri = Util.uri_dirname(uri)
554
+ @auth[uri] = [user, passwd]
555
+ else
556
+ @auth_default = [user, passwd]
557
+ end
558
+ @set = true
512
559
  end
513
560
  end
514
561
 
515
562
  # have we marked this as set - ie that it's valid to use in this context?
516
563
  def set?
517
- @set == true
564
+ synchronize {
565
+ @set == true
566
+ }
518
567
  end
519
568
 
520
569
  # Response handler: returns credential.
@@ -522,50 +571,54 @@ class HTTPClient
522
571
  def get(req)
523
572
  return nil unless NTLMEnabled
524
573
  target_uri = req.header.request_uri
525
- domain_uri, param = @challenge.find { |uri, v|
526
- Util.uri_part_of(target_uri, uri)
527
- }
528
- return nil unless param
529
- user, passwd = Util.hash_find_value(@auth) { |uri, auth_data|
530
- Util.uri_part_of(target_uri, uri)
574
+ synchronize {
575
+ domain_uri, param = @challenge.find { |uri, v|
576
+ Util.uri_part_of(target_uri, uri)
577
+ }
578
+ return nil unless param
579
+ user, passwd = Util.hash_find_value(@auth) { |uri, auth_data|
580
+ Util.uri_part_of(target_uri, uri)
581
+ }
582
+ unless user
583
+ user, passwd = @auth_default
584
+ end
585
+ return nil unless user
586
+ domain = nil
587
+ domain, user = user.split("\\") if user.index("\\")
588
+ state = param[:state]
589
+ authphrase = param[:authphrase]
590
+ case state
591
+ when :init
592
+ t1 = Net::NTLM::Message::Type1.new
593
+ t1.domain = domain if domain
594
+ return t1.encode64
595
+ when :response
596
+ t2 = Net::NTLM::Message.decode64(authphrase)
597
+ param = {:user => user, :password => passwd}
598
+ param[:domain] = domain if domain
599
+ t3 = t2.response(param, @ntlm_opt.dup)
600
+ @challenge.delete(domain_uri)
601
+ return t3.encode64
602
+ end
603
+ nil
531
604
  }
532
- unless user
533
- user, passwd = @auth_default
534
- end
535
- return nil unless user
536
- domain = nil
537
- domain, user = user.split("\\") if user.index("\\")
538
- state = param[:state]
539
- authphrase = param[:authphrase]
540
- case state
541
- when :init
542
- t1 = Net::NTLM::Message::Type1.new
543
- t1.domain = domain if domain
544
- return t1.encode64
545
- when :response
546
- t2 = Net::NTLM::Message.decode64(authphrase)
547
- param = {:user => user, :password => passwd}
548
- param[:domain] = domain if domain
549
- t3 = t2.response(param, @ntlm_opt.dup)
550
- @challenge.delete(domain_uri)
551
- return t3.encode64
552
- end
553
- nil
554
605
  end
555
606
 
556
607
  # Challenge handler: remember URL and challenge token for response.
557
608
  def challenge(uri, param_str)
558
609
  return false unless NTLMEnabled
559
- if param_str.nil? or @challenge[uri].nil?
560
- c = @challenge[uri] = {}
561
- c[:state] = :init
562
- c[:authphrase] = ""
563
- else
564
- c = @challenge[uri]
565
- c[:state] = :response
566
- c[:authphrase] = param_str
567
- end
568
- true
610
+ synchronize {
611
+ if param_str.nil? or @challenge[uri].nil?
612
+ c = @challenge[uri] = {}
613
+ c[:state] = :init
614
+ c[:authphrase] = ""
615
+ else
616
+ c = @challenge[uri]
617
+ c[:state] = :response
618
+ c[:authphrase] = param_str
619
+ end
620
+ true
621
+ }
569
622
  end
570
623
  end
571
624
 
@@ -575,11 +628,14 @@ class HTTPClient
575
628
  #
576
629
  # SSPINegotiateAuth depends on 'win32/sspi' module.
577
630
  class SSPINegotiateAuth
631
+ include Mutex_m
632
+
578
633
  # Authentication scheme.
579
634
  attr_reader :scheme
580
635
 
581
636
  # Creates new SSPINegotiateAuth filter.
582
637
  def initialize
638
+ super
583
639
  @challenge = {}
584
640
  @scheme = "Negotiate"
585
641
  end
@@ -587,7 +643,9 @@ class HTTPClient
587
643
  # Resets challenge state. Do not send '*Authorization' header until the
588
644
  # server sends '*Authentication' again.
589
645
  def reset_challenge
590
- @challenge.clear
646
+ synchronize do
647
+ @challenge.clear
648
+ end
591
649
  end
592
650
 
593
651
  # Set authentication credential.
@@ -607,48 +665,52 @@ class HTTPClient
607
665
  def get(req)
608
666
  return nil unless SSPIEnabled || GSSAPIEnabled
609
667
  target_uri = req.header.request_uri
610
- domain_uri, param = @challenge.find { |uri, v|
611
- Util.uri_part_of(target_uri, uri)
612
- }
613
- return nil unless param
614
- state = param[:state]
615
- authenticator = param[:authenticator]
616
- authphrase = param[:authphrase]
617
- case state
618
- when :init
619
- if SSPIEnabled
620
- authenticator = param[:authenticator] = Win32::SSPI::NegotiateAuth.new
621
- return authenticator.get_initial_token(@scheme)
622
- else # use GSSAPI
623
- authenticator = param[:authenticator] = GSSAPI::Simple.new(domain_uri.host, 'HTTP')
624
- # Base64 encode the context token
625
- return [authenticator.init_context].pack('m').gsub(/\n/,'')
626
- end
627
- when :response
628
- @challenge.delete(domain_uri)
629
- if SSPIEnabled
630
- return authenticator.complete_authentication(authphrase)
631
- else # use GSSAPI
632
- return authenticator.init_context(authphrase.unpack('m').pop)
668
+ synchronize {
669
+ domain_uri, param = @challenge.find { |uri, v|
670
+ Util.uri_part_of(target_uri, uri)
671
+ }
672
+ return nil unless param
673
+ state = param[:state]
674
+ authenticator = param[:authenticator]
675
+ authphrase = param[:authphrase]
676
+ case state
677
+ when :init
678
+ if SSPIEnabled
679
+ authenticator = param[:authenticator] = Win32::SSPI::NegotiateAuth.new
680
+ return authenticator.get_initial_token(@scheme)
681
+ else # use GSSAPI
682
+ authenticator = param[:authenticator] = GSSAPI::Simple.new(domain_uri.host, 'HTTP')
683
+ # Base64 encode the context token
684
+ return [authenticator.init_context].pack('m').gsub(/\n/,'')
685
+ end
686
+ when :response
687
+ @challenge.delete(domain_uri)
688
+ if SSPIEnabled
689
+ return authenticator.complete_authentication(authphrase)
690
+ else # use GSSAPI
691
+ return authenticator.init_context(authphrase.unpack('m').pop)
692
+ end
633
693
  end
634
- end
635
- nil
694
+ nil
695
+ }
636
696
  end
637
697
 
638
698
  # Challenge handler: remember URL and challenge token for response.
639
699
  def challenge(uri, param_str)
640
700
  return false unless SSPIEnabled || GSSAPIEnabled
641
- if param_str.nil? or @challenge[uri].nil?
642
- c = @challenge[uri] = {}
643
- c[:state] = :init
644
- c[:authenticator] = nil
645
- c[:authphrase] = ""
646
- else
647
- c = @challenge[uri]
648
- c[:state] = :response
649
- c[:authphrase] = param_str
650
- end
651
- true
701
+ synchronize {
702
+ if param_str.nil? or @challenge[uri].nil?
703
+ c = @challenge[uri] = {}
704
+ c[:state] = :init
705
+ c[:authenticator] = nil
706
+ c[:authphrase] = ""
707
+ else
708
+ c = @challenge[uri]
709
+ c[:state] = :response
710
+ c[:authphrase] = param_str
711
+ end
712
+ true
713
+ }
652
714
  end
653
715
  end
654
716
 
@@ -664,6 +726,7 @@ class HTTPClient
664
726
  #
665
727
  class OAuth
666
728
  include HTTPClient::Util
729
+ include Mutex_m
667
730
 
668
731
  # Authentication scheme.
669
732
  attr_reader :scheme
@@ -737,9 +800,10 @@ class HTTPClient
737
800
 
738
801
  # Creates new DigestAuth filter.
739
802
  def initialize
803
+ super
740
804
  @config = nil # common config
741
805
  @auth = {} # configs for each site
742
- @challengeable = {}
806
+ @challenge = {}
743
807
  @nonce_count = 0
744
808
  @signature_handler = {
745
809
  'HMAC-SHA1' => method(:sign_hmac_sha1)
@@ -750,7 +814,9 @@ class HTTPClient
750
814
  # Resets challenge state. Do not send '*Authorization' header until the
751
815
  # server sends '*Authentication' again.
752
816
  def reset_challenge
753
- @challengeable.clear
817
+ synchronize do
818
+ @challenge.clear
819
+ end
754
820
  end
755
821
 
756
822
  # Set authentication credential.
@@ -766,24 +832,21 @@ class HTTPClient
766
832
 
767
833
  # Set authentication credential.
768
834
  def set_config(uri, config)
769
- if uri.nil?
770
- @config = config
771
- else
772
- uri = Util.uri_dirname(urify(uri))
773
- @auth[uri] = config
835
+ synchronize do
836
+ if uri.nil?
837
+ @config = config
838
+ else
839
+ uri = Util.uri_dirname(urify(uri))
840
+ @auth[uri] = config
841
+ end
774
842
  end
775
843
  end
776
844
 
777
845
  # Get authentication credential.
778
846
  def get_config(uri = nil)
779
- if uri.nil?
780
- @config
781
- else
782
- uri = urify(uri)
783
- Util.hash_find_value(@auth) { |cand_uri, cred|
784
- Util.uri_part_of(uri, cand_uri)
785
- }
786
- end
847
+ synchronize {
848
+ do_get_config(uri)
849
+ }
787
850
  end
788
851
 
789
852
  # Response handler: returns credential.
@@ -792,26 +855,47 @@ class HTTPClient
792
855
  # * child page of defined credential
793
856
  def get(req)
794
857
  target_uri = req.header.request_uri
795
- return nil unless @challengeable[nil] or @challengeable.find { |uri, ok|
796
- Util.uri_part_of(target_uri, uri) and ok
858
+ synchronize {
859
+ return nil unless @challenge[nil] or @challenge.find { |uri, ok|
860
+ Util.uri_part_of(target_uri, uri) and ok
861
+ }
862
+ config = do_get_config(target_uri) || @config
863
+ return nil unless config
864
+ calc_cred(req, config)
797
865
  }
798
- config = get_config(target_uri) || @config
799
- return nil unless config
800
- calc_cred(req, config)
801
866
  end
802
867
 
803
868
  # Challenge handler: remember URL for response.
869
+ #
870
+ # challenge() in OAuth handler always returns false to avoid connection
871
+ # retry which should not work in OAuth authentication context. This
872
+ # method just remember URL (nil means 'any') for the next connection.
873
+ # Normally OAuthClient handles this correctly but see how it uses when
874
+ # you need to use this class directly.
804
875
  def challenge(uri, param_str = nil)
876
+ synchronize {
877
+ if uri.nil?
878
+ @challenge[nil] = true
879
+ else
880
+ @challenge[urify(uri)] = true
881
+ end
882
+ false
883
+ }
884
+ end
885
+
886
+ private
887
+
888
+ def do_get_config(uri = nil)
805
889
  if uri.nil?
806
- @challengeable[nil] = true
890
+ @config
807
891
  else
808
- @challengeable[urify(uri)] = true
892
+ uri = urify(uri)
893
+ Util.hash_find_value(@auth) { |cand_uri, cred|
894
+ Util.uri_part_of(uri, cand_uri)
895
+ }
809
896
  end
810
- true
811
897
  end
812
898
 
813
- private
814
-
815
899
  def calc_cred(req, config)
816
900
  header = {}
817
901
  header['oauth_consumer_key'] = config.consumer_key