httpclient-jgraichen 2.3.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/README.txt +759 -0
  3. data/bin/httpclient +65 -0
  4. data/lib/hexdump.rb +50 -0
  5. data/lib/http-access2.rb +55 -0
  6. data/lib/http-access2/cookie.rb +1 -0
  7. data/lib/http-access2/http.rb +1 -0
  8. data/lib/httpclient.rb +1156 -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 +1046 -0
  14. data/lib/httpclient/include_client.rb +83 -0
  15. data/lib/httpclient/session.rb +1028 -0
  16. data/lib/httpclient/ssl_config.rb +405 -0
  17. data/lib/httpclient/timeout.rb +140 -0
  18. data/lib/httpclient/util.rb +178 -0
  19. data/lib/httpclient/version.rb +3 -0
  20. data/lib/oauthclient.rb +110 -0
  21. data/sample/async.rb +8 -0
  22. data/sample/auth.rb +11 -0
  23. data/sample/cookie.rb +18 -0
  24. data/sample/dav.rb +103 -0
  25. data/sample/howto.rb +49 -0
  26. data/sample/oauth_buzz.rb +57 -0
  27. data/sample/oauth_friendfeed.rb +59 -0
  28. data/sample/oauth_twitter.rb +61 -0
  29. data/sample/ssl/0cert.pem +22 -0
  30. data/sample/ssl/0key.pem +30 -0
  31. data/sample/ssl/1000cert.pem +19 -0
  32. data/sample/ssl/1000key.pem +18 -0
  33. data/sample/ssl/htdocs/index.html +10 -0
  34. data/sample/ssl/ssl_client.rb +22 -0
  35. data/sample/ssl/webrick_httpsd.rb +29 -0
  36. data/sample/stream.rb +21 -0
  37. data/sample/thread.rb +27 -0
  38. data/sample/wcat.rb +21 -0
  39. data/test/ca-chain.cert +44 -0
  40. data/test/ca.cert +23 -0
  41. data/test/client.cert +19 -0
  42. data/test/client.key +15 -0
  43. data/test/helper.rb +129 -0
  44. data/test/htdigest +1 -0
  45. data/test/htpasswd +2 -0
  46. data/test/runner.rb +2 -0
  47. data/test/server.cert +19 -0
  48. data/test/server.key +15 -0
  49. data/test/sslsvr.rb +65 -0
  50. data/test/subca.cert +21 -0
  51. data/test/test_auth.rb +348 -0
  52. data/test/test_cookie.rb +412 -0
  53. data/test/test_hexdump.rb +14 -0
  54. data/test/test_http-access2.rb +507 -0
  55. data/test/test_httpclient.rb +1783 -0
  56. data/test/test_include_client.rb +52 -0
  57. data/test/test_ssl.rb +235 -0
  58. metadata +100 -0
