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 +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +2 -2
- data/Gemfile +0 -9
- data/Gemfile.lock +34 -258
- data/README.md +1 -0
- data/httpclient.gemspec +1 -2
- data/lib/httpclient/auth.rb +241 -157
- data/lib/httpclient/cacert.p7s +3865 -1911
- data/lib/httpclient/lru_cache.rb +27 -24
- data/lib/httpclient/ssl_config.rb +3 -2
- data/lib/httpclient/version.rb +2 -1
- data/spec/basic_spec.rb +82 -82
- data/spec/cookie_spec.rb +132 -132
- data/spec/hexdump_spec.rb +1 -1
- data/spec/http_message_spec.rb +37 -37
- data/spec/httpclient_spec.rb +267 -263
- data/spec/keepalive_spec.rb +5 -5
- data/spec/lru_spec.rb +5 -11
- data/test/test_auth.rb +29 -2
- metadata +2 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e431a2b363f87ec472a3c7d50656a1fcd1c054d7
|
4
|
+
data.tar.gz: 85a6326b3ba79941dd50b8636a99a423cd581328
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb3f3735bea1202b763ad5f32eaee8f40a16fdca132b4df1594095c06fc335ec45a7904f03a41b7342794ffde71d48e1440a051b1c2ded6f81e37f2caff9ec18
|
7
|
+
data.tar.gz: 7baf041485d74dc7aef7398f96690e43cf56a8e3fb211b41a50cd40ebb3a1e714d3ce9c42a1d621f77bfc2027420adbab2571f4733286f4a35326097320a30d8
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.1.
|
1
|
+
2.1.2
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,15 +1,18 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
glebtv-httpclient (3.2.
|
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 (
|
11
|
-
i18n (~> 0.6, >= 0.6.
|
12
|
-
|
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.
|
23
|
-
|
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.
|
28
|
-
|
29
|
-
|
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.
|
33
|
-
mime-types (>= 1.16)
|
34
|
-
|
35
|
-
|
36
|
-
rspec-
|
37
|
-
rspec-
|
38
|
-
|
39
|
-
rspec-
|
40
|
-
|
41
|
-
rspec-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
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
|
+
|
data/lib/httpclient/auth.rb
CHANGED
@@ -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
|
-
@
|
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
|
-
|
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
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
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
|
-
|
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
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
Util.
|
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
|
-
|
286
|
-
|
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
|
-
|
294
|
-
|
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
|
-
|
300
|
-
|
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
|
-
|
306
|
-
|
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
|
-
|
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
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
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
|
-
|
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
|
-
|
353
|
-
Util.
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
Util.
|
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
|
-
|
366
|
-
|
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
|
-
|
449
|
-
|
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
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
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
|
-
|
501
|
+
synchronize do
|
502
|
+
@challenge = nil
|
503
|
+
end
|
466
504
|
end
|
467
505
|
|
468
506
|
def challenge(uri, param_str)
|
469
|
-
|
470
|
-
|
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
|
-
|
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
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
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
|
-
|
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
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
Util.
|
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
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
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
|
-
|
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
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
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
|
-
|
635
|
-
|
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
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
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
|
-
@
|
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
|
-
|
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
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
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
|
-
|
780
|
-
|
781
|
-
|
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
|
-
|
796
|
-
|
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
|
-
@
|
890
|
+
@config
|
807
891
|
else
|
808
|
-
|
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
|