glebtv-httpclient 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/README.rdoc +108 -0
  3. data/bin/httpclient +65 -0
  4. data/lib/glebtv-httpclient.rb +1 -0
  5. data/lib/hexdump.rb +50 -0
  6. data/lib/http-access2/cookie.rb +1 -0
  7. data/lib/http-access2/http.rb +1 -0
  8. data/lib/http-access2.rb +55 -0
  9. data/lib/httpclient/auth.rb +899 -0
  10. data/lib/httpclient/cacert.p7s +1912 -0
  11. data/lib/httpclient/connection.rb +88 -0
  12. data/lib/httpclient/cookie.rb +438 -0
  13. data/lib/httpclient/http.rb +1050 -0
  14. data/lib/httpclient/include_client.rb +83 -0
  15. data/lib/httpclient/session.rb +1031 -0
  16. data/lib/httpclient/ssl_config.rb +403 -0
  17. data/lib/httpclient/timeout.rb +140 -0
  18. data/lib/httpclient/util.rb +186 -0
  19. data/lib/httpclient/version.rb +3 -0
  20. data/lib/httpclient.rb +1157 -0
  21. data/lib/oauthclient.rb +110 -0
  22. data/sample/async.rb +8 -0
  23. data/sample/auth.rb +11 -0
  24. data/sample/cookie.rb +18 -0
  25. data/sample/dav.rb +103 -0
  26. data/sample/howto.rb +49 -0
  27. data/sample/oauth_buzz.rb +57 -0
  28. data/sample/oauth_friendfeed.rb +59 -0
  29. data/sample/oauth_twitter.rb +61 -0
  30. data/sample/ssl/0cert.pem +22 -0
  31. data/sample/ssl/0key.pem +30 -0
  32. data/sample/ssl/1000cert.pem +19 -0
  33. data/sample/ssl/1000key.pem +18 -0
  34. data/sample/ssl/htdocs/index.html +10 -0
  35. data/sample/ssl/ssl_client.rb +22 -0
  36. data/sample/ssl/webrick_httpsd.rb +29 -0
  37. data/sample/stream.rb +21 -0
  38. data/sample/thread.rb +27 -0
  39. data/sample/wcat.rb +21 -0
  40. data/test/ca-chain.cert +44 -0
  41. data/test/ca.cert +23 -0
  42. data/test/client.cert +19 -0
  43. data/test/client.key +15 -0
  44. data/test/helper.rb +129 -0
  45. data/test/htdigest +1 -0
  46. data/test/htpasswd +2 -0
  47. data/test/runner.rb +2 -0
  48. data/test/server.cert +19 -0
  49. data/test/server.key +15 -0
  50. data/test/sslsvr.rb +65 -0
  51. data/test/subca.cert +21 -0
  52. data/test/test_auth.rb +321 -0
  53. data/test/test_cookie.rb +412 -0
  54. data/test/test_hexdump.rb +14 -0
  55. data/test/test_http-access2.rb +507 -0
  56. data/test/test_httpclient.rb +1801 -0
  57. data/test/test_include_client.rb +52 -0
  58. data/test/test_ssl.rb +235 -0
  59. metadata +102 -0