@@ -0,0 +1,1783 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('helper', File.dirname(__FILE__))
3
+
4
+
5
+ class TestHTTPClient < Test::Unit::TestCase
6
+ include Helper
7
+ include HTTPClient::Util
8
+
9
+ def setup
10
+ super
11
+ setup_server
12
+ setup_client
13
+ end
14
+
15
+ def teardown
16
+ super
17
+ end
18
+
19
+ def test_initialize
20
+ setup_proxyserver
21
+ escape_noproxy do
22
+ @proxyio.string = ""
23
+ @client = HTTPClient.new(proxyurl)
24
+ assert_equal(urify(proxyurl), @client.proxy)
25
+ assert_equal(200, @client.head(serverurl).status)
26
+ assert(/accept/ =~ @proxyio.string)
27
+ end
28
+ end
29
+
30
+ def test_agent_name
31
+ @client = HTTPClient.new(nil, "agent_name_foo")
32
+ str = ""
33
+ @client.debug_dev = str
34
+ @client.get(serverurl)
35
+ lines = str.split(/(?:\r?\n)+/)
36
+ assert_equal("= Request", lines[0])
37
+ assert_match(/^User-Agent: agent_name_foo \(#{HTTPClient::VERSION}/, lines[4])
38
+ end
39
+
40
+ def test_from
41
+ @client = HTTPClient.new(nil, nil, "from_bar")
42
+ str = ""
43
+ @client.debug_dev = str
44
+ @client.get(serverurl)
45
+ lines = str.split(/(?:\r?\n)+/)
46
+ assert_equal("= Request", lines[0])
47
+ assert_match(/^From: from_bar/, lines[5])
48
+ end
49
+
50
+ def test_debug_dev
51
+ str = ""
52
+ @client.debug_dev = str
53
+ assert_equal(str.object_id, @client.debug_dev.object_id)
54
+ assert(str.empty?)
55
+ @client.get(serverurl)
56
+ assert(!str.empty?)
57
+ end
58
+
59
+ def test_debug_dev_stream
60
+ str = ""
61
+ @client.debug_dev = str
62
+ conn = @client.get_async(serverurl)
63
+ Thread.pass while !conn.finished?
64
+ assert(!str.empty?)
65
+ end
66
+
67
+ def test_protocol_version_http09
68
+ @client.protocol_version = 'HTTP/0.9'
69
+ @client.debug_dev = str = ''
70
+ @client.test_loopback_http_response << "hello\nworld\n"
71
+ res = @client.get(serverurl + 'hello')
72
+ assert_equal('0.9', res.http_version)
73
+ assert_equal(nil, res.status)
74
+ assert_equal(nil, res.reason)
75
+ assert_equal("hello\nworld\n", res.content)
76
+ lines = str.split(/(?:\r?\n)+/)
77
+ assert_equal("= Request", lines[0])
78
+ assert_equal("! CONNECTION ESTABLISHED", lines[2])
79
+ assert_equal("GET /hello HTTP/0.9", lines[3])
80
+ assert_equal("Connection: close", lines[7])
81
+ assert_equal("= Response", lines[8])
82
+ assert_match(/^hello$/, lines[9])
83
+ assert_match(/^world$/, lines[10])
84
+ end
85
+
86
+ def test_protocol_version_http10
87
+ assert_equal(nil, @client.protocol_version)
88
+ @client.protocol_version = 'HTTP/1.0'
89
+ assert_equal('HTTP/1.0', @client.protocol_version)
90
+ str = ""
91
+ @client.debug_dev = str
92
+ @client.get(serverurl + 'hello')
93
+ lines = str.split(/(?:\r?\n)+/)
94
+ assert_equal("= Request", lines[0])
95
+ assert_equal("! CONNECTION ESTABLISHED", lines[2])
96
+ assert_equal("GET /hello HTTP/1.0", lines[3])
97
+ assert_equal("Connection: close", lines[7])
98
+ assert_equal("= Response", lines[8])
99
+ end
100
+
101
+ def test_header_accept_by_default
102
+ str = ""
103
+ @client.debug_dev = str
104
+ @client.get(serverurl)
105
+ lines = str.split(/(?:\r?\n)+/)
106
+ assert_equal("Accept: */*", lines[5])
107
+ end
108
+
109
+ def test_header_accept
110
+ str = ""
111
+ @client.debug_dev = str
112
+ @client.get(serverurl, :header => {:Accept => 'text/html'})
113
+ lines = str.split(/(?:\r?\n)+/)
114
+ assert_equal("Accept: text/html", lines[4])
115
+ end
116
+
117
+ def test_host_given
118
+ str = ""
119
+ @client.debug_dev = str
120
+ @client.get(serverurl)
121
+ lines = str.split(/(?:\r?\n)+/)
122
+ assert_equal("= Request", lines[0])
123
+ assert_equal("! CONNECTION ESTABLISHED", lines[2])
124
+ assert_equal("GET / HTTP/1.1", lines[3])
125
+ assert_equal("Host: localhost:#{serverport}", lines[7])
126
+ #
127
+ @client.reset_all
128
+ str = ""
129
+ @client.debug_dev = str
130
+ @client.get(serverurl, nil, {'Host' => 'foo'})
131
+ lines = str.split(/(?:\r?\n)+/)
132
+ assert_equal("= Request", lines[0])
133
+ assert_equal("! CONNECTION ESTABLISHED", lines[2])
134
+ assert_equal("GET / HTTP/1.1", lines[3])
135
+ assert_equal("Host: foo", lines[4]) # use given param
136
+ end
137
+
138
+ def test_redirect_returns_not_modified
139
+ assert_nothing_raised do
140
+ timeout(2) do
141
+ @client.get(serverurl + 'status', {:status => 306}, {:follow_redirect => true})
142
+ end
143
+ end
144
+ end
145
+
146
+ def test_protocol_version_http11
147
+ assert_equal(nil, @client.protocol_version)
148
+ str = ""
149
+ @client.debug_dev = str
150
+ @client.get(serverurl)
151
+ lines = str.split(/(?:\r?\n)+/)
152
+ assert_equal("= Request", lines[0])
153
+ assert_equal("! CONNECTION ESTABLISHED", lines[2])
154
+ assert_equal("GET / HTTP/1.1", lines[3])
155
+ assert_equal("Host: localhost:#{serverport}", lines[7])
156
+ @client.protocol_version = 'HTTP/1.1'
157
+ assert_equal('HTTP/1.1', @client.protocol_version)
158
+ str = ""
159
+ @client.debug_dev = str
160
+ @client.get(serverurl)
161
+ lines = str.split(/(?:\r?\n)+/)
162
+ assert_equal("= Request", lines[0])
163
+ assert_equal("! CONNECTION ESTABLISHED", lines[2])
164
+ assert_equal("GET / HTTP/1.1", lines[3])
165
+ @client.protocol_version = 'HTTP/1.0'
166
+ str = ""
167
+ @client.debug_dev = str
168
+ @client.get(serverurl)
169
+ lines = str.split(/(?:\r?\n)+/)
170
+ assert_equal("= Request", lines[0])
171
+ assert_equal("! CONNECTION ESTABLISHED", lines[2])
172
+ assert_equal("GET / HTTP/1.0", lines[3])
173
+ end
174
+
175
+ def test_proxy
176
+ setup_proxyserver
177
+ escape_noproxy do
178
+ begin
179
+ @client.proxy = "http://"
180
+ rescue
181
+ assert_match(/InvalidURIError/, $!.class.to_s)
182
+ end
183
+ @client.proxy = ""
184
+ assert_nil(@client.proxy)
185
+ @client.proxy = "http://admin:admin@foo:1234"
186
+ assert_equal(urify("http://admin:admin@foo:1234"), @client.proxy)
187
+ uri = urify("http://bar:2345")
188
+ @client.proxy = uri
189
+ assert_equal(uri, @client.proxy)
190
+ #
191
+ @proxyio.string = ""
192
+ @client.proxy = nil
193
+ assert_equal(200, @client.head(serverurl).status)
194
+ assert(/accept/ !~ @proxyio.string)
195
+ #
196
+ @proxyio.string = ""
197
+ @client.proxy = proxyurl
198
+ @client.debug_dev = str = ""
199
+ assert_equal(200, @client.head(serverurl).status)
200
+ assert(/accept/ =~ @proxyio.string)
201
+ assert(/Host: localhost:#{serverport}/ =~ str)
202
+ end
203
+ end
204
+
205
+ def test_host_header
206
+ @client.proxy = proxyurl
207
+ @client.debug_dev = str = ""
208
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n"
209
+ assert_equal(200, @client.head('http://www.example.com/foo').status)
210
+ # ensure no ':80' is added. some servers dislike that.
211
+ assert(/\r\nHost: www\.example\.com\r\n/ =~ str)
212
+ #
213
+ @client.debug_dev = str = ""
214
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n"
215
+ assert_equal(200, @client.head('http://www.example.com:12345/foo').status)
216
+ # ensure ':12345' exists.
217
+ assert(/\r\nHost: www\.example\.com:12345\r\n/ =~ str)
218
+ end
219
+
220
+ def test_proxy_env
221
+ setup_proxyserver
222
+ escape_env do
223
+ ENV['http_proxy'] = "http://admin:admin@foo:1234"
224
+ ENV['NO_PROXY'] = "foobar"
225
+ client = HTTPClient.new
226
+ assert_equal(urify("http://admin:admin@foo:1234"), client.proxy)
227
+ assert_equal('foobar', client.no_proxy)
228
+ end
229
+ end
230
+
231
+ def test_proxy_env_cgi
232
+ setup_proxyserver
233
+ escape_env do
234
+ ENV['REQUEST_METHOD'] = 'GET' # CGI environment emulation
235
+ ENV['http_proxy'] = "http://admin:admin@foo:1234"
236
+ ENV['no_proxy'] = "foobar"
237
+ client = HTTPClient.new
238
+ assert_equal(nil, client.proxy)
239
+ ENV['CGI_HTTP_PROXY'] = "http://admin:admin@foo:1234"
240
+ client = HTTPClient.new
241
+ assert_equal(urify("http://admin:admin@foo:1234"), client.proxy)
242
+ end
243
+ end
244
+
245
+ def test_empty_proxy_env
246
+ setup_proxyserver
247
+ escape_env do
248
+ ENV['http_proxy'] = ""
249
+ client = HTTPClient.new
250
+ assert_equal(nil, client.proxy)
251
+ end
252
+ end
253
+
254
+ def test_noproxy_for_localhost
255
+ @proxyio.string = ""
256
+ @client.proxy = proxyurl
257
+ assert_equal(200, @client.head(serverurl).status)
258
+ assert(/accept/ !~ @proxyio.string)
259
+ end
260
+
261
+ def test_no_proxy
262
+ setup_proxyserver
263
+ escape_noproxy do
264
+ # proxy is not set.
265
+ assert_equal(nil, @client.no_proxy)
266
+ @client.no_proxy = 'localhost'
267
+ assert_equal('localhost', @client.no_proxy)
268
+ @proxyio.string = ""
269
+ @client.proxy = nil
270
+ assert_equal(200, @client.head(serverurl).status)
271
+ assert(/accept/ !~ @proxyio.string)
272
+ #
273
+ @proxyio.string = ""
274
+ @client.proxy = proxyurl
275
+ assert_equal(200, @client.head(serverurl).status)
276
+ assert(/accept/ !~ @proxyio.string)
277
+ #
278
+ @client.no_proxy = 'foobar'
279
+ @proxyio.string = ""
280
+ @client.proxy = proxyurl
281
+ assert_equal(200, @client.head(serverurl).status)
282
+ assert(/accept/ =~ @proxyio.string)
283
+ #
284
+ @client.no_proxy = 'foobar,localhost:baz'
285
+ @proxyio.string = ""
286
+ @client.proxy = proxyurl
287
+ assert_equal(200, @client.head(serverurl).status)
288
+ assert(/accept/ !~ @proxyio.string)
289
+ #
290
+ @client.no_proxy = 'foobar,localhost:443'
291
+ @proxyio.string = ""
292
+ @client.proxy = proxyurl
293
+ assert_equal(200, @client.head(serverurl).status)
294
+ assert(/accept/ =~ @proxyio.string)
295
+ #
296
+ @client.no_proxy = "foobar,localhost:443:localhost:#{serverport},baz"
297
+ @proxyio.string = ""
298
+ @client.proxy = proxyurl
299
+ assert_equal(200, @client.head(serverurl).status)
300
+ assert(/accept/ !~ @proxyio.string)
301
+ end
302
+ end
303
+
304
+ def test_no_proxy_with_initial_dot
305
+ @client.debug_dev = str = ""
306
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n"
307
+ @client.no_proxy = ''
308
+ @client.proxy = proxyurl
309
+ @client.head('http://www.foo.com')
310
+ assert(/CONNECT TO localhost/ =~ str, 'via proxy')
311
+ #
312
+ @client.debug_dev = str = ""
313
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n"
314
+ @client.no_proxy = '.foo.com'
315
+ @client.proxy = proxyurl
316
+ @client.head('http://www.foo.com')
317
+ assert(/CONNECT TO www.foo.com/ =~ str, 'no proxy because .foo.com matches with www.foo.com')
318
+ #
319
+ @client.debug_dev = str = ""
320
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n"
321
+ @client.no_proxy = '.foo.com'
322
+ @client.proxy = proxyurl
323
+ @client.head('http://foo.com')
324
+ assert(/CONNECT TO localhost/ =~ str, 'via proxy because .foo.com does not matche with foo.com')
325
+ #
326
+ @client.debug_dev = str = ""
327
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n"
328
+ @client.no_proxy = 'foo.com'
329
+ @client.proxy = proxyurl
330
+ @client.head('http://foo.com')
331
+ assert(/CONNECT TO foo.com/ =~ str, 'no proxy because foo.com matches with foo.com')
332
+ end
333
+
334
+ def test_cookie_update_while_authentication
335
+ escape_noproxy do
336
+ @client.test_loopback_http_response << <<EOS
337
+ HTTP/1.0 401\r
338
+ Date: Fri, 19 Dec 2008 11:57:29 GMT\r
339
+ Content-Type: text/plain\r
340
+ Content-Length: 0\r
341
+ WWW-Authenticate: Basic realm="hello"\r
342
+ Set-Cookie: foo=bar; path=/; domain=.example.org; expires=#{Time.at(1924873200).httpdate}\r
343
+ \r
344
+ EOS
345
+ @client.test_loopback_http_response << <<EOS
346
+ HTTP/1.1 200 OK\r
347
+ Content-Length: 5\r
348
+ Connection: close\r
349
+ \r
350
+ hello
351
+ EOS
352
+ @client.debug_dev = str = ''
353
+ @client.set_auth("http://www.example.org/baz/", 'admin', 'admin')
354
+ assert_equal('hello', @client.get('http://www.example.org/baz/foo').content)
355
+ assert_match(/^Cookie: foo=bar/, str)
356
+ assert_match(/^Authorization: Basic YWRtaW46YWRtaW4=/, str)
357
+ end
358
+ end
359
+
360
+
361
+ def test_proxy_ssl
362
+ escape_noproxy do
363
+ @client.proxy = 'http://admin:admin@localhost:8080/'
364
+ # disconnected at initial 'CONNECT' so there're 2 loopback responses
365
+ @client.test_loopback_http_response << <<EOS
366
+ HTTP/1.0 407 Proxy Authentication Required\r
367
+ Date: Fri, 19 Dec 2008 11:57:29 GMT\r
368
+ Content-Type: text/plain\r
369
+ Content-Length: 0\r
370
+ Proxy-Authenticate: Basic realm="hello"\r
371
+ Proxy-Connection: close\r
372
+ \r
373
+ EOS
374
+ @client.test_loopback_http_response << <<EOS
375
+ HTTP/1.0 200 Connection established\r
376
+ \r
377
+ HTTP/1.1 200 OK\r
378
+ Content-Length: 5\r
379
+ Connection: close\r
380
+ \r
381
+ hello
382
+ EOS
383
+ assert_equal('hello', @client.get('https://localhost:17171/baz').content)
384
+ end
385
+ end
386
+
387
+ def test_loopback_response
388
+ @client.test_loopback_response << 'message body 1'
389
+ @client.test_loopback_response << 'message body 2'
390
+ assert_equal('message body 1', @client.get_content('http://somewhere'))
391
+ assert_equal('message body 2', @client.get_content('http://somewhere'))
392
+ #
393
+ @client.debug_dev = str = ''
394
+ @client.test_loopback_response << 'message body 3'
395
+ assert_equal('message body 3', @client.get_content('http://somewhere'))
396
+ assert_match(/message body 3/, str)
397
+ end
398
+
399
+ def test_loopback_response_stream
400
+ @client.test_loopback_response << 'message body 1'
401
+ @client.test_loopback_response << 'message body 2'
402
+ conn = @client.get_async('http://somewhere')
403
+ Thread.pass while !conn.finished?
404
+ assert_equal('message body 1', conn.pop.content.read)
405
+ conn = @client.get_async('http://somewhere')
406
+ Thread.pass while !conn.finished?
407
+ assert_equal('message body 2', conn.pop.content.read)
408
+ end
409
+
410
+ def test_loopback_http_response
411
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\ncontent-length: 100\n\nmessage body 1"
412
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\ncontent-length: 100\n\nmessage body 2"
413
+ assert_equal('message body 1', @client.get_content('http://somewhere'))
414
+ assert_equal('message body 2', @client.get_content('http://somewhere'))
415
+ end
416
+
417
+ def test_multiline_header
418
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\nX-Foo: XXX\n YYY\nX-Bar: \n XXX\n\tYYY\ncontent-length: 100\n\nmessage body 1"
419
+ res = @client.get('http://somewhere')
420
+ assert_equal('message body 1', res.content)
421
+ assert_equal(['XXX YYY'], res.header['x-foo'])
422
+ assert_equal(['XXX YYY'], res.header['x-bar'])
423
+ end
424
+
425
+ def test_broken_header
426
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\nXXXXX\ncontent-length: 100\n\nmessage body 1"
427
+ res = @client.get('http://somewhere')
428
+ assert_equal('message body 1', res.content)
429
+ end
430
+
431
+ def test_request_uri_in_response
432
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\ncontent-length: 100\n\nmessage body"
433
+ assert_equal(urify('http://google.com/'), @client.get('http://google.com/').header.request_uri)
434
+ end
435
+
436
+ def test_request_uri_in_response_when_redirect
437
+ expected = urify(serverurl + 'hello')
438
+ assert_equal(expected, @client.get(serverurl + 'redirect1', :follow_redirect => true).header.request_uri)
439
+ assert_equal(expected, @client.get(serverurl + 'redirect2', :follow_redirect => true).header.request_uri)
440
+ end
441
+
442
+ def test_redirect_non_https
443
+ url = serverurl + 'redirect1'
444
+ https_url = urify(url)
445
+ https_url.scheme = 'https'
446
+ #
447
+ redirect_to_http = "HTTP/1.0 302 OK\nLocation: #{url}\n\n"
448
+ redirect_to_https = "HTTP/1.0 302 OK\nLocation: #{https_url}\n\n"
449
+ #
450
+ # https -> http is denied
451
+ @client.test_loopback_http_response << redirect_to_http
452
+ assert_raises(HTTPClient::BadResponseError) do
453
+ @client.get_content(https_url)
454
+ end
455
+ #
456
+ # http -> http is OK
457
+ @client.reset_all
458
+ @client.test_loopback_http_response << redirect_to_http
459
+ assert_equal('hello', @client.get_content(url))
460
+ #
461
+ # http -> https is OK
462
+ @client.reset_all
463
+ @client.test_loopback_http_response << redirect_to_https
464
+ assert_raises(OpenSSL::SSL::SSLError) do
465
+ # trying to normal endpoint with SSL -> SSL negotiation failure
466
+ @client.get_content(url)
467
+ end
468
+ #
469
+ # https -> https is OK
470
+ @client.reset_all
471
+ @client.test_loopback_http_response << redirect_to_https
472
+ assert_raises(OpenSSL::SSL::SSLError) do
473
+ # trying to normal endpoint with SSL -> SSL negotiation failure
474
+ @client.get_content(https_url)
475
+ end
476
+ #
477
+ # https -> http with strict_redirect_uri_callback
478
+ @client.redirect_uri_callback = @client.method(:strict_redirect_uri_callback)
479
+ @client.test_loopback_http_response << redirect_to_http
480
+ assert_raises(HTTPClient::BadResponseError) do
481
+ @client.get_content(https_url)
482
+ end
483
+ end
484
+
485
+ def test_redirect_see_other
486
+ assert_equal('hello', @client.post_content(serverurl + 'redirect_see_other'))
487
+ end
488
+
489
+ def test_redirect_relative
490
+ @client.test_loopback_http_response << "HTTP/1.0 302 OK\nLocation: hello\n\n"
491
+ silent do
492
+ assert_equal('hello', @client.get_content(serverurl + 'redirect1'))
493
+ end
494
+ #
495
+ @client.reset_all
496
+ @client.redirect_uri_callback = @client.method(:strict_redirect_uri_callback)
497
+ assert_equal('hello', @client.get_content(serverurl + 'redirect1'))
498
+ @client.reset_all
499
+ @client.test_loopback_http_response << "HTTP/1.0 302 OK\nLocation: hello\n\n"
500
+ begin
501
+ @client.get_content(serverurl + 'redirect1')
502
+ assert(false)
503
+ rescue HTTPClient::BadResponseError => e
504
+ assert_equal(302, e.res.status)
505
+ end
506
+ end
507
+
508
+ def test_redirect_https_relative
509
+ url = serverurl + 'redirect1'
510
+ https_url = urify(url)
511
+ https_url.scheme = 'https'
512
+ @client.test_loopback_http_response << "HTTP/1.0 302 OK\nLocation: /foo\n\n"
513
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\n\nhello"
514
+ silent do
515
+ assert_equal('hello', @client.get_content(https_url))
516
+ end
517
+ end
518
+
519
+ def test_no_content
520
+ assert_nothing_raised do
521
+ timeout(2) do
522
+ @client.get(serverurl + 'status', :status => 101)
523
+ @client.get(serverurl + 'status', :status => 204)
524
+ @client.get(serverurl + 'status', :status => 304)
525
+ end
526
+ end
527
+ end
528
+
529
+ def test_get_content
530
+ assert_equal('hello', @client.get_content(serverurl + 'hello'))
531
+ assert_equal('hello', @client.get_content(serverurl + 'redirect1'))
532
+ assert_equal('hello', @client.get_content(serverurl + 'redirect2'))
533
+ url = serverurl.sub(/localhost/, '127.0.0.1')
534
+ assert_equal('hello', @client.get_content(url + 'hello'))
535
+ assert_equal('hello', @client.get_content(url + 'redirect1'))
536
+ assert_equal('hello', @client.get_content(url + 'redirect2'))
537
+ @client.reset(serverurl)
538
+ @client.reset(url)
539
+ @client.reset(serverurl)
540
+ @client.reset(url)
541
+ assert_raises(HTTPClient::BadResponseError) do
542
+ @client.get_content(serverurl + 'notfound')
543
+ end
544
+ assert_raises(HTTPClient::BadResponseError) do
545
+ @client.get_content(serverurl + 'redirect_self')
546
+ end
547
+ called = false
548
+ @client.redirect_uri_callback = lambda { |uri, res|
549
+ newuri = res.header['location'][0]
550
+ called = true
551
+ newuri
552
+ }
553
+ assert_equal('hello', @client.get_content(serverurl + 'relative_redirect'))
554
+ assert(called)
555
+ end
556
+
557
+ GZIP_CONTENT = "\x1f\x8b\x08\x00\x1a\x96\xe0\x4c\x00\x03\xcb\x48\xcd\xc9\xc9\x07\x00\x86\xa6\x10\x36\x05\x00\x00\x00"
558
+ DEFLATE_CONTENT = "\x78\x9c\xcb\x48\xcd\xc9\xc9\x07\x00\x06\x2c\x02\x15"
559
+ GZIP_CONTENT.force_encoding('BINARY') if GZIP_CONTENT.respond_to?(:force_encoding)
560
+ DEFLATE_CONTENT.force_encoding('BINARY') if DEFLATE_CONTENT.respond_to?(:force_encoding)
561
+ def test_get_gzipped_content
562
+ @client.transparent_gzip_decompression = false
563
+ content = @client.get_content(serverurl + 'compressed?enc=gzip')
564
+ assert_not_equal('hello', content)
565
+ assert_equal(GZIP_CONTENT, content)
566
+ @client.transparent_gzip_decompression = true
567
+ assert_equal('hello', @client.get_content(serverurl + 'compressed?enc=gzip'))
568
+ assert_equal('hello', @client.get_content(serverurl + 'compressed?enc=deflate'))
569
+ @client.transparent_gzip_decompression = false
570
+ end
571
+
572
+ def test_get_content_with_block
573
+ @client.get_content(serverurl + 'hello') do |str|
574
+ assert_equal('hello', str)
575
+ end
576
+ @client.get_content(serverurl + 'redirect1') do |str|
577
+ assert_equal('hello', str)
578
+ end
579
+ @client.get_content(serverurl + 'redirect2') do |str|
580
+ assert_equal('hello', str)
581
+ end
582
+ end
583
+
584
+ def test_post_content
585
+ assert_equal('hello', @client.post_content(serverurl + 'hello'))
586
+ assert_equal('hello', @client.post_content(serverurl + 'redirect1'))
587
+ assert_equal('hello', @client.post_content(serverurl + 'redirect2'))
588
+ assert_raises(HTTPClient::BadResponseError) do
589
+ @client.post_content(serverurl + 'notfound')
590
+ end
591
+ assert_raises(HTTPClient::BadResponseError) do
592
+ @client.post_content(serverurl + 'redirect_self')
593
+ end
594
+ called = false
595
+ @client.redirect_uri_callback = lambda { |uri, res|
596
+ newuri = res.header['location'][0]
597
+ called = true
598
+ newuri
599
+ }
600
+ assert_equal('hello', @client.post_content(serverurl + 'relative_redirect'))
601
+ assert(called)
602
+ end
603
+
604
+ def test_post_content_io
605
+ post_body = StringIO.new("1234567890")
606
+ assert_equal('post,1234567890', @client.post_content(serverurl + 'servlet', post_body))
607
+ post_body = StringIO.new("1234567890")
608
+ assert_equal('post,1234567890', @client.post_content(serverurl + 'servlet_redirect', post_body))
609
+ #
610
+ post_body = StringIO.new("1234567890")
611
+ post_body.read(5)
612
+ assert_equal('post,67890', @client.post_content(serverurl + 'servlet_redirect', post_body))
613
+ end
614
+
615
+ def test_head
616
+ assert_equal("head", @client.head(serverurl + 'servlet').header["x-head"][0])
617
+ param = {'1'=>'2', '3'=>'4'}
618
+ res = @client.head(serverurl + 'servlet', param)
619
+ assert_equal(param, params(res.header["x-query"][0]))
620
+ end
621
+
622
+ def test_head_async
623
+ param = {'1'=>'2', '3'=>'4'}
624
+ conn = @client.head_async(serverurl + 'servlet', param)
625
+ Thread.pass while !conn.finished?
626
+ res = conn.pop
627
+ assert_equal(param, params(res.header["x-query"][0]))
628
+ end
629
+
630
+ def test_get
631
+ assert_equal("get", @client.get(serverurl + 'servlet').content)
632
+ param = {'1'=>'2', '3'=>'4'}
633
+ res = @client.get(serverurl + 'servlet', param)
634
+ assert_equal(param, params(res.header["x-query"][0]))
635
+ assert_nil(res.contenttype)
636
+ #
637
+ url = serverurl.to_s + 'servlet?5=6&7=8'
638
+ res = @client.get(url, param)
639
+ assert_equal(param.merge("5"=>"6", "7"=>"8"), params(res.header["x-query"][0]))
640
+ assert_nil(res.contenttype)
641
+ end
642
+
643
+ def test_head_follow_redirect
644
+ expected = urify(serverurl + 'hello')
645
+ assert_equal(expected, @client.head(serverurl + 'hello', :follow_redirect => true).header.request_uri)
646
+ assert_equal(expected, @client.head(serverurl + 'redirect1', :follow_redirect => true).header.request_uri)
647
+ assert_equal(expected, @client.head(serverurl + 'redirect2', :follow_redirect => true).header.request_uri)
648
+ end
649
+
650
+ def test_get_follow_redirect
651
+ assert_equal('hello', @client.get(serverurl + 'hello', :follow_redirect => true).body)
652
+ assert_equal('hello', @client.get(serverurl + 'redirect1', :follow_redirect => true).body)
653
+ assert_equal('hello', @client.get(serverurl + 'redirect2', :follow_redirect => true).body)
654
+ end
655
+
656
+ def test_get_async
657
+ param = {'1'=>'2', '3'=>'4'}
658
+ conn = @client.get_async(serverurl + 'servlet', param)
659
+ Thread.pass while !conn.finished?
660
+ res = conn.pop
661
+ assert_equal(param, params(res.header["x-query"][0]))
662
+ end
663
+
664
+ def test_get_async_for_largebody
665
+ conn = @client.get_async(serverurl + 'largebody')
666
+ res = conn.pop
667
+ assert_equal(1000*1000, res.content.read.length)
668
+ end
669
+
670
+ def test_get_with_block
671
+ called = false
672
+ res = @client.get(serverurl + 'servlet') { |str|
673
+ assert_equal('get', str)
674
+ called = true
675
+ }
676
+ assert(called)
677
+ # res does not have a content
678
+ assert_nil(res.content)
679
+ end
680
+
681
+ def test_get_with_block_chunk_string_recycle
682
+ @client.read_block_size = 2
683
+ body = []
684
+ res = @client.get(serverurl + 'servlet') { |str|
685
+ body << str
686
+ }
687
+ assert_equal(2, body.size)
688
+ assert_equal("get", body.join) # Was "tt" by String object recycle...
689
+ end
690
+
691
+ def test_post
692
+ assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4])
693
+ param = {'1'=>'2', '3'=>'4'}
694
+ res = @client.post(serverurl + 'servlet', param)
695
+ assert_equal(param, params(res.header["x-query"][0]))
696
+ end
697
+
698
+ def test_post_follow_redirect
699
+ assert_equal('hello', @client.post(serverurl + 'hello', :follow_redirect => true).body)
700
+ assert_equal('hello', @client.post(serverurl + 'redirect1', :follow_redirect => true).body)
701
+ assert_equal('hello', @client.post(serverurl + 'redirect2', :follow_redirect => true).body)
702
+ end
703
+
704
+ def test_post_with_content_type
705
+ param = [['1', '2'], ['3', '4']]
706
+ ext = {'content-type' => 'application/x-www-form-urlencoded', 'hello' => 'world'}
707
+ assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext)
708
+ res = @client.post(serverurl + 'servlet', param, ext)
709
+ assert_equal(Hash[param], params(res.header["x-query"][0]))
710
+ #
711
+ ext = [['content-type', 'multipart/form-data'], ['hello', 'world']]
712
+ assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext)
713
+ res = @client.post(serverurl + 'servlet', param, ext)
714
+ assert_match(/Content-Disposition: form-data; name="1"/, res.content)
715
+ assert_match(/Content-Disposition: form-data; name="3"/, res.content)
716
+ #
717
+ ext = {'content-type' => 'multipart/form-data; boundary=hello'}
718
+ assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext)
719
+ res = @client.post(serverurl + 'servlet', param, ext)
720
+ assert_match(/Content-Disposition: form-data; name="1"/, res.content)
721
+ assert_match(/Content-Disposition: form-data; name="3"/, res.content)
722
+ assert_equal("post,--hello\r\nContent-Disposition: form-data; name=\"1\"\r\n\r\n2\r\n--hello\r\nContent-Disposition: form-data; name=\"3\"\r\n\r\n4\r\n--hello--\r\n\r\n", res.content)
723
+ end
724
+
725
+ def test_post_with_custom_multipart_and_boolean_params
726
+ param = [['boolean_true', true]]
727
+ ext = { 'content-type' => 'multipart/form-data' }
728
+ assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext)
729
+ res = @client.post(serverurl + 'servlet', param, ext)
730
+ assert_match(/Content-Disposition: form-data; name="boolean_true"\r\n\r\ntrue\r\n/, res.content)
731
+ #
732
+ param = [['boolean_false', false]]
733
+ res = @client.post(serverurl + 'servlet', param, ext)
734
+ assert_match(/Content-Disposition: form-data; name="boolean_false"\r\n\r\nfalse\r\n/, res.content)
735
+ #
736
+ param = [['nil', nil]]
737
+ res = @client.post(serverurl + 'servlet', param, ext)
738
+ assert_match(/Content-Disposition: form-data; name="nil"\r\n\r\n\r\n/, res.content)
739
+ end
740
+
741
+ def test_post_with_file
742
+ STDOUT.sync = true
743
+ File.open(__FILE__) do |file|
744
+ res = @client.post(serverurl + 'servlet', {1=>2, 3=>file})
745
+ assert_match(/^Content-Disposition: form-data; name="1"\r\n/nm, res.content)
746
+ assert_match(/^Content-Disposition: form-data; name="3";/, res.content)
747
+ assert_match(/FIND_TAG_IN_THIS_FILE/, res.content)
748
+ end
749
+ end
750
+
751
+ def test_post_with_file_without_size
752
+ STDOUT.sync = true
753
+ File.open(__FILE__) do |file|
754
+ def file.size
755
+ # Simulates some strange Windows behaviour
756
+ raise SystemCallError.new "Unknown Error (20047)"
757
+ end
758
+ assert_nothing_raised do
759
+ @client.post(serverurl + 'servlet', {1=>2, 3=>file})
760
+ end
761
+ end
762
+ end
763
+
764
+ def test_post_with_io # streaming, but not chunked
765
+ myio = StringIO.new("X" * (HTTP::Message::Body::DEFAULT_CHUNK_SIZE + 1))
766
+ def myio.read(*args)
767
+ @called ||= 0
768
+ @called += 1
769
+ super
770
+ end
771
+ def myio.called
772
+ @called
773
+ end
774
+ @client.debug_dev = str = StringIO.new
775
+ res = @client.post(serverurl + 'servlet', {1=>2, 3=>myio})
776
+ assert_match(/\r\nContent-Disposition: form-data; name="1"\r\n/m, res.content)
777
+ assert_match(/\r\n2\r\n/m, res.content)
778
+ assert_match(/\r\nContent-Disposition: form-data; name="3"; filename=""\r\n/m, res.content)
779
+ assert_match(/\r\nContent-Length:/m, str.string)
780
+ assert_equal(3, myio.called)
781
+ end
782
+
783
+ def test_post_with_io_nosize # streaming + chunked post
784
+ myio = StringIO.new("4")
785
+ def myio.size
786
+ nil
787
+ end
788
+ @client.debug_dev = str = StringIO.new
789
+ res = @client.post(serverurl + 'servlet', {1=>2, 3=>myio})
790
+ assert_match(/\r\nContent-Disposition: form-data; name="1"\r\n/m, res.content)
791
+ assert_match(/\r\n2\r\n/m, res.content)
792
+ assert_match(/\r\nContent-Disposition: form-data; name="3"; filename=""\r\n/m, res.content)
793
+ assert_match(/\r\n4\r\n/m, res.content)
794
+ assert_match(/\r\nTransfer-Encoding: chunked\r\n/m, str.string)
795
+ end
796
+
797
+ def test_post_async
798
+ param = {'1'=>'2', '3'=>'4'}
799
+ conn = @client.post_async(serverurl + 'servlet', param)
800
+ Thread.pass while !conn.finished?
801
+ res = conn.pop
802
+ assert_equal(param, params(res.header["x-query"][0]))
803
+ end
804
+
805
+ def test_post_with_block
806
+ called = false
807
+ res = @client.post(serverurl + 'servlet') { |str|
808
+ assert_equal('post,', str)
809
+ called = true
810
+ }
811
+ assert(called)
812
+ assert_nil(res.content)
813
+ #
814
+ called = false
815
+ param = [['1', '2'], ['3', '4']]
816
+ res = @client.post(serverurl + 'servlet', param) { |str|
817
+ assert_equal('post,1=2&3=4', str)
818
+ called = true
819
+ }
820
+ assert(called)
821
+ assert_equal('1=2&3=4', res.header["x-query"][0])
822
+ assert_nil(res.content)
823
+ end
824
+
825
+ def test_post_with_custom_multipart
826
+ ext = {'content-type' => 'multipart/form-data'}
827
+ assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext)
828
+ body = [{ 'Content-Disposition' => 'form-data; name="1"', :content => "2"},
829
+ { 'Content-Disposition' => 'form-data; name="3"', :content => "4"}]
830
+ res = @client.post(serverurl + 'servlet', body, ext)
831
+ assert_match(/Content-Disposition: form-data; name="1"/, res.content)
832
+ assert_match(/Content-Disposition: form-data; name="3"/, res.content)
833
+ #
834
+ ext = {'content-type' => 'multipart/form-data; boundary=hello'}
835
+ assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext)
836
+ res = @client.post(serverurl + 'servlet', body, ext)
837
+ assert_match(/Content-Disposition: form-data; name="1"/, res.content)
838
+ assert_match(/Content-Disposition: form-data; name="3"/, res.content)
839
+ assert_equal("post,--hello\r\nContent-Disposition: form-data; name=\"1\"\r\n\r\n2\r\n--hello\r\nContent-Disposition: form-data; name=\"3\"\r\n\r\n4\r\n--hello--\r\n\r\n", res.content)
840
+ end
841
+
842
+ def test_post_with_custom_multipart_and_file
843
+ STDOUT.sync = true
844
+ File.open(__FILE__) do |file|
845
+ ext = { 'Content-Type' => 'multipart/alternative' }
846
+ body = [{ 'Content-Type' => 'text/plain', :content => "this is only a test" },
847
+ { 'Content-Type' => 'application/x-ruby', :content => file }]
848
+ res = @client.post(serverurl + 'servlet', body, ext)
849
+ assert_match(/^Content-Type: text\/plain\r\n/m, res.content)
850
+ assert_match(/^this is only a test\r\n/m, res.content)
851
+ assert_match(/^Content-Type: application\/x-ruby\r\n/m, res.content)
852
+ assert_match(/FIND_TAG_IN_THIS_FILE/, res.content)
853
+ end
854
+ end
855
+
856
+ def test_put
857
+ assert_equal("put", @client.put(serverurl + 'servlet').content)
858
+ param = {'1'=>'2', '3'=>'4'}
859
+ @client.debug_dev = str = ''
860
+ res = @client.put(serverurl + 'servlet', param)
861
+ assert_equal(param, params(res.header["x-query"][0]))
862
+ assert_equal('Content-Type: application/x-www-form-urlencoded', str.split(/\r?\n/)[5])
863
+ end
864
+
865
+ def test_put_bytesize
866
+ res = @client.put(serverurl + 'servlet', 'txt' => 'あいうえお')
867
+ assert_equal('txt=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A', res.header["x-query"][0])
868
+ assert_equal('15', res.header["x-size"][0])
869
+ end
870
+
871
+ def test_put_async
872
+ param = {'1'=>'2', '3'=>'4'}
873
+ conn = @client.put_async(serverurl + 'servlet', param)
874
+ Thread.pass while !conn.finished?
875
+ res = conn.pop
876
+ assert_equal(param, params(res.header["x-query"][0]))
877
+ end
878
+
879
+ def test_delete
880
+ assert_equal("delete", @client.delete(serverurl + 'servlet').content)
881
+ end
882
+
883
+ # Not prohibited by spec, but normally it's ignored
884
+ def test_delete_with_body
885
+ param = {'1'=>'2', '3'=>'4'}
886
+ @client.debug_dev = str = ''
887
+ assert_equal("delete", @client.delete(serverurl + 'servlet', param).content)
888
+ assert_equal({'1' => ['2'], '3' => ['4']}, HTTP::Message.parse(str.split(/\r?\n\r?\n/)[2]))
889
+ end
890
+
891
+ def test_delete_async
892
+ conn = @client.delete_async(serverurl + 'servlet')
893
+ Thread.pass while !conn.finished?
894
+ res = conn.pop
895
+ assert_equal('delete', res.content.read)
896
+ end
897
+
898
+ def test_options
899
+ assert_equal("options", @client.options(serverurl + 'servlet').content)
900
+ end
901
+
902
+ def test_options_async
903
+ conn = @client.options_async(serverurl + 'servlet')
904
+ Thread.pass while !conn.finished?
905
+ res = conn.pop
906
+ assert_equal('options', res.content.read)
907
+ end
908
+
909
+ def test_propfind
910
+ assert_equal("propfind", @client.propfind(serverurl + 'servlet').content)
911
+ end
912
+
913
+ def test_propfind_async
914
+ conn = @client.propfind_async(serverurl + 'servlet')
915
+ Thread.pass while !conn.finished?
916
+ res = conn.pop
917
+ assert_equal('propfind', res.content.read)
918
+ end
919
+
920
+ def test_proppatch
921
+ assert_equal("proppatch", @client.proppatch(serverurl + 'servlet').content)
922
+ param = {'1'=>'2', '3'=>'4'}
923
+ res = @client.proppatch(serverurl + 'servlet', param)
924
+ assert_equal('proppatch', res.content)
925
+ assert_equal(param, params(res.header["x-query"][0]))
926
+ end
927
+
928
+ def test_proppatch_async
929
+ param = {'1'=>'2', '3'=>'4'}
930
+ conn = @client.proppatch_async(serverurl + 'servlet', param)
931
+ Thread.pass while !conn.finished?
932
+ res = conn.pop
933
+ assert_equal('proppatch', res.content.read)
934
+ assert_equal(param, params(res.header["x-query"][0]))
935
+ end
936
+
937
+ def test_trace
938
+ assert_equal("trace", @client.trace(serverurl + 'servlet').content)
939
+ param = {'1'=>'2', '3'=>'4'}
940
+ res = @client.trace(serverurl + 'servlet', param)
941
+ assert_equal(param, params(res.header["x-query"][0]))
942
+ end
943
+
944
+ def test_trace_async
945
+ param = {'1'=>'2', '3'=>'4'}
946
+ conn = @client.trace_async(serverurl + 'servlet', param)
947
+ Thread.pass while !conn.finished?
948
+ res = conn.pop
949
+ assert_equal(param, params(res.header["x-query"][0]))
950
+ end
951
+
952
+ def test_chunked
953
+ assert_equal('chunked', @client.get_content(serverurl + 'chunked', { 'msg' => 'chunked' }))
954
+ assert_equal('あいうえお', @client.get_content(serverurl + 'chunked', { 'msg' => 'あいうえお' }))
955
+ end
956
+
957
+ def test_chunked_empty
958
+ assert_equal('', @client.get_content(serverurl + 'chunked', { 'msg' => '' }))
959
+ end
960
+
961
+ def test_get_query
962
+ assert_equal({'1'=>'2'}, check_query_get({1=>2}))
963
+ assert_equal({'a'=>'A', 'B'=>'b'}, check_query_get({"a"=>"A", "B"=>"b"}))
964
+ assert_equal({'&'=>'&'}, check_query_get({"&"=>"&"}))
965
+ assert_equal({'= '=>' =+'}, check_query_get({"= "=>" =+"}))
966
+ assert_equal(
967
+ ['=', '&'].sort,
968
+ check_query_get([["=", "="], ["=", "&"]])['='].to_ary.sort
969
+ )
970
+ assert_equal({'123'=>'45'}, check_query_get('123=45'))
971
+ assert_equal({'12 3'=>'45', ' '=>' '}, check_query_get('12+3=45&+=+'))
972
+ assert_equal({}, check_query_get(''))
973
+ assert_equal({'1'=>'2'}, check_query_get({1=>StringIO.new('2')}))
974
+ assert_equal({'1'=>'2', '3'=>'4'}, check_query_get(StringIO.new('3=4&1=2')))
975
+
976
+ hash = check_query_get({"a"=>["A","a"], "B"=>"b"})
977
+ assert_equal({'a'=>'A', 'B'=>'b'}, hash)
978
+ assert_equal(['A','a'], hash['a'].to_ary)
979
+
980
+ hash = check_query_get({"a"=>WEBrick::HTTPUtils::FormData.new("A","a"), "B"=>"b"})
981
+ assert_equal({'a'=>'A', 'B'=>'b'}, hash)
982
+ assert_equal(['A','a'], hash['a'].to_ary)
983
+
984
+ hash = check_query_get({"a"=>[StringIO.new("A"),StringIO.new("a")], "B"=>StringIO.new("b")})
985
+ assert_equal({'a'=>'A', 'B'=>'b'}, hash)
986
+ assert_equal(['A','a'], hash['a'].to_ary)
987
+ end
988
+
989
+ def test_post_body
990
+ assert_equal({'1'=>'2'}, check_query_post({1=>2}))
991
+ assert_equal({'a'=>'A', 'B'=>'b'}, check_query_post({"a"=>"A", "B"=>"b"}))
992
+ assert_equal({'&'=>'&'}, check_query_post({"&"=>"&"}))
993
+ assert_equal({'= '=>' =+'}, check_query_post({"= "=>" =+"}))
994
+ assert_equal(
995
+ ['=', '&'].sort,
996
+ check_query_post([["=", "="], ["=", "&"]])['='].to_ary.sort
997
+ )
998
+ assert_equal({'123'=>'45'}, check_query_post('123=45'))
999
+ assert_equal({'12 3'=>'45', ' '=>' '}, check_query_post('12+3=45&+=+'))
1000
+ assert_equal({}, check_query_post(''))
1001
+ #
1002
+ post_body = StringIO.new("foo=bar&foo=baz")
1003
+ assert_equal(
1004
+ ["bar", "baz"],
1005
+ check_query_post(post_body)["foo"].to_ary.sort
1006
+ )
1007
+ end
1008
+
1009
+ def test_extra_headers
1010
+ str = ""
1011
+ @client.debug_dev = str
1012
+ @client.head(serverurl, nil, {"ABC" => "DEF"})
1013
+ lines = str.split(/(?:\r?\n)+/)
1014
+ assert_equal("= Request", lines[0])
1015
+ assert_match("ABC: DEF", lines[4])
1016
+ #
1017
+ str = ""
1018
+ @client.debug_dev = str
1019
+ @client.get(serverurl, nil, [["ABC", "DEF"], ["ABC", "DEF"]])
1020
+ lines = str.split(/(?:\r?\n)+/)
1021
+ assert_equal("= Request", lines[0])
1022
+ assert_match("ABC: DEF", lines[4])
1023
+ assert_match("ABC: DEF", lines[5])
1024
+ end
1025
+
1026
+ def test_http_custom_date_header
1027
+ @client.debug_dev = (str = "")
1028
+ res = @client.get(serverurl + 'hello', :header => {'Date' => 'foo'})
1029
+ lines = str.split(/(?:\r?\n)+/)
1030
+ assert_equal('Date: foo', lines[4])
1031
+ end
1032
+
1033
+ def test_timeout
1034
+ assert_equal(60, @client.connect_timeout)
1035
+ assert_equal(120, @client.send_timeout)
1036
+ assert_equal(60, @client.receive_timeout)
1037
+ #
1038
+ @client.connect_timeout = 1
1039
+ @client.send_timeout = 2
1040
+ @client.receive_timeout = 3
1041
+ assert_equal(1, @client.connect_timeout)
1042
+ assert_equal(2, @client.send_timeout)
1043
+ assert_equal(3, @client.receive_timeout)
1044
+ end
1045
+
1046
+ def test_connect_timeout
1047
+ # ToDo
1048
+ end
1049
+
1050
+ def test_send_timeout
1051
+ # ToDo
1052
+ end
1053
+
1054
+ def test_receive_timeout
1055
+ # this test takes 2 sec
1056
+ assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=2'))
1057
+ @client.receive_timeout = 1
1058
+ assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=0'))
1059
+ assert_raise(HTTPClient::ReceiveTimeoutError) do
1060
+ @client.get_content(serverurl + 'sleep?sec=2')
1061
+ end
1062
+ @client.receive_timeout = 3
1063
+ assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=2'))
1064
+ end
1065
+
1066
+ def test_receive_timeout_post
1067
+ # this test takes 2 sec
1068
+ assert_equal('hello', @client.post(serverurl + 'sleep', :sec => 2).content)
1069
+ @client.receive_timeout = 1
1070
+ assert_equal('hello', @client.post(serverurl + 'sleep', :sec => 0).content)
1071
+ assert_raise(HTTPClient::ReceiveTimeoutError) do
1072
+ @client.post(serverurl + 'sleep', :sec => 2)
1073
+ end
1074
+ @client.receive_timeout = 3
1075
+ assert_equal('hello', @client.post(serverurl + 'sleep', :sec => 2).content)
1076
+ end
1077
+
1078
+ def test_reset
1079
+ url = serverurl + 'servlet'
1080
+ assert_nothing_raised do
1081
+ 5.times do
1082
+ @client.get(url)
1083
+ @client.reset(url)
1084
+ end
1085
+ end
1086
+ end
1087
+
1088
+ def test_reset_all
1089
+ assert_nothing_raised do
1090
+ 5.times do
1091
+ @client.get(serverurl + 'servlet')
1092
+ @client.reset_all
1093
+ end
1094
+ end
1095
+ end
1096
+
1097
+ def test_cookies
1098
+ cookiefile = File.join(File.dirname(File.expand_path(__FILE__)), 'test_cookies_file')
1099
+ File.open(cookiefile, "wb") do |f|
1100
+ f << "http://rubyforge.org/account/login.php\tsession_ser\tLjEwMy45Ni40Ni0q%2A-fa0537de8cc31\t2000000000\t.rubyforge.org\t/\t13\n"
1101
+ end
1102
+ @client.set_cookie_store(cookiefile)
1103
+ cookie = @client.cookie_manager.cookies.first
1104
+ url = cookie.url
1105
+ assert(cookie.domain_match(url.host, cookie.domain))
1106
+ #
1107
+ @client.reset_all
1108
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\nSet-Cookie: foo=bar; expires=#{Time.at(1924873200).gmtime.httpdate}\n\nOK"
1109
+ @client.get_content('http://rubyforge.org/account/login.php')
1110
+ @client.save_cookie_store
1111
+ str = File.read(cookiefile)
1112
+ assert_match(%r(http://rubyforge.org/account/login.php\tfoo\tbar\t1924873200\trubyforge.org\t/account\t1), str)
1113
+ File.unlink(cookiefile)
1114
+ end
1115
+
1116
+ def test_eof_error_length
1117
+ io = StringIO.new('')
1118
+ def io.gets(*arg)
1119
+ @buf ||= ["HTTP/1.0 200 OK\n", "content-length: 123\n", "\n"]
1120
+ @buf.shift
1121
+ end
1122
+ def io.readpartial(size, buf)
1123
+ @second ||= false
1124
+ if !@second
1125
+ @second = '1st'
1126
+ buf << "abc"
1127
+ buf
1128
+ elsif @second == '1st'
1129
+ @second = '2nd'
1130
+ raise EOFError.new
1131
+ else
1132
+ raise Exception.new
1133
+ end
1134
+ end
1135
+ def io.eof?
1136
+ true
1137
+ end
1138
+ @client.test_loopback_http_response << io
1139
+ assert_nothing_raised do
1140
+ @client.get('http://foo/bar')
1141
+ end
1142
+ end
1143
+
1144
+ def test_eof_error_rest
1145
+ io = StringIO.new('')
1146
+ def io.gets(*arg)
1147
+ @buf ||= ["HTTP/1.0 200 OK\n", "\n"]
1148
+ @buf.shift
1149
+ end
1150
+ def io.readpartial(size, buf)
1151
+ @second ||= false
1152
+ if !@second
1153
+ @second = '1st'
1154
+ buf << "abc"
1155
+ buf
1156
+ elsif @second == '1st'
1157
+ @second = '2nd'
1158
+ raise EOFError.new
1159
+ else
1160
+ raise Exception.new
1161
+ end
1162
+ end
1163
+ def io.eof?
1164
+ true
1165
+ end
1166
+ @client.test_loopback_http_response << io
1167
+ assert_nothing_raised do
1168
+ @client.get('http://foo/bar')
1169
+ end
1170
+ end
1171
+
1172
+ def test_urify
1173
+ extend HTTPClient::Util
1174
+ assert_nil(urify(nil))
1175
+ uri = 'http://foo'
1176
+ assert_equal(urify(uri), urify(uri))
1177
+ assert_equal(urify(uri), urify(urify(uri)))
1178
+ end
1179
+
1180
+ def test_connection
1181
+ c = HTTPClient::Connection.new
1182
+ assert(c.finished?)
1183
+ assert_nil(c.join)
1184
+ end
1185
+
1186
+ def test_site
1187
+ site = HTTPClient::Site.new
1188
+ assert_equal('tcp', site.scheme)
1189
+ assert_equal('0.0.0.0', site.host)
1190
+ assert_equal(0, site.port)
1191
+ assert_equal('tcp://0.0.0.0:0', site.addr)
1192
+ assert_equal('tcp://0.0.0.0:0', site.to_s)
1193
+ assert_nothing_raised do
1194
+ site.inspect
1195
+ end
1196
+ #
1197
+ site = HTTPClient::Site.new(urify('http://localhost:12345/foo'))
1198
+ assert_equal('http', site.scheme)
1199
+ assert_equal('localhost', site.host)
1200
+ assert_equal(12345, site.port)
1201
+ assert_equal('http://localhost:12345', site.addr)
1202
+ assert_equal('http://localhost:12345', site.to_s)
1203
+ assert_nothing_raised do
1204
+ site.inspect
1205
+ end
1206
+ #
1207
+ site1 = HTTPClient::Site.new(urify('http://localhost:12341/'))
1208
+ site2 = HTTPClient::Site.new(urify('http://localhost:12342/'))
1209
+ site3 = HTTPClient::Site.new(urify('http://localhost:12342/'))
1210
+ assert(!(site1 == site2))
1211
+ h = { site1 => 'site1', site2 => 'site2' }
1212
+ h[site3] = 'site3'
1213
+ assert_equal('site1', h[site1])
1214
+ assert_equal('site3', h[site2])
1215
+ end
1216
+
1217
+ def test_http_header
1218
+ res = @client.get(serverurl + 'hello')
1219
+ assert_equal('text/html', res.contenttype)
1220
+ assert_equal(5, res.header.get(nil).size)
1221
+ #
1222
+ res.header.delete('connection')
1223
+ assert_equal(4, res.header.get(nil).size)
1224
+ #
1225
+ res.header['foo'] = 'bar'
1226
+ assert_equal(['bar'], res.header['foo'])
1227
+ #
1228
+ assert_equal([['foo', 'bar']], res.header.get('foo'))
1229
+ res.header['foo'] = ['bar', 'bar2']
1230
+ assert_equal([['foo', 'bar'], ['foo', 'bar2']], res.header.get('foo'))
1231
+ end
1232
+
1233
+ def test_mime_type
1234
+ assert_equal('text/plain', HTTP::Message.mime_type('foo.txt'))
1235
+ assert_equal('text/html', HTTP::Message.mime_type('foo.html'))
1236
+ assert_equal('text/html', HTTP::Message.mime_type('foo.htm'))
1237
+ assert_equal('application/msword', HTTP::Message.mime_type('foo.doc'))
1238
+ assert_equal('image/png', HTTP::Message.mime_type('foo.png'))
1239
+ assert_equal('image/gif', HTTP::Message.mime_type('foo.gif'))
1240
+ assert_equal('image/jpeg', HTTP::Message.mime_type('foo.jpg'))
1241
+ assert_equal('image/jpeg', HTTP::Message.mime_type('foo.jpeg'))
1242
+ assert_equal('application/octet-stream', HTTP::Message.mime_type('foo.unknown'))
1243
+ #
1244
+ handler = lambda { |path| 'hello/world' }
1245
+ assert_nil(HTTP::Message.mime_type_handler)
1246
+ assert_nil(HTTP::Message.get_mime_type_func)
1247
+ HTTP::Message.mime_type_handler = handler
1248
+ assert_not_nil(HTTP::Message.mime_type_handler)
1249
+ assert_not_nil(HTTP::Message.get_mime_type_func)
1250
+ assert_equal('hello/world', HTTP::Message.mime_type('foo.txt'))
1251
+ HTTP::Message.mime_type_handler = nil
1252
+ assert_equal('text/plain', HTTP::Message.mime_type('foo.txt'))
1253
+ HTTP::Message.set_mime_type_func(nil)
1254
+ assert_equal('text/plain', HTTP::Message.mime_type('foo.txt'))
1255
+ #
1256
+ handler = lambda { |path| nil }
1257
+ HTTP::Message.mime_type_handler = handler
1258
+ assert_equal('application/octet-stream', HTTP::Message.mime_type('foo.txt'))
1259
+ end
1260
+
1261
+ def test_connect_request
1262
+ req = HTTP::Message.new_connect_request(urify('https://foo/bar'))
1263
+ assert_equal("CONNECT foo:443 HTTP/1.0\r\n\r\n", req.dump)
1264
+ req = HTTP::Message.new_connect_request(urify('https://example.com/'))
1265
+ assert_equal("CONNECT example.com:443 HTTP/1.0\r\n\r\n", req.dump)
1266
+ end
1267
+
1268
+ def test_response
1269
+ res = HTTP::Message.new_response('response')
1270
+ res.contenttype = 'text/plain'
1271
+ res.header.body_date = Time.at(946652400)
1272
+ assert_equal(
1273
+ [
1274
+ "",
1275
+ "Content-Length: 8",
1276
+ "Content-Type: text/plain",
1277
+ "Last-Modified: Fri, 31 Dec 1999 15:00:00 GMT",
1278
+ "Status: 200 OK",
1279
+ "response"
1280
+ ],
1281
+ res.dump.split(/\r\n/).sort
1282
+ )
1283
+ assert_equal(['8'], res.header['Content-Length'])
1284
+ assert_equal('8', res.headers['Content-Length'])
1285
+ res.header.set('foo', 'bar')
1286
+ assert_equal(
1287
+ [
1288
+ "",
1289
+ "Content-Length: 8",
1290
+ "Content-Type: text/plain",
1291
+ "Last-Modified: Fri, 31 Dec 1999 15:00:00 GMT",
1292
+ "Status: 200 OK",
1293
+ "foo: bar",
1294
+ "response"
1295
+ ],
1296
+ res.dump.split(/\r\n/).sort
1297
+ )
1298
+ # nil body
1299
+ res = HTTP::Message.new_response(nil)
1300
+ assert_equal(
1301
+ [
1302
+ "Content-Length: 0",
1303
+ "Content-Type: text/html; charset=us-ascii",
1304
+ "Status: 200 OK"
1305
+ ],
1306
+ res.dump.split(/\r\n/).sort
1307
+ )
1308
+ # for mod_ruby env
1309
+ Object.const_set('Apache', nil)
1310
+ begin
1311
+ res = HTTP::Message.new_response('response')
1312
+ assert(res.dump.split(/\r\n/).any? { |line| /^Date/ =~ line })
1313
+ #
1314
+ res = HTTP::Message.new_response('response')
1315
+ res.contenttype = 'text/plain'
1316
+ res.header.body_date = Time.at(946652400)
1317
+ res.header['Date'] = Time.at(946652400).httpdate
1318
+ assert_equal(
1319
+ [
1320
+ "",
1321
+ "Content-Length: 8",
1322
+ "Content-Type: text/plain",
1323
+ "Date: Fri, 31 Dec 1999 15:00:00 GMT",
1324
+ "HTTP/1.1 200 OK",
1325
+ "Last-Modified: Fri, 31 Dec 1999 15:00:00 GMT",
1326
+ "response"
1327
+ ],
1328
+ res.dump.split(/\r\n/).sort
1329
+ )
1330
+ ensure
1331
+ Object.instance_eval { remove_const('Apache') }
1332
+ end
1333
+ end
1334
+
1335
+ def test_response_cookies
1336
+ res = HTTP::Message.new_response('response')
1337
+ res.contenttype = 'text/plain'
1338
+ res.header.body_date = Time.at(946652400)
1339
+ assert_nil(res.cookies)
1340
+ #
1341
+ res.header['Set-Cookie'] = [
1342
+ 'CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT',
1343
+ 'PART_NUMBER=ROCKET_LAUNCHER_0001; path=/'
1344
+ ]
1345
+ assert_equal(
1346
+ [
1347
+ "",
1348
+ "Content-Length: 8",
1349
+ "Content-Type: text/plain",
1350
+ "Last-Modified: Fri, 31 Dec 1999 15:00:00 GMT",
1351
+ "Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT",
1352
+ "Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/",
1353
+ "Status: 200 OK",
1354
+ "response"
1355
+ ],
1356
+ res.dump.split(/\r\n/).sort
1357
+ )
1358
+ assert_equal(2, res.cookies.size)
1359
+ assert_equal('CUSTOMER', res.cookies[0].name)
1360
+ assert_equal('PART_NUMBER', res.cookies[1].name)
1361
+ end
1362
+
1363
+ def test_ok_response_success
1364
+ res = HTTP::Message.new_response('response')
1365
+ assert_equal(true, res.ok?)
1366
+ res.status = 404
1367
+ assert_equal(false, res.ok?)
1368
+ res.status = 500
1369
+ assert_equal(false, res.ok?)
1370
+ res.status = 302
1371
+ assert_equal(false, res.ok?)
1372
+ end
1373
+
1374
+ if !defined?(JRUBY_VERSION) and RUBY_VERSION < '1.9'
1375
+ def test_timeout_scheduler
1376
+ assert_equal('hello', @client.get_content(serverurl + 'hello'))
1377
+ status = HTTPClient.timeout_scheduler.instance_eval { @thread.kill; @thread.join; @thread.status }
1378
+ assert(!status) # dead
1379
+ assert_equal('hello', @client.get_content(serverurl + 'hello'))
1380
+ end
1381
+ end
1382
+
1383
+ def test_session_manager
1384
+ mgr = HTTPClient::SessionManager.new(@client)
1385
+ assert_nil(mgr.instance_eval { @proxy })
1386
+ assert_nil(mgr.debug_dev)
1387
+ @client.debug_dev = Object.new
1388
+ @client.proxy = 'http://myproxy:12345'
1389
+ mgr = HTTPClient::SessionManager.new(@client)
1390
+ assert_equal('http://myproxy:12345', mgr.instance_eval { @proxy }.to_s)
1391
+ assert_equal(@client.debug_dev, mgr.debug_dev)
1392
+ end
1393
+
1394
+ def create_keepalive_disconnected_thread(idx, sock)
1395
+ Thread.new {
1396
+ # return "12345" for the first connection
1397
+ sock.gets
1398
+ sock.gets
1399
+ sock.write("HTTP/1.1 200 OK\r\n")
1400
+ sock.write("Content-Length: 5\r\n")
1401
+ sock.write("\r\n")
1402
+ sock.write("12345")
1403
+ # for the next connection, close while reading the request for emulating
1404
+ # KeepAliveDisconnected
1405
+ sock.gets
1406
+ sock.close
1407
+ }
1408
+ end
1409
+
1410
+ def test_keepalive_disconnected
1411
+ client = HTTPClient.new
1412
+ server = TCPServer.open('127.0.0.1', 0)
1413
+ server.listen(30) # set enough backlogs
1414
+ endpoint = "http://127.0.0.1:#{server.addr[1]}/"
1415
+ Thread.new {
1416
+ Thread.abort_on_exception = true
1417
+ # emulate 10 keep-alive connections
1418
+ 10.times do |idx|
1419
+ sock = server.accept
1420
+ create_keepalive_disconnected_thread(idx, sock)
1421
+ end
1422
+ # return "23456" for the request which gets KeepAliveDisconnected
1423
+ 5.times do
1424
+ sock = server.accept
1425
+ sock.gets
1426
+ sock.gets
1427
+ sock.write("HTTP/1.1 200 OK\r\n")
1428
+ sock.write("\r\n")
1429
+ sock.write("23456")
1430
+ sock.close
1431
+ end
1432
+ # return "34567" for the rest requests
1433
+ while true
1434
+ sock = server.accept
1435
+ sock.gets
1436
+ sock.gets
1437
+ sock.write("HTTP/1.1 200 OK\r\n")
1438
+ sock.write("Connection: close\r\n")
1439
+ sock.write("Content-Length: 5\r\n")
1440
+ sock.write("\r\n")
1441
+ sock.write("34567")
1442
+ sock.close
1443
+ end
1444
+ }
1445
+ # allocate 10 keep-alive connections
1446
+ (0...10).to_a.map {
1447
+ Thread.new {
1448
+ assert_equal("12345", client.get(endpoint).content)
1449
+ }
1450
+ }.each { |th| th.join }
1451
+ # send 5 requests, which should get KeepAliveDesconnected.
1452
+ # doing these requests, rest keep-alive connections are invalidated.
1453
+ (0...5).to_a.map {
1454
+ Thread.new {
1455
+ assert_equal("23456", client.get(endpoint).content)
1456
+ }
1457
+ }.each { |th| th.join }
1458
+ # rest requests won't get KeepAliveDisconnected; how can I check this?
1459
+ (0...10).to_a.map {
1460
+ Thread.new {
1461
+ assert_equal("34567", client.get(endpoint).content)
1462
+ }
1463
+ }.each { |th| th.join }
1464
+ end
1465
+
1466
+ def create_keepalive_thread(count, sock)
1467
+ Thread.new {
1468
+ Thread.abort_on_exception = true
1469
+ count.times do
1470
+ req = sock.gets
1471
+ while line = sock.gets
1472
+ break if line.chomp.empty?
1473
+ end
1474
+ case req
1475
+ when /chunked/
1476
+ sock.write("HTTP/1.1 200 OK\r\n")
1477
+ sock.write("Transfer-Encoding: chunked\r\n")
1478
+ sock.write("\r\n")
1479
+ sock.write("1a\r\n")
1480
+ sock.write("abcdefghijklmnopqrstuvwxyz\r\n")
1481
+ sock.write("10\r\n")
1482
+ sock.write("1234567890abcdef\r\n")
1483
+ sock.write("0\r\n")
1484
+ sock.write("\r\n")
1485
+ else
1486
+ sock.write("HTTP/1.1 200 OK\r\n")
1487
+ sock.write("Content-Length: 5\r\n")
1488
+ sock.write("\r\n")
1489
+ sock.write("12345")
1490
+ end
1491
+ end
1492
+ sock.close
1493
+ }
1494
+ end
1495
+
1496
+ def test_keepalive
1497
+ server = TCPServer.open('localhost', 0)
1498
+ server_thread = Thread.new {
1499
+ Thread.abort_on_exception = true
1500
+ sock = server.accept
1501
+ create_keepalive_thread(10, sock)
1502
+ }
1503
+ url = "http://localhost:#{server.addr[1]}/"
1504
+ begin
1505
+ # content-length
1506
+ 5.times do
1507
+ assert_equal('12345', @client.get(url).body)
1508
+ end
1509
+ # chunked
1510
+ 5.times do
1511
+ assert_equal('abcdefghijklmnopqrstuvwxyz1234567890abcdef', @client.get(url + 'chunked').body)
1512
+ end
1513
+ ensure
1514
+ server.close
1515
+ server_thread.join
1516
+ end
1517
+ end
1518
+
1519
+ def test_socket_local
1520
+ @client.socket_local.host = '127.0.0.1'
1521
+ assert_equal('hello', @client.get_content(serverurl + 'hello'))
1522
+ @client.reset_all
1523
+ @client.socket_local.port = serverport
1524
+ begin
1525
+ @client.get_content(serverurl + 'hello')
1526
+ rescue Errno::EADDRINUSE, SocketError
1527
+ assert(true)
1528
+ end
1529
+ end
1530
+
1531
+ def test_body_param_order
1532
+ ary = ('b'..'d').map { |k| ['key2', k] } << ['key1', 'a'] << ['key3', 'z']
1533
+ assert_equal("key2=b&key2=c&key2=d&key1=a&key3=z", HTTP::Message.escape_query(ary))
1534
+ end
1535
+
1536
+ if RUBY_VERSION > "1.9"
1537
+ def test_charset
1538
+ body = @client.get(serverurl + 'charset').body
1539
+ assert_equal(Encoding::EUC_JP, body.encoding)
1540
+ assert_equal('あいうえお'.encode(Encoding::EUC_JP), body)
1541
+ end
1542
+ end
1543
+
1544
+ if RUBY_VERSION >= "1.9.3"
1545
+ def test_continue
1546
+ @client.debug_dev = str = ''
1547
+ res = @client.get(serverurl + 'continue', :header => {:Expect => '100-continue'})
1548
+ assert_equal(200, res.status)
1549
+ assert_equal('done!', res.body)
1550
+ assert_match(/Expect: 100-continue/, str)
1551
+ end
1552
+ end
1553
+
1554
+ def test_ipv6literaladdress_in_uri
1555
+ server = TCPServer.open('::1', 0) rescue return # Skip if IPv6 is unavailable.
1556
+ server_thread = Thread.new {
1557
+ Thread.abort_on_exception = true
1558
+ sock = server.accept
1559
+ while line = sock.gets
1560
+ break if line.chomp.empty?
1561
+ end
1562
+ sock.write("HTTP/1.1 200 OK\r\n")
1563
+ sock.write("Content-Length: 5\r\n")
1564
+ sock.write("\r\n")
1565
+ sock.write("12345")
1566
+ sock.close
1567
+ }
1568
+ uri = "http://[::1]:#{server.addr[1]}/"
1569
+ begin
1570
+ assert_equal('12345', @client.get(uri).body)
1571
+ ensure
1572
+ server.close
1573
+ server_thread.kill
1574
+ server_thread.join
1575
+ end
1576
+ end
1577
+
1578
+ private
1579
+
1580
+ def check_query_get(query)
1581
+ WEBrick::HTTPUtils.parse_query(
1582
+ @client.get(serverurl + 'servlet', query).header["x-query"][0]
1583
+ )
1584
+ end
1585
+
1586
+ def check_query_post(query)
1587
+ WEBrick::HTTPUtils.parse_query(
1588
+ @client.post(serverurl + 'servlet', query).header["x-query"][0]
1589
+ )
1590
+ end
1591
+
1592
+ def setup_server
1593
+ @server = WEBrick::HTTPServer.new(
1594
+ :BindAddress => "localhost",
1595
+ :Logger => @logger,
1596
+ :Port => 0,
1597
+ :AccessLog => [],
1598
+ :DocumentRoot => File.dirname(File.expand_path(__FILE__))
1599
+ )
1600
+ @serverport = @server.config[:Port]
1601
+ [
1602
+ :hello, :sleep, :servlet_redirect, :redirect1, :redirect2, :redirect3,
1603
+ :redirect_self, :relative_redirect, :redirect_see_other, :chunked,
1604
+ :largebody, :status, :compressed, :charset, :continue
1605
+ ].each do |sym|
1606
+ @server.mount(
1607
+ "/#{sym}",
1608
+ WEBrick::HTTPServlet::ProcHandler.new(method("do_#{sym}").to_proc)
1609
+ )
1610
+ end
1611
+ @server.mount('/servlet', TestServlet.new(@server))
1612
+ @server_thread = start_server_thread(@server)
1613
+ end
1614
+
1615
+ def escape_noproxy
1616
+ backup = HTTPClient::NO_PROXY_HOSTS.dup
1617
+ HTTPClient::NO_PROXY_HOSTS.clear
1618
+ yield
1619
+ ensure
1620
+ HTTPClient::NO_PROXY_HOSTS.replace(backup)
1621
+ end
1622
+
1623
+ def do_hello(req, res)
1624
+ res['content-type'] = 'text/html'
1625
+ res.body = "hello"
1626
+ end
1627
+
1628
+ def do_sleep(req, res)
1629
+ sec = req.query['sec'].to_i
1630
+ sleep sec
1631
+ res['content-type'] = 'text/html'
1632
+ res.body = "hello"
1633
+ end
1634
+
1635
+ def do_servlet_redirect(req, res)
1636
+ res.set_redirect(WEBrick::HTTPStatus::Found, serverurl + "servlet")
1637
+ end
1638
+
1639
+ def do_redirect1(req, res)
1640
+ res.set_redirect(WEBrick::HTTPStatus::MovedPermanently, serverurl + "hello")
1641
+ end
1642
+
1643
+ def do_redirect2(req, res)
1644
+ res.set_redirect(WEBrick::HTTPStatus::TemporaryRedirect, serverurl + "redirect3")
1645
+ end
1646
+
1647
+ def do_redirect3(req, res)
1648
+ res.set_redirect(WEBrick::HTTPStatus::Found, serverurl + "hello")
1649
+ end
1650
+
1651
+ def do_redirect_self(req, res)
1652
+ res.set_redirect(WEBrick::HTTPStatus::Found, serverurl + "redirect_self")
1653
+ end
1654
+
1655
+ def do_relative_redirect(req, res)
1656
+ res.set_redirect(WEBrick::HTTPStatus::Found, "hello")
1657
+ end
1658
+
1659
+ def do_redirect_see_other(req, res)
1660
+ if req.request_method == 'POST'
1661
+ res.set_redirect(WEBrick::HTTPStatus::SeeOther, serverurl + "redirect_see_other") # self
1662
+ else
1663
+ res.body = 'hello'
1664
+ end
1665
+ end
1666
+
1667
+ def do_chunked(req, res)
1668
+ res.chunked = true
1669
+ res['content-type'] = 'text/plain; charset=UTF-8'
1670
+ piper, pipew = IO.pipe
1671
+ res.body = piper
1672
+ pipew << req.query['msg']
1673
+ pipew.close
1674
+ end
1675
+
1676
+ def do_largebody(req, res)
1677
+ res['content-type'] = 'text/html'
1678
+ res.body = "a" * 1000 * 1000
1679
+ end
1680
+
1681
+ def do_compressed(req, res)
1682
+ res['content-type'] = 'application/octet-stream'
1683
+ if req.query['enc'] == 'gzip'
1684
+ res['content-encoding'] = 'gzip'
1685
+ res.body = GZIP_CONTENT
1686
+ elsif req.query['enc'] == 'deflate'
1687
+ res['content-encoding'] = 'deflate'
1688
+ res.body = DEFLATE_CONTENT
1689
+ end
1690
+ end
1691
+
1692
+ def do_charset(req, res)
1693
+ if RUBY_VERSION > "1.9"
1694
+ res.body = 'あいうえお'.encode("euc-jp")
1695
+ res['Content-Type'] = 'text/plain; charset=euc-jp'
1696
+ else
1697
+ res.body = 'this endpoint is for 1.9 or later'
1698
+ end
1699
+ end
1700
+
1701
+ def do_status(req, res)
1702
+ res.status = req.query['status'].to_i
1703
+ end
1704
+
1705
+ def do_continue(req, res)
1706
+ req.continue
1707
+ res.body = 'done!'
1708
+ end
1709
+
1710
+ class TestServlet < WEBrick::HTTPServlet::AbstractServlet
1711
+ def get_instance(*arg)
1712
+ self
1713
+ end
1714
+
1715
+ def do_HEAD(req, res)
1716
+ res["x-head"] = 'head' # use this for test purpose only.
1717
+ res["x-query"] = query_response(req)
1718
+ end
1719
+
1720
+ def do_GET(req, res)
1721
+ res.body = 'get'
1722
+ res["x-query"] = query_response(req)
1723
+ end
1724
+
1725
+ def do_POST(req, res)
1726
+ res["content-type"] = "text/plain" # iso-8859-1, not US-ASCII
1727
+ res.body = 'post,' + req.body.to_s
1728
+ res["x-query"] = body_response(req)
1729
+ end
1730
+
1731
+ def do_PUT(req, res)
1732
+ res["x-query"] = body_response(req)
1733
+ param = WEBrick::HTTPUtils.parse_query(req.body) || {}
1734
+ res["x-size"] = (param['txt'] || '').size
1735
+ res.body = param['txt'] || 'put'
1736
+ end
1737
+
1738
+ def do_DELETE(req, res)
1739
+ res.body = 'delete'
1740
+ end
1741
+
1742
+ def do_OPTIONS(req, res)
1743
+ # check RFC for legal response.
1744
+ res.body = 'options'
1745
+ end
1746
+
1747
+ def do_PROPFIND(req, res)
1748
+ res.body = 'propfind'
1749
+ end
1750
+
1751
+ def do_PROPPATCH(req, res)
1752
+ res.body = 'proppatch'
1753
+ res["x-query"] = body_response(req)
1754
+ end
1755
+
1756
+ def do_TRACE(req, res)
1757
+ # client SHOULD reflect the message received back to the client as the
1758
+ # entity-body of a 200 (OK) response. [RFC2616]
1759
+ res.body = 'trace'
1760
+ res["x-query"] = query_response(req)
1761
+ end
1762
+
1763
+ private
1764
+
1765
+ def query_response(req)
1766
+ query_escape(WEBrick::HTTPUtils.parse_query(req.query_string))
1767
+ end
1768
+
1769
+ def body_response(req)
1770
+ query_escape(WEBrick::HTTPUtils.parse_query(req.body))
1771
+ end
1772
+
1773
+ def query_escape(query)
1774
+ escaped = []
1775
+ query.sort_by { |k, v| k }.collect do |k, v|
1776
+ v.to_ary.each do |ve|
1777
+ escaped << CGI.escape(k) + '=' + CGI.escape(ve)
1778
+ end
1779
+ end
1780
+ escaped.join('&')
1781
+ end
1782
+ end
1783
+ end