data/test/test_auth.rb ADDED
@@ -0,0 +1,321 @@
1
+ require File.expand_path('helper', File.dirname(__FILE__))
2
+ require 'digest/md5'
3
+
4
+ class TestAuth < Test::Unit::TestCase
5
+ include Helper
6
+
7
+ def setup
8
+ super
9
+ setup_server
10
+ end
11
+
12
+ def teardown
13
+ super
14
+ end
15
+
16
+ def setup_server
17
+ @server = WEBrick::HTTPServer.new(
18
+ :BindAddress => "localhost",
19
+ :Logger => @logger,
20
+ :Port => 0,
21
+ :AccessLog => [],
22
+ :DocumentRoot => File.dirname(File.expand_path(__FILE__))
23
+ )
24
+ @serverport = @server.config[:Port]
25
+ @server.mount(
26
+ '/basic_auth',
27
+ WEBrick::HTTPServlet::ProcHandler.new(method(:do_basic_auth).to_proc)
28
+ )
29
+ @server.mount(
30
+ '/digest_auth',
31
+ WEBrick::HTTPServlet::ProcHandler.new(method(:do_digest_auth).to_proc)
32
+ )
33
+ @server.mount(
34
+ '/digest_sess_auth',
35
+ WEBrick::HTTPServlet::ProcHandler.new(method(:do_digest_sess_auth).to_proc)
36
+ )
37
+ htpasswd = File.join(File.dirname(__FILE__), 'htpasswd')
38
+ htpasswd_userdb = WEBrick::HTTPAuth::Htpasswd.new(htpasswd)
39
+ htdigest = File.join(File.dirname(__FILE__), 'htdigest')
40
+ htdigest_userdb = WEBrick::HTTPAuth::Htdigest.new(htdigest)
41
+ @basic_auth = WEBrick::HTTPAuth::BasicAuth.new(
42
+ :Logger => @logger,
43
+ :Realm => 'auth',
44
+ :UserDB => htpasswd_userdb
45
+ )
46
+ @digest_auth = WEBrick::HTTPAuth::DigestAuth.new(
47
+ :Logger => @logger,
48
+ :Algorithm => 'MD5',
49
+ :Realm => 'auth',
50
+ :UserDB => htdigest_userdb
51
+ )
52
+ @digest_sess_auth = WEBrick::HTTPAuth::DigestAuth.new(
53
+ :Logger => @logger,
54
+ :Algorithm => 'MD5-sess',
55
+ :Realm => 'auth',
56
+ :UserDB => htdigest_userdb
57
+ )
58
+ @server_thread = start_server_thread(@server)
59
+
60
+ @proxy_digest_auth = WEBrick::HTTPAuth::ProxyDigestAuth.new(
61
+ :Logger => @proxylogger,
62
+ :Algorithm => 'MD5',
63
+ :Realm => 'auth',
64
+ :UserDB => htdigest_userdb
65
+ )
66
+
67
+ @proxyserver = WEBrick::HTTPProxyServer.new(
68
+ :ProxyAuthProc => @proxy_digest_auth.method(:authenticate).to_proc,
69
+ :BindAddress => "localhost",
70
+ :Logger => @proxylogger,
71
+ :Port => 0,
72
+ :AccessLog => []
73
+ )
74
+ @proxyport = @proxyserver.config[:Port]
75
+ @proxyserver_thread = start_server_thread(@proxyserver)
76
+ end
77
+
78
+ def do_basic_auth(req, res)
79
+ @basic_auth.authenticate(req, res)
80
+ res['content-type'] = 'text/plain'
81
+ res.body = 'basic_auth OK'
82
+ end
83
+
84
+ def do_digest_auth(req, res)
85
+ @digest_auth.authenticate(req, res)
86
+ res['content-type'] = 'text/plain'
87
+ res['x-query'] = req.body
88
+ res.body = 'digest_auth OK' + req.query_string.to_s
89
+ end
90
+
91
+ def do_digest_sess_auth(req, res)
92
+ @digest_sess_auth.authenticate(req, res)
93
+ res['content-type'] = 'text/plain'
94
+ res['x-query'] = req.body
95
+ res.body = 'digest_sess_auth OK' + req.query_string.to_s
96
+ end
97
+
98
+ def test_basic_auth
99
+ c = HTTPClient.new
100
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
101
+ assert_equal('basic_auth OK', c.get_content("http://localhost:#{serverport}/basic_auth"))
102
+ end
103
+
104
+ def test_basic_auth_compat
105
+ c = HTTPClient.new
106
+ c.set_basic_auth("http://localhost:#{serverport}/", 'admin', 'admin')
107
+ assert_equal('basic_auth OK', c.get_content("http://localhost:#{serverport}/basic_auth"))
108
+ end
109
+
110
+ def test_BASIC_auth
111
+ c = HTTPClient.new
112
+ webrick_backup = @basic_auth.instance_eval { @auth_scheme }
113
+ #httpaccess2_backup = c.www_auth.basic_auth.instance_eval { @scheme }
114
+ begin
115
+ @basic_auth.instance_eval { @auth_scheme = "BASIC" }
116
+ c.www_auth.basic_auth.instance_eval { @scheme = "BASIC" }
117
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
118
+ assert_equal('basic_auth OK', c.get_content("http://localhost:#{serverport}/basic_auth"))
119
+ ensure
120
+ @basic_auth.instance_eval { @auth_scheme = webrick_backup }
121
+ #c.www_auth.basic_auth.instance_eval { @scheme = httpaccess2_backup }
122
+ end
123
+ end
124
+
125
+ def test_basic_auth_reuses_credentials
126
+ c = HTTPClient.new
127
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
128
+ assert_equal('basic_auth OK', c.get_content("http://localhost:#{serverport}/basic_auth/"))
129
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
130
+ c.debug_dev = str = ''
131
+ c.get_content("http://localhost:#{serverport}/basic_auth/sub/dir/")
132
+ assert_match /Authorization: Basic YWRtaW46YWRtaW4=/, str
133
+ end
134
+
135
+ def test_digest_auth
136
+ c = HTTPClient.new
137
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
138
+ assert_equal('digest_auth OK', c.get_content("http://localhost:#{serverport}/digest_auth"))
139
+ end
140
+
141
+ def test_digest_auth_reuses_credentials
142
+ c = HTTPClient.new
143
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
144
+ assert_equal('digest_auth OK', c.get_content("http://localhost:#{serverport}/digest_auth/"))
145
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
146
+ c.debug_dev = str = ''
147
+ c.get_content("http://localhost:#{serverport}/digest_auth/sub/dir/")
148
+ assert_match /Authorization: Digest/, str
149
+ end
150
+
151
+ def test_digest_auth_with_block
152
+ c = HTTPClient.new
153
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
154
+ called = false
155
+ c.get_content("http://localhost:#{serverport}/digest_auth") do |str|
156
+ assert_equal('digest_auth OK', str)
157
+ called = true
158
+ end
159
+ assert(called)
160
+ #
161
+ called = false
162
+ c.get("http://localhost:#{serverport}/digest_auth") do |str|
163
+ assert_equal('digest_auth OK', str)
164
+ called = true
165
+ end
166
+ assert(called)
167
+ end
168
+
169
+ def test_digest_auth_with_post_io
170
+ c = HTTPClient.new
171
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
172
+ post_body = StringIO.new("1234567890")
173
+ assert_equal('1234567890', c.post("http://localhost:#{serverport}/digest_auth", post_body).header['x-query'][0])
174
+ #
175
+ post_body = StringIO.new("1234567890")
176
+ post_body.read(5)
177
+ assert_equal('67890', c.post("http://localhost:#{serverport}/digest_auth", post_body).header['x-query'][0])
178
+ end
179
+
180
+ def test_digest_auth_with_querystring
181
+ c = HTTPClient.new
182
+ c.debug_dev = STDERR if $DEBUG
183
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
184
+ assert_equal('digest_auth OKbar=baz', c.get_content("http://localhost:#{serverport}/digest_auth/foo?bar=baz"))
185
+ end
186
+
187
+ def test_perfer_digest
188
+ c = HTTPClient.new
189
+ c.set_auth('http://example.com/', 'admin', 'admin')
190
+ c.test_loopback_http_response << "HTTP/1.0 401 Unauthorized\nWWW-Authenticate: Basic realm=\"foo\"\nWWW-Authenticate: Digest realm=\"foo\", nonce=\"nonce\", stale=false\nContent-Length: 2\n\nNG"
191
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
192
+ c.debug_dev = str = ''
193
+ c.get_content('http://example.com/')
194
+ assert_match(/^Authorization: Digest/, str)
195
+ end
196
+
197
+ def test_digest_sess_auth
198
+ c = HTTPClient.new
199
+ c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
200
+ assert_equal('digest_sess_auth OK', c.get_content("http://localhost:#{serverport}/digest_sess_auth"))
201
+ end
202
+
203
+ def test_proxy_auth
204
+ c = HTTPClient.new
205
+ c.set_proxy_auth('admin', 'admin')
206
+ c.test_loopback_http_response << "HTTP/1.0 407 Unauthorized\nProxy-Authenticate: Basic realm=\"foo\"\nContent-Length: 2\n\nNG"
207
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
208
+ c.debug_dev = str = ''
209
+ c.get_content('http://example.com/')
210
+ assert_match(/Proxy-Authorization: Basic YWRtaW46YWRtaW4=/, str)
211
+ end
212
+
213
+ def test_proxy_auth_reuses_credentials
214
+ c = HTTPClient.new
215
+ c.set_proxy_auth('admin', 'admin')
216
+ c.test_loopback_http_response << "HTTP/1.0 407 Unauthorized\nProxy-Authenticate: Basic realm=\"foo\"\nContent-Length: 2\n\nNG"
217
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
218
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
219
+ c.get_content('http://www1.example.com/')
220
+ c.debug_dev = str = ''
221
+ c.get_content('http://www2.example.com/')
222
+ assert_match(/Proxy-Authorization: Basic YWRtaW46YWRtaW4=/, str)
223
+ end
224
+
225
+ def test_digest_proxy_auth_loop
226
+ c = HTTPClient.new
227
+ c.set_proxy_auth('admin', 'admin')
228
+ c.test_loopback_http_response << "HTTP/1.0 407 Unauthorized\nProxy-Authenticate: Digest realm=\"foo\", nonce=\"nonce\", stale=false\nContent-Length: 2\n\nNG"
229
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
230
+ md5 = Digest::MD5.new
231
+ ha1 = md5.hexdigest("admin:foo:admin")
232
+ ha2 = md5.hexdigest("GET:/")
233
+ response = md5.hexdigest("#{ha1}:nonce:#{ha2}")
234
+ c.debug_dev = str = ''
235
+ c.get_content('http://example.com/')
236
+ assert_match(/Proxy-Authorization: Digest/, str)
237
+ assert_match(%r"response=\"#{response}\"", str)
238
+ end
239
+
240
+ def test_digest_proxy_auth
241
+ c=HTTPClient.new("http://localhost:#{proxyport}/")
242
+ c.set_proxy_auth('admin', 'admin')
243
+ c.set_auth("http://127.0.0.1:#{serverport}/", 'admin', 'admin')
244
+ assert_equal('basic_auth OK', c.get_content("http://127.0.0.1:#{serverport}/basic_auth"))
245
+ end
246
+
247
+ def test_digest_proxy_invalid_auth
248
+ c=HTTPClient.new("http://localhost:#{proxyport}/")
249
+ c.set_proxy_auth('admin', 'wrong')
250
+ c.set_auth("http://127.0.0.1:#{serverport}/", 'admin', 'admin')
251
+ assert_raises(HTTPClient::BadResponseError) do
252
+ c.get_content("http://127.0.0.1:#{serverport}/basic_auth")
253
+ end
254
+ end
255
+
256
+ def test_prefer_digest_to_basic_proxy_auth
257
+ c = HTTPClient.new
258
+ c.set_proxy_auth('admin', 'admin')
259
+ c.test_loopback_http_response << "HTTP/1.0 407 Unauthorized\nProxy-Authenticate: Digest realm=\"foo\", nonce=\"nonce\", stale=false\nProxy-Authenticate: Basic realm=\"bar\"\nContent-Length: 2\n\nNG"
260
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
261
+ md5 = Digest::MD5.new
262
+ ha1 = md5.hexdigest("admin:foo:admin")
263
+ ha2 = md5.hexdigest("GET:/")
264
+ response = md5.hexdigest("#{ha1}:nonce:#{ha2}")
265
+ c.debug_dev = str = ''
266
+ c.get_content('http://example.com/')
267
+ assert_match(/Proxy-Authorization: Digest/, str)
268
+ assert_match(%r"response=\"#{response}\"", str)
269
+ end
270
+
271
+ def test_digest_proxy_auth_reuses_credentials
272
+ c = HTTPClient.new
273
+ c.set_proxy_auth('admin', 'admin')
274
+ c.test_loopback_http_response << "HTTP/1.0 407 Unauthorized\nProxy-Authenticate: Digest realm=\"foo\", nonce=\"nonce\", stale=false\nContent-Length: 2\n\nNG"
275
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
276
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
277
+ md5 = Digest::MD5.new
278
+ ha1 = md5.hexdigest("admin:foo:admin")
279
+ ha2 = md5.hexdigest("GET:/")
280
+ response = md5.hexdigest("#{ha1}:nonce:#{ha2}")
281
+ c.get_content('http://www1.example.com/')
282
+ c.debug_dev = str = ''
283
+ c.get_content('http://www2.example.com/')
284
+ assert_match(/Proxy-Authorization: Digest/, str)
285
+ assert_match(%r"response=\"#{response}\"", str)
286
+ end
287
+
288
+ def test_oauth
289
+ c = HTTPClient.new
290
+ config = HTTPClient::OAuth::Config.new(
291
+ :realm => 'http://photos.example.net/',
292
+ :consumer_key => 'dpf43f3p2l4k3l03',
293
+ :consumer_secret => 'kd94hf93k423kf44',
294
+ :token => 'nnch734d00sl2jdk',
295
+ :secret => 'pfkkdhi9sl3r4s00',
296
+ :version => '1.0',
297
+ :signature_method => 'HMAC-SHA1'
298
+ )
299
+ config.debug_timestamp = '1191242096'
300
+ config.debug_nonce = 'kllo9940pd9333jh'
301
+ c.www_auth.oauth.set_config('http://photos.example.net/', config)
302
+ c.www_auth.oauth.challenge('http://photos.example.net/')
303
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
304
+ c.debug_dev = str = ''
305
+ c.get_content('http://photos.example.net/photos', [[:file, 'vacation.jpg'], [:size, 'original']])
306
+ assert(str.index(%q(GET /photos?file=vacation.jpg&size=original)))
307
+ assert(str.index(%q(Authorization: OAuth realm="http://photos.example.net/", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_nonce="kllo9940pd9333jh", oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1191242096", oauth_token="nnch734d00sl2jdk", oauth_version="1.0")))
308
+ #
309
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
310
+ c.debug_dev = str = ''
311
+ c.get_content('http://photos.example.net/photos?file=vacation.jpg&size=original')
312
+ assert(str.index(%q(GET /photos?file=vacation.jpg&size=original)))
313
+ assert(str.index(%q(Authorization: OAuth realm="http://photos.example.net/", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_nonce="kllo9940pd9333jh", oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1191242096", oauth_token="nnch734d00sl2jdk", oauth_version="1.0")))
314
+ #
315
+ c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
316
+ c.debug_dev = str = ''
317
+ c.post_content('http://photos.example.net/photos', [[:file, 'vacation.jpg'], [:size, 'original']])
318
+ assert(str.index(%q(POST /photos)))
319
+ assert(str.index(%q(Authorization: OAuth realm="http://photos.example.net/", oauth_consumer_key="dpf43f3p2l4k3l03", oauth_nonce="kllo9940pd9333jh", oauth_signature="wPkvxykrw%2BBTdCcGqKr%2B3I%2BPsiM%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1191242096", oauth_token="nnch734d00sl2jdk", oauth_version="1.0")))
320
+ end
321
+ end