glebtv-httpclient 3.2.4 → 3.2.6

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.
@@ -1,322 +1,1138 @@
1
1
  # coding: utf-8
2
2
  require 'spec_helper'
3
3
 
4
- describe HTTPClient do
4
+ describe 'HTTPClient' do
5
5
  before :each do
6
6
  @client = HTTPClient.new
7
7
  end
8
8
 
9
- describe 'GET' do
10
- it 'performs normal GET' do
11
- HTTPClient.new.get(@srv.u('servlet')) do |s|
12
- s.should eq 'get'
9
+ it "initialize" do
10
+ without_noproxy do
11
+ @proxy.io.string = ""
12
+ @client = HTTPClient.new(@proxy.u)
13
+ @client.proxy.should == urify(@proxy.u)
14
+ @client.head(@srv.u).status.should == 200
15
+ @proxy.io.string.should =~ /accept/
16
+ end
17
+ end
18
+
19
+ it "agent name" do
20
+ @client = HTTPClient.new(nil, "agent_name_foo")
21
+ str = ""
22
+ @client.debug_dev = str
23
+ @client.get(@srv.u)
24
+ lines = str.split(/(?:\r?\n)+/)
25
+ lines[0].should == "= Request"
26
+ lines[4].should match /^User-Agent: agent_name_foo/
27
+ end
28
+
29
+ it "from" do
30
+ @client = HTTPClient.new(nil, nil, "from_bar")
31
+ str = ""
32
+ @client.debug_dev = str
33
+ @client.get(@srv.u)
34
+ lines = str.split(/(?:\r?\n)+/)
35
+ lines[0].should == "= Request"
36
+ lines[5].should match /^From: from_bar/
37
+ end
38
+
39
+ it "debug dev" do
40
+ str = ""
41
+ @client.debug_dev = str
42
+ @client.debug_dev.object_id.should == str.object_id
43
+ str.empty?.should be_true
44
+ @client.get(@srv.u)
45
+ str.empty?.should be_false
46
+ end
47
+
48
+ it "debug dev stream" do
49
+ str = ""
50
+ @client.debug_dev = str
51
+ conn = @client.get_async(@srv.u)
52
+ until conn.finished?
53
+ Thread.pass
54
+ end
55
+ str.empty?.should be_false
56
+ end
57
+
58
+ it "host given" do
59
+ str = ""
60
+ @client.debug_dev = str
61
+ @client.get(@srv.u)
62
+ lines = str.split(/(?:\r?\n)+/)
63
+ lines[0].should == "= Request"
64
+ lines[2].should == "! CONNECTION ESTABLISHED"
65
+ lines[3].should == "GET / HTTP/1.1"
66
+ lines[7].should == "Host: localhost:#{@srv.port}"
67
+ @client.reset_all
68
+ str = ""
69
+ @client.debug_dev = str
70
+ @client.get(@srv.u, nil, "Host" => "foo")
71
+ lines = str.split(/(?:\r?\n)+/)
72
+ lines[0].should == "= Request"
73
+ lines[2].should == "! CONNECTION ESTABLISHED"
74
+ lines[3].should == "GET / HTTP/1.1"
75
+ lines[4].should == "Host: foo"
76
+ end
77
+
78
+ it "redirect returns not modified" do
79
+ timeout(2) do
80
+ @client.get(@srv.u("status"), {:status => 306}, :follow_redirect => true)
81
+ end
82
+ end
83
+
84
+ it "proxy" do
85
+ without_noproxy do
86
+ begin
87
+ @client.proxy = "http://"
88
+ rescue
89
+ $!.class.to_s.should match(/InvalidURIError/)
13
90
  end
91
+ @client.proxy = ""
92
+ @client.proxy.should be_nil
93
+ @client.proxy = "http://admin:admin@foo:1234"
94
+ @client.proxy.should == urify("http://admin:admin@foo:1234")
95
+ uri = urify("http://bar:2345")
96
+ @client.proxy = uri
97
+ @client.proxy.should == uri
98
+ @proxy.io.string = ""
99
+ @client.proxy = nil
100
+ @client.head(@srv.u).status.should == 200
101
+ @proxy.io.string.should_not =~ /accept/
102
+ @proxy.io.string = ""
103
+ @client.proxy = @proxy.u
104
+ @client.debug_dev = str = ""
105
+ @client.head(@srv.u).status.should == 200
106
+ @proxy.io.string.should =~ /accept/
107
+ str.should =~ /Host: localhost:#{@srv.port}/
14
108
  end
15
-
16
- describe '#download_file' do
17
- it 'writes to file' do
18
- file = Tempfile.new('httpcl')
19
- HTTPClient.new.download_file(@srv.u('largebody'), file.path)
20
- file.read.length.should eq 1_000_000
109
+ end
110
+
111
+ it "host header" do
112
+ @client.proxy = @proxy.u
113
+ @client.debug_dev = str = ""
114
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n"
115
+ @client.head("http://www.example.com/foo").status.should == 200
116
+ (/\r\nHost: www\.example\.com\r\n/ =~ str).should be_true
117
+ @client.debug_dev = str = ""
118
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n"
119
+ @client.head('http://www.example.com:12345/foo').status.should eq 200
120
+ str.should =~ /\r\nHost: www\.example\.com:12345\r\n/
121
+ end
122
+
123
+ it "proxy env" do
124
+ ClimateControl.modify http_proxy: 'http://admin:admin@foo:1234', NO_PROXY: 'foobar' do
125
+ client = HTTPClient.new
126
+ client.proxy.should == urify("http://admin:admin@foo:1234")
127
+ client.no_proxy.should == "foobar"
128
+ end
129
+ end
130
+
131
+ it "proxy env cgi" do
132
+ ClimateControl.modify http_proxy: 'http://admin:admin@foo:1234', NO_PROXY: 'foobar', REQUEST_METHOD: 'GET' do
133
+ client = HTTPClient.new
134
+ client.proxy.should == nil
135
+ ClimateControl.modify CGI_HTTP_PROXY: 'http://admin:admin@foo:1234' do
136
+ client = HTTPClient.new
137
+ client.proxy.should == urify("http://admin:admin@foo:1234")
21
138
  end
139
+ end
140
+ end
141
+
142
+ it "empty proxy env" do
143
+ ClimateControl.modify http_proxy: '' do
144
+ client = HTTPClient.new
145
+ client.proxy.should == nil
146
+ end
147
+ end
148
+
149
+ it "noproxy for localhost" do
150
+ @proxy.io.string = ""
151
+ @client.proxy = @proxy.u
152
+ @client.head(@srv.u).status.should == 200
153
+ @proxy.io.string.should_not =~ /accept/
154
+ end
155
+
156
+ it "no proxy" do
157
+ without_noproxy do
158
+ @client.no_proxy.should == nil
159
+ @client.no_proxy = "localhost"
160
+ @client.no_proxy.should == "localhost"
22
161
 
23
- it 'compressed' do
24
- file = Tempfile.new('httpcl')
25
- @client.download_file(@srv.u('compressed?enc=gzip'), file.path)
26
- file.read.length.should eq 25
27
- end
162
+ @proxy.io.string = ""
163
+ @client.proxy = nil
164
+ @client.head(@srv.u).status.should == 200
165
+ @proxy.io.string.should_not =~ /accept/
28
166
 
29
- it 'compressed transparent' do
30
- @client.transparent_gzip_decompression = true
167
+ @proxy.io.string = ""
168
+ @client.proxy = @proxy.u
169
+ @client.head(@srv.u).status.should == 200
170
+ @proxy.io.string.should_not =~ /accept/
31
171
 
32
- file = Tempfile.new('httpcl')
33
- @client.download_file(@srv.u('compressed?enc=gzip'), file.path)
34
- cnt = file.read
35
- cnt.length.should eq 5
36
- cnt.should eq 'hello'
172
+ @proxy.io.string = ""
173
+ @client.no_proxy = "foobar"
174
+ @client.proxy = @proxy.u
175
+ @client.head(@srv.u).status.should == 200
176
+ @proxy.io.string.should =~ /accept/
37
177
 
38
- @client.download_file(@srv.u('compressed?enc=deflate'), file.path)
39
- cnt = file.read
40
- cnt.length.should eq 5
41
- cnt.should eq 'hello'
42
- end
178
+ @proxy.io.string = ""
179
+ @client.no_proxy = "foobar,localhost:baz"
180
+ @client.proxy = @proxy.u
181
+ @client.head(@srv.u).status.should == 200
182
+ @proxy.io.string.should_not =~ /accept/
43
183
 
44
- it 'compressed large' do
45
- file = Tempfile.new('httpcl')
46
- @client.transparent_gzip_decompression = true
184
+ @proxy.io.string = ""
185
+ @client.no_proxy = "foobar,localhost:443"
186
+ @client.proxy = @proxy.u
187
+ @client.head(@srv.u).status.should == 200
188
+ @proxy.io.string.should =~ /accept/
47
189
 
48
- content = @client.download_file(@srv.u('compressed_large?enc=gzip'), file.path)
49
- file.read.should eq LARGE_STR
190
+ @proxy.io.string = ""
191
+ @client.no_proxy = "foobar,localhost:443:localhost:#{@srv.port},baz"
192
+ @client.proxy = @proxy.u
193
+ @client.head(@srv.u).status.should == 200
194
+ @proxy.io.string.should_not =~ /accept/
195
+ end
196
+ end
197
+
198
+ describe "no proxy with initial dot" do
199
+ before :each do
200
+ @client.debug_dev = @str = ""
201
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n"
202
+ @client.proxy = @proxy.u
50
203
 
51
- content = @client.download_file(@srv.u('compressed_large?enc=deflate'), file.path)
52
- file.read.should eq LARGE_STR
53
- end
54
204
  end
205
+ it 'via proxy' do
206
+ @client.no_proxy = ""
207
+ @client.head("http://www.foo.com")
208
+ @str.should =~ /CONNECT TO localhost/
209
+ end
210
+ it 'no proxy because .foo.com matches with www.foo.com' do
211
+ @client.no_proxy = ".foo.com"
212
+ @client.head("http://www.foo.com")
213
+ @str.should =~ /CONNECT TO www.foo.com/
214
+ end
215
+ it 'via proxy because .foo.com does not matche with foo.com' do
216
+ @client.no_proxy = ".foo.com"
217
+ @client.head("http://foo.com")
218
+ @str.should =~ /CONNECT TO localhost/
219
+ end
220
+ it 'no proxy because foo.com matches with foo.com' do
221
+ @client.no_proxy = "foo.com"
222
+ @client.head("http://foo.com")
223
+ @str.should =~ /CONNECT TO foo.com/
224
+ end
225
+ end
226
+
227
+ it "cookie update while authentication" do
228
+ without_noproxy do
229
+ @client.test_loopback_http_response << <<EOS
230
+ HTTP/1.0 401\r
231
+ Date: Fri, 19 Dec 2008 11:57:29 GMT\r
232
+ Content-Type: text/plain\r
233
+ Content-Length: 0\r
234
+ WWW-Authenticate: Basic realm="hello"\r
235
+ Set-Cookie: foo=bar; path=/; domain=.example.org; expires=#{Time.at(1924873200).httpdate}\r
236
+ \r
237
+ EOS
238
+ @client.test_loopback_http_response << <<EOS
239
+ HTTP/1.1 200 OK\r
240
+ Content-Length: 5\r
241
+ Connection: close\r
242
+ \r
243
+ hello
244
+ EOS
245
+ @client.debug_dev = str = ""
246
+ @client.set_auth("http://www.example.org/baz/", "admin", "admin")
247
+ @client.get("http://www.example.org/baz/foo").content.should == "hello"
248
+ str.should match /^Cookie: foo=bar/
249
+ str.should match /^Authorization: Basic YWRtaW46YWRtaW4=/
250
+ end
251
+ end
252
+
253
+ it "proxy ssl" do
254
+ without_noproxy do
255
+ @client.proxy = "http://admin:admin@localhost:8080/"
256
+ @client.test_loopback_http_response << <<EOS
257
+ HTTP/1.0 407 Proxy Authentication Required\r
258
+ Date: Fri, 19 Dec 2008 11:57:29 GMT\r
259
+ Content-Type: text/plain\r
260
+ Content-Length: 0\r
261
+ Proxy-Authenticate: Basic realm="hello"\r
262
+ Proxy-Connection: close\r
263
+ \r
264
+ EOS
265
+ @client.test_loopback_http_response << <<EOS
266
+ HTTP/1.0 200 Connection established\r
267
+ \r
268
+ HTTP/1.1 200 OK\r
269
+ Content-Length: 5\r
270
+ Connection: close\r
271
+ \r
272
+ hello
273
+ EOS
274
+ @client.get("https://localhost:17171/baz").content.should == "hello"
275
+ end
276
+ end
277
+
278
+ it "loopback response" do
279
+ @client.test_loopback_response << "message body 1"
280
+ @client.test_loopback_response << "message body 2"
281
+ @client.get_content("http://somewhere").should == "message body 1"
282
+ @client.get_content("http://somewhere").should == "message body 2"
283
+ @client.debug_dev = str = ""
284
+ @client.test_loopback_response << "message body 3"
285
+ @client.get_content("http://somewhere").should == "message body 3"
286
+ str.should match /message body 3/
287
+ end
288
+
289
+ it "loopback response stream" do
290
+ @client.test_loopback_response << "message body 1"
291
+ @client.test_loopback_response << "message body 2"
292
+ conn = @client.get_async("http://somewhere")
293
+ until conn.finished?
294
+ Thread.pass
295
+ end
296
+ conn.pop.content.read.should == "message body 1"
297
+ conn = @client.get_async("http://somewhere")
298
+ until conn.finished?
299
+ Thread.pass
300
+ end
301
+ conn.pop.content.read.should == "message body 2"
302
+ end
303
+
304
+ it "loopback http response" do
305
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK
306
+ content-length: 100
55
307
 
56
- describe '#get_content' do
57
- it 'normal' do
58
- @client.get_content(@srv.u('hello')).should eq 'hello'
59
- @client.get_content(@srv.u('redirect1')).should eq 'hello'
60
- @client.get_content(@srv.u('redirect2')).should eq 'hello'
61
- end
308
+ message body 1"
309
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK
310
+ content-length: 100
62
311
 
63
- it '127.0.0.1' do
64
- url = @srv.u.sub(/localhost/, '127.0.0.1')
65
- @client.get_content(url + 'hello').should eq 'hello'
66
- @client.get_content(url + 'redirect1').should eq 'hello'
67
- @client.get_content(url + 'redirect2').should eq 'hello'
68
- end
312
+ message body 2"
313
+ @client.get_content("http://somewhere").should == "message body 1"
314
+ @client.get_content("http://somewhere").should == "message body 2"
315
+ end
316
+
317
+ it "multiline header" do
318
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK
319
+ X-Foo: XXX
320
+ YYY
321
+ X-Bar:
322
+ XXX
323
+ YYY
324
+ content-length: 100
69
325
 
70
- it 'redirect callback' do
71
- called = false
72
- @client.redirect_uri_callback = lambda { |uri, res|
73
- newuri = res.header['location'][0]
74
- called = true
75
- newuri
76
- }
326
+ message body 1"
327
+ res = @client.get("http://somewhere")
328
+ res.content.should == "message body 1"
329
+ res.header["x-foo"].should == ["XXX YYY"]
330
+ res.header["x-bar"].should == ["XXX YYY"]
331
+ end
332
+
333
+ it "broken header" do
334
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK
335
+ XXXXX
336
+ content-length: 100
77
337
 
78
- @client.get_content(@srv.u('relative_redirect')).should eq 'hello'
79
- called.should be_true
80
- end
338
+ message body 1"
339
+ res = @client.get("http://somewhere")
340
+ res.content.should == "message body 1"
341
+ end
342
+
343
+ it "request uri in response" do
344
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK
345
+ content-length: 100
81
346
 
82
- it 'errors' do
83
- expect {
84
- @client.get_content(@srv.u 'notfound')
85
- }.to raise_error(HTTPClient::BadResponseError)
347
+ message body"
348
+ @client.get("http://google.com/").header.request_uri.should == urify("http://google.com/")
349
+ end
350
+
351
+ it "request uri in response when redirect" do
352
+ expected = urify(@srv.u("hello"))
353
+ @client.get(@srv.u("redirect1"), :follow_redirect => true).header.request_uri.should == expected
354
+ @client.get(@srv.u("redirect2"), :follow_redirect => true).header.request_uri.should == expected
355
+ end
356
+
357
+ describe "redirect" do
358
+ before :each do
359
+ @url = @srv.u('redirect1')
360
+ @https_url = urify(@url)
361
+ @https_url.scheme = 'https'
362
+ @redirect_to_http = "HTTP/1.0 302 OK\nLocation: #{@url}\n\n"
363
+ @redirect_to_https = "HTTP/1.0 302 OK\nLocation: #{@https_url}\n\n"
364
+ @client.reset_all
365
+ end
86
366
 
87
- expect {
88
- @client.get_content(@srv.u 'redirect_self')
89
- }.to raise_error(HTTPClient::BadResponseError)
90
- end
367
+ # TODO check if this should be present
368
+ pending 'https -> http is denied' do
369
+ @client.test_loopback_http_response << @redirect_to_http
370
+ expect {
371
+ @client.get_content(@https_url)
372
+ }.to raise_error(HTTPClient::BadResponseError)
373
+ end
91
374
 
92
- it 'with block' do
93
- @client.get_content(@srv.u 'hello') do |str|
94
- str.should eq 'hello'
95
- end
96
- @client.get_content(@srv.u + 'redirect1') do |str|
97
- str.should eq 'hello'
98
- end
99
- @client.get_content(@srv.u + 'redirect2') do |str|
100
- str.should eq 'hello'
101
- end
102
- end
375
+ it 'http -> http is OK' do
376
+ @client.test_loopback_http_response << @redirect_to_http
377
+ @client.get_content(@url).should eq 'hello'
378
+ end
103
379
 
104
- it 'compressed' do
105
- @client.transparent_gzip_decompression = false
380
+ it 'trying to normal endpoint with SSL -> SSL negotiation failure' do
381
+ @client.test_loopback_http_response << @redirect_to_https
382
+ expect {
383
+ @client.get_content(@https_url)
384
+ }.to raise_error(OpenSSL::SSL::SSLError)
385
+ end
106
386
 
107
- content = @client.get_content(@srv.u 'compressed?enc=gzip')
108
- content.should_not eq 'hello'
109
- content.should eq GZIP_CONTENT
110
- @client.transparent_gzip_decompression = true
387
+ it 'https -> https is OK' do
388
+ @client.reset_all
389
+ @client.test_loopback_http_response << @redirect_to_https
390
+ expect {
391
+ @client.get_content(@https_url)
392
+ }.to raise_error(OpenSSL::SSL::SSLError)
393
+ end
111
394
 
112
- content = @client.get_content(@srv.u 'compressed?enc=gzip')
113
- content.should eq 'hello'
395
+ it 'https -> http with strict_redirect_uri_callback' do
396
+ @client.redirect_uri_callback = @client.method(:strict_redirect_uri_callback)
397
+ @client.test_loopback_http_response << @redirect_to_http
398
+ expect {
399
+ @client.get_content(@https_url)
400
+ }.to raise_error(HTTPClient::BadResponseError)
401
+ end
402
+ end
403
+
404
+ it "redirect see other" do
405
+ @client.post_content(@srv.u("redirect_see_other")).should == "hello"
406
+ end
407
+
408
+ it "redirect relative" do
409
+ @client.test_loopback_http_response << "HTTP/1.0 302 OK\nLocation: hello\n\n"
410
+ silent do
411
+ @client.get_content(@srv.u('redirect1')).should eq 'hello'
412
+ end
114
413
 
115
- content = @client.get_content(@srv.u 'compressed?enc=deflate')
116
- content.should eq 'hello'
117
- end
414
+ @client.reset_all
415
+ @client.redirect_uri_callback = @client.method(:strict_redirect_uri_callback)
416
+ @client.get_content(@srv.u('redirect1')).should eq 'hello'
417
+ @client.reset_all
418
+ @client.test_loopback_http_response << "HTTP/1.0 302 OK\nLocation: hello\n\n"
419
+ begin
420
+ @client.get_content(@srv.u('redirect1'))
421
+ false.should be_true
422
+ rescue HTTPClient::BadResponseError => e
423
+ e.res.status.should eq 302
424
+ end
425
+ end
426
+
427
+ it "redirect https relative" do
428
+ url = @srv.u("redirect1")
429
+ https_url = urify(url)
430
+ https_url.scheme = "https"
431
+ @client.test_loopback_http_response << "HTTP/1.0 302 OK
432
+ Location: /foo
118
433
 
119
- it 'compressed large' do
120
- @client.transparent_gzip_decompression = true
434
+ "
435
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK
121
436
 
122
- content = @client.get_content(@srv.u 'compressed_large?enc=gzip')
123
- content.should eq LARGE_STR
437
+ hello"
438
+
439
+ silent do
440
+ @client.get_content(https_url).should == "hello"
441
+ end
442
+ end
443
+
444
+ it "no content" do
445
+ timeout(2) do
446
+ @client.get(@srv.u("status"), :status => 101)
447
+ @client.get(@srv.u("status"), :status => 204)
448
+ @client.get(@srv.u("status"), :status => 304)
449
+ end
450
+ end
451
+
452
+ it "head" do
453
+ @client.head(@srv.u("servlet")).header["x-head"][0].should == "head"
454
+ param = {"1" => "2", "3" => "4"}
455
+ res = @client.head(@srv.u("servlet"), param)
456
+ params(res.header["x-query"][0]).should == param
457
+ end
458
+
459
+ it "head async" do
460
+ param = {"1" => "2", "3" => "4"}
461
+ conn = @client.head_async(@srv.u("servlet"), param)
462
+ until conn.finished?
463
+ Thread.pass
464
+ end
465
+ res = conn.pop
466
+ params(res.header["x-query"][0]).should == param
467
+ end
468
+
469
+ it "get" do
470
+ @client.get(@srv.u("servlet")).content.should == "get"
471
+ param = {"1" => "2", "3" => "4"}
472
+ res = @client.get(@srv.u("servlet"), param)
473
+ params(res.header["x-query"][0]).should == param
474
+ res.contenttype.should be_nil
475
+ url = @srv.u("servlet?5=6&7=8")
476
+ res = @client.get(url, param)
477
+ params(res.header["x-query"][0]).should == param.merge("5" => "6", "7" => "8")
478
+ res.contenttype.should be_nil
479
+ end
480
+
481
+ it "head follow redirect" do
482
+ expected = urify(@srv.u("hello"))
483
+ @client.head(@srv.u("hello"), :follow_redirect => true).header.request_uri.should == expected
484
+ @client.head(@srv.u("redirect1"), :follow_redirect => true).header.request_uri.should == expected
485
+ @client.head(@srv.u("redirect2"), :follow_redirect => true).header.request_uri.should == expected
486
+ end
487
+
488
+ it "get follow redirect" do
489
+ @client.get(@srv.u("hello"), :follow_redirect => true).body.should == "hello"
490
+ @client.get(@srv.u("redirect1"), :follow_redirect => true).body.should == "hello"
491
+ @client.get(@srv.u("redirect2"), :follow_redirect => true).body.should == "hello"
492
+ end
493
+
494
+ it "get async" do
495
+ param = {"1" => "2", "3" => "4"}
496
+ conn = @client.get_async(@srv.u("servlet"), param)
497
+ until conn.finished?
498
+ Thread.pass
499
+ end
500
+ res = conn.pop
501
+ params(res.header["x-query"][0]).should == param
502
+ end
503
+
504
+ it "get async for largebody" do
505
+ conn = @client.get_async(@srv.u("largebody"))
506
+ res = conn.pop
507
+ res.content.read.length.should == 1000.*(1000)
508
+ end
509
+
510
+ it "get with block" do
511
+ called = false
512
+ res = @client.get(@srv.u("servlet")) do |str|
513
+ str.should == "get"
514
+ called = true
515
+ end
516
+ called.should be_true
517
+ res.content.should be_nil
518
+ end
519
+
520
+ it "get with block chunk string recycle" do
521
+ @client.read_block_size = 2
522
+ body = []
523
+ res = @client.get(@srv.u("servlet")) do |str|
524
+ body << str
525
+ end
526
+ body.size.should == 2
527
+ body.join.should == "get"
528
+ end
529
+
530
+ it "post" do
531
+ @client.post(@srv.u("servlet")).content[0, 4].should == "post"
532
+ param = {"1" => "2", "3" => "4"}
533
+ res = @client.post(@srv.u("servlet"), param)
534
+ params(res.header["x-query"][0]).should == param
535
+ end
536
+
537
+ it "post follow redirect" do
538
+ @client.post(@srv.u("hello"), :follow_redirect => true).body.should == "hello"
539
+ @client.post(@srv.u("redirect1"), :follow_redirect => true).body.should == "hello"
540
+ @client.post(@srv.u("redirect2"), :follow_redirect => true).body.should == "hello"
541
+ end
542
+
543
+ it "post with content type" do
544
+ param = [["1", "2"], ["3", "4"]]
545
+ ext = {"content-type" => "application/x-www-form-urlencoded", "hello" => "world"}
546
+ @client.post(@srv.u("servlet")).content[0, 4].should == "post"
547
+ res = @client.post(@srv.u("servlet"), param, ext)
548
+ params(res.header["x-query"][0]).should == Hash[param]
549
+ ext = [["content-type", "multipart/form-data"], ["hello", "world"]]
550
+ @client.post(@srv.u("servlet")).content[0, 4].should == "post"
551
+ res = @client.post(@srv.u("servlet"), param, ext)
552
+ res.content.should match /Content-Disposition: form-data; name="1"/
553
+ res.content.should match /Content-Disposition: form-data; name="3"/
554
+ ext = {"content-type" => "multipart/form-data; boundary=hello"}
555
+ @client.post(@srv.u("servlet")).content[0, 4].should == "post"
556
+ res = @client.post(@srv.u("servlet"), param, ext)
557
+ res.content.should match /Content-Disposition: form-data; name="1"/
558
+ res.content.should match /Content-Disposition: form-data; name="3"/
559
+ res.content.should == "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"
560
+ end
561
+
562
+ it "post with custom multipart and boolean params" do
563
+ param = [["boolean_true", true]]
564
+ ext = {"content-type" => "multipart/form-data"}
565
+ @client.post(@srv.u("servlet")).content[0, 4].should == "post"
566
+ res = @client.post(@srv.u("servlet"), param, ext)
567
+ res.content.should match /Content-Disposition: form-data; name="boolean_true"\r\n\r\ntrue\r\n/
124
568
 
125
- content = @client.get_content(@srv.u 'compressed_large?enc=deflate')
126
- content.should eq LARGE_STR
127
- end
569
+ param = [["boolean_false", false]]
570
+ res = @client.post(@srv.u("servlet"), param, ext)
571
+ res.content.should match /Content-Disposition: form-data; name="boolean_false"\r\n\r\nfalse\r\n/
572
+
573
+ param = [["nil", nil]]
574
+ res = @client.post(@srv.u("servlet"), param, ext)
575
+ res.content.should match /Content-Disposition: form-data; name="nil"\r\n\r\n\r\n/
576
+ end
577
+
578
+ it "post with file" do
579
+ STDOUT.sync = true
580
+ File.open(__FILE__) do |file|
581
+ res = @client.post(@srv.u("servlet"), 1 => 2, 3 => file)
582
+ res.content.should match /^Content-Disposition: form-data; name="1"\r\n/mn
583
+ res.content.should match /^Content-Disposition: form-data; name="3";/
584
+ res.content.should match /FIND_TAG_IN_THIS_FILE/
128
585
  end
129
586
  end
130
- describe 'request' do
131
- describe 'get with block' do
132
- it 'works with filter_block: true' do
133
- @client.request(:get, @srv.u('hello')) do |str|
134
- str.should eq 'hello'
135
- end
136
- end
137
- it 'works with filter_block: false' do
138
- @client.request(:get, @srv.u('hello'), filter_block: false) do |req, str|
139
- req.class.name.should eq 'HTTP::Message'
140
- str.should eq 'hello'
141
- end
587
+
588
+ it "post with file without size" do
589
+ STDOUT.sync = true
590
+ File.open(__FILE__) do |file|
591
+ def file.size
592
+ raise SystemCallError.new("Unknown Error (20047)")
142
593
  end
594
+
595
+ @client.post(@srv.u("servlet"), 1 => 2, 3 => file)
143
596
  end
144
597
  end
145
- describe 'agent name' do
146
- it 'default' do
147
- str = ""
148
- @client.debug_dev = str
149
- @client.get(@srv.u)
150
- lines = str.split(/(?:\r?\n)+/)
151
- lines[0].should eq '= Request'
152
- lines[4].should eq "User-Agent: HTTPClient #{HTTPClient::VERSION}"
598
+
599
+ it "post with io" do
600
+ myio = StringIO.new("X".*(HTTP::Message::Body::DEFAULT_CHUNK_SIZE + 1))
601
+ def myio.read(*args)
602
+ @called ||= 0
603
+ @called = @called + 1
604
+ super
153
605
  end
154
-
155
- it 'custom' do
156
- client = HTTPClient.new(nil, "agent_name_foo")
157
- str = ""
158
- client.debug_dev = str
159
- client.get(@srv.u)
160
- lines = str.split(/(?:\r?\n)+/)
161
- lines[0].should eq '= Request'
162
- lines[4].should eq 'User-Agent: agent_name_foo'
606
+
607
+ def myio.called
608
+ @called
163
609
  end
610
+ @client.debug_dev = str = StringIO.new
611
+ res = @client.post(@srv.u("servlet"), 1 => 2, 3 => myio)
612
+ res.content.should match /\r\nContent-Disposition: form-data; name="1"\r\n/m
613
+ res.content.should match /\r\n2\r\n/m
614
+ res.content.should match /\r\nContent-Disposition: form-data; name="3"; filename=""\r\n/m
615
+ str.string.should match /\r\nContent-Length:/m
616
+ myio.called.should == 3
164
617
  end
165
-
166
- describe 'protocol versions' do
167
- it '0.9' do
168
- @client.protocol_version = 'HTTP/0.9'
169
- @client.debug_dev = str = ''
170
- @client.test_loopback_http_response << "hello\nworld\n"
171
- res = @client.get(@srv.u 'hello')
172
- res.http_version.should eq '0.9'
173
- res.status.should be_nil
174
- res.reason.should be_nil
175
- res.content.should eq "hello\nworld\n"
176
- lines = str.split(/(?:\r?\n)+/)
177
- lines[0].should eq "= Request"
178
- lines[2].should eq "! CONNECTION ESTABLISHED"
179
- lines[3].should eq "GET /hello HTTP/0.9"
180
- lines[7].should eq "Connection: close"
181
- lines[8].should eq "= Response"
182
- lines[9].should match /^hello$/
183
- lines[10].should match /^world$/
618
+
619
+ it "post with io nosize" do
620
+ myio = StringIO.new("4")
621
+ def myio.size
622
+ nil
184
623
  end
185
-
186
- it '1.0' do
187
- @client.protocol_version.should be_nil
188
- @client.protocol_version = 'HTTP/1.0'
189
- @client.protocol_version.should eq 'HTTP/1.0'
190
- str = ""
191
- @client.debug_dev = str
192
- @client.get(@srv.u 'hello')
193
- lines = str.split(/(?:\r?\n)+/)
194
- lines[0].should eq "= Request"
195
- lines[2].should eq "! CONNECTION ESTABLISHED"
196
- lines[3].should eq "GET /hello HTTP/1.0"
197
- lines[7].should eq "Connection: close"
198
- lines[8].should eq "= Response"
624
+ @client.debug_dev = str = StringIO.new
625
+ res = @client.post(@srv.u("servlet"), {1 => 2, 3 => myio})
626
+ res.content.should match /\r\nContent-Disposition: form-data; name="1"\r\n/m
627
+ res.content.should match /\r\n2\r\n/m
628
+ res.content.should match /\r\nContent-Disposition: form-data; name="3"; filename=""\r\n/m
629
+ res.content.should match /\r\n4\r\n/m
630
+ # TODO is this needed?
631
+ #res.content.should match /\r\nTransfer-Encoding: chunked\r\n/m
632
+ end
633
+
634
+ it "post async" do
635
+ param = {"1" => "2", "3" => "4"}
636
+ conn = @client.post_async(@srv.u("servlet"), param)
637
+ until conn.finished?
638
+ Thread.pass
199
639
  end
200
-
201
- it '1.1' do
202
- @client.protocol_version.should be_nil
203
- str = ""
204
- @client.debug_dev = str
205
- @client.get(@srv.u)
206
- lines = str.split(/(?:\r?\n)+/)
207
- lines[0].should eq "= Request"
208
- lines[2].should eq "! CONNECTION ESTABLISHED"
209
- lines[3].should eq "GET / HTTP/1.1"
210
- lines[7].should eq "Host: localhost:#{@srv.port}"
211
- @client.protocol_version = 'HTTP/1.1'
212
- @client.protocol_version.should eq 'HTTP/1.1'
213
- str = ""
214
- @client.debug_dev = str
215
- @client.get(@srv.u)
216
- lines = str.split(/(?:\r?\n)+/)
217
- lines[0].should eq "= Request"
218
- lines[2].should eq "! CONNECTION ESTABLISHED"
219
- lines[3].should eq "GET / HTTP/1.1"
220
- @client.protocol_version = 'HTTP/1.0'
221
- str = ""
222
- @client.debug_dev = str
223
- @client.get(@srv.u)
224
- lines = str.split(/(?:\r?\n)+/)
225
- lines[0].should eq "= Request"
226
- lines[2].should eq "! CONNECTION ESTABLISHED"
227
- lines[3].should eq "GET / HTTP/1.0"
640
+ res = conn.pop
641
+ params(res.header["x-query"][0]).should == param
642
+ end
643
+
644
+ it "post with block" do
645
+ called = false
646
+ res = @client.post(@srv.u("servlet")) do |str|
647
+ str.should == "post,"
648
+ called = true
228
649
  end
650
+ called.should be_true
651
+ res.content.should be_nil
652
+ called = false
653
+ param = [["1", "2"], ["3", "4"]]
654
+ res = @client.post(@srv.u("servlet"), param) do |str|
655
+ str.should == "post,1=2&3=4"
656
+ called = true
657
+ end
658
+ called.should be_true
659
+ res.header["x-query"][0].should == "1=2&3=4"
660
+ res.content.should be_nil
229
661
  end
230
-
231
- describe 'accept' do
232
- it '*/* by default' do
233
- str = ""
234
- @client.debug_dev = str
235
- @client.get(@srv.u)
236
- lines = str.split(/(?:\r?\n)+/)
237
- lines[5].should eq "Accept: */*"
662
+
663
+ it "post with custom multipart" do
664
+ ext = {"content-type" => "multipart/form-data"}
665
+ @client.post(@srv.u("servlet")).content[0, 4].should == "post"
666
+ body = [{ 'Content-Disposition' => 'form-data; name="1"', :content => "2"},
667
+ { 'Content-Disposition' => 'form-data; name="3"', :content => "4"}]
668
+ res = @client.post(@srv.u("servlet"), body, ext)
669
+ res.content.should match /Content-Disposition: form-data; name="1"/
670
+ res.content.should match /Content-Disposition: form-data; name="3"/
671
+ ext = {"content-type" => "multipart/form-data; boundary=hello"}
672
+ @client.post(@srv.u("servlet")).content[0, 4].should == "post"
673
+ res = @client.post(@srv.u("servlet"), body, ext)
674
+ res.content.should match /Content-Disposition: form-data; name="1"/
675
+ res.content.should match /Content-Disposition: form-data; name="3"/
676
+ res.content.should == "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"
677
+ end
678
+
679
+ it "post with custom multipart and file" do
680
+ STDOUT.sync = true
681
+ File.open(__FILE__) do |file|
682
+ ext = {"Content-Type" => "multipart/alternative"}
683
+ body = [{"Content-Type" => "text/plain", :content => "this is only a test"}, {"Content-Type" => "application/x-ruby", :content => file}]
684
+ res = @client.post(@srv.u("servlet"), body, ext)
685
+ res.content.should match /^Content-Type: text\/plain\r\n/m
686
+ res.content.should match /^this is only a test\r\n/m
687
+ res.content.should match /^Content-Type: application\/x-ruby\r\n/m
688
+ res.content.should match /FIND_TAG_IN_THIS_FILE/
238
689
  end
239
-
240
- it 'sets properly' do
241
- str = ""
242
- @client.debug_dev = str
243
- @client.get(@srv.u, :header => {:Accept => 'text/html'})
244
- lines = str.split(/(?:\r?\n)+/)
245
- lines[4].should eq "Accept: text/html"
246
- lines.each do |line|
247
- line.should_not eq "Accept: */*"
248
- end
690
+ end
691
+
692
+ it "put" do
693
+ @client.put(@srv.u("servlet")).content.should == "put"
694
+ param = {"1" => "2", "3" => "4"}
695
+ @client.debug_dev = str = ""
696
+ res = @client.put(@srv.u("servlet"), param)
697
+ params(res.header["x-query"][0]).should == param
698
+ str.split(/\r?\n/)[5].should == "Content-Type: application/x-www-form-urlencoded"
699
+ end
700
+
701
+ it "put bytesize" do
702
+ res = @client.put(@srv.u("servlet"), "txt" => "あいうえお")
703
+ res.header["x-query"][0].should == "txt=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A"
704
+ res.header["x-size"][0].should == "15"
705
+ end
706
+
707
+ it "put async" do
708
+ param = {"1" => "2", "3" => "4"}
709
+ conn = @client.put_async(@srv.u("servlet"), param)
710
+ until conn.finished?
711
+ Thread.pass
249
712
  end
713
+ res = conn.pop
714
+ params(res.header["x-query"][0]).should == param
250
715
  end
251
-
252
- describe 'POST' do
253
- describe '#post_content' do
254
- it 'works' do
255
- @client.post_content(@srv.u('hello')).should eq 'hello'
256
- @client.post_content(@srv.u("redirect1")).should eq 'hello'
257
- @client.post_content(@srv.u("redirect2")).should eq 'hello'
258
- end
716
+
717
+ it "patch" do
718
+ @client.patch(@srv.u("servlet")).content.should == "patch"
719
+ param = {"1" => "2", "3" => "4"}
720
+ @client.debug_dev = str = ""
721
+ res = @client.patch(@srv.u("servlet"), param)
722
+ params(res.header["x-query"][0]).should == param
723
+ str.split(/\r?\n/)[5].should == "Content-Type: application/x-www-form-urlencoded"
724
+ end
725
+
726
+ it "patch async" do
727
+ param = {"1" => "2", "3" => "4"}
728
+ conn = @client.patch_async(@srv.u("servlet"), param)
729
+ until conn.finished?
730
+ Thread.pass
259
731
  end
260
-
261
- it 'redirect callback' do
262
- called = false
263
- @client.redirect_uri_callback = lambda { |uri, res|
264
- newuri = res.header['location'][0]
265
- called = true
266
- newuri
267
- }
268
- @client.post_content(@srv.u("relative_redirect")).should eq 'hello'
269
- called.should be_true
732
+ res = conn.pop
733
+ params(res.header["x-query"][0]).should == param
734
+ end
735
+
736
+ it "delete" do
737
+ @client.delete(@srv.u("servlet")).content.should == "delete"
738
+ end
739
+
740
+ it "delete with body" do
741
+ param = {'1'=>'2', '3'=>'4'}
742
+ @client.debug_dev = str = ''
743
+ @client.delete(@srv.u('servlet'), param).content.should eq "delete"
744
+ HTTP::Message.parse(str.split(/\r?\n\r?\n/)[2]).should eq({'1' => ['2'], '3' => ['4']})
745
+ end
746
+
747
+ it "delete async" do
748
+ conn = @client.delete_async(@srv.u("servlet"))
749
+ until conn.finished?
750
+ Thread.pass
270
751
  end
271
-
272
- it 'errors' do
273
- expect {
274
- @client.post_content(@srv.u 'notfound')
275
- }.to raise_error(HTTPClient::BadResponseError)
276
-
277
- expect {
278
- @client.post_content(@srv.u 'redirect_self')
279
- }.to raise_error(HTTPClient::BadResponseError)
752
+ res = conn.pop
753
+ res.content.read.should == "delete"
754
+ end
755
+
756
+ it "options" do
757
+ @client.options(@srv.u("servlet")).content.should == "options"
758
+ end
759
+
760
+ it "options async" do
761
+ conn = @client.options_async(@srv.u("servlet"))
762
+ until conn.finished?
763
+ Thread.pass
280
764
  end
765
+ res = conn.pop
766
+ res.content.read.should == "options"
767
+ end
768
+
769
+ it "propfind" do
770
+ @client.propfind(@srv.u("servlet")).content.should == "propfind"
771
+ end
772
+
773
+ it "propfind async" do
774
+ conn = @client.propfind_async(@srv.u("servlet"))
775
+ until conn.finished?
776
+ Thread.pass
777
+ end
778
+ res = conn.pop
779
+ res.content.read.should == "propfind"
780
+ end
781
+
782
+ it "proppatch" do
783
+ @client.proppatch(@srv.u("servlet")).content.should == "proppatch"
784
+ param = {"1" => "2", "3" => "4"}
785
+ res = @client.proppatch(@srv.u("servlet"), param)
786
+ res.content.should == "proppatch"
787
+ params(res.header["x-query"][0]).should == param
788
+ end
789
+
790
+ it "proppatch async" do
791
+ param = {"1" => "2", "3" => "4"}
792
+ conn = @client.proppatch_async(@srv.u("servlet"), param)
793
+ until conn.finished?
794
+ Thread.pass
795
+ end
796
+ res = conn.pop
797
+ res.content.read.should == "proppatch"
798
+ params(res.header["x-query"][0]).should == param
799
+ end
800
+
801
+ it "trace" do
802
+ @client.trace(@srv.u("servlet")).content.should == "trace"
803
+ param = {"1" => "2", "3" => "4"}
804
+ res = @client.trace(@srv.u("servlet"), param)
805
+ params(res.header["x-query"][0]).should == param
806
+ end
807
+
808
+ it "trace async" do
809
+ param = {"1" => "2", "3" => "4"}
810
+ conn = @client.trace_async(@srv.u("servlet"), param)
811
+ until conn.finished?
812
+ Thread.pass
813
+ end
814
+ res = conn.pop
815
+ params(res.header["x-query"][0]).should == param
816
+ end
817
+
818
+ it "chunked" do
819
+ @client.get_content(@srv.u("chunked"), "msg" => "chunked").should == "chunked"
820
+ @client.get_content(@srv.u("chunked"), "msg" => "あいうえお").should == "あいうえお"
821
+ end
822
+
823
+ it "chunked empty" do
824
+ @client.get_content(@srv.u("chunked"), "msg" => "").should == ""
825
+ end
826
+
827
+ it "get query" do
828
+ check_query_get({1=>2}).should eq({'1'=>'2'})
829
+ check_query_get({"a"=>"A", "B"=>"b"}).should eq({'a'=>'A', 'B'=>'b'})
830
+ check_query_get({"&"=>"&"}).should eq({'&'=>'&'})
831
+ check_query_get({"= "=>" =+"}).should eq({'= '=>' =+'})
832
+ ['=', '&'].sort.should eq check_query_get([["=", "="], ["=", "&"]])['='].to_ary.sort
281
833
 
834
+ {'123'=>'45'}.should eq check_query_get('123=45')
835
+ {'12 3'=>'45', ' '=>' '}.should eq check_query_get('12+3=45&+=+')
836
+ {}.should eq check_query_get('')
837
+ {'1'=>'2'}.should eq check_query_get({1=>StringIO.new('2')})
838
+ {'1'=>'2', '3'=>'4'}.should eq check_query_get(StringIO.new('3=4&1=2'))
282
839
 
283
- describe 'string io' do
284
- it do
285
- post_body = StringIO.new("1234567890")
286
- @client.post_content(@srv.u("servlet"), post_body).should eq 'post,1234567890'
287
-
288
- # all browsers use GET for 302
289
- post_body = StringIO.new("1234567890")
290
- @client.post_content(@srv.u("servlet_413"), post_body).should eq '1234567890'
840
+ hash = check_query_get({"a"=>["A","a"], "B"=>"b"})
841
+ {'a'=>'A', 'B'=>'b'}.should eq hash
842
+ ['A','a'].should eq hash['a'].to_ary
291
843
 
292
- @client.get_content(@srv.u("servlet_redirect_413")).should eq ''
844
+ hash = check_query_get({"a"=>WEBrick::HTTPUtils::FormData.new("A","a"), "B"=>"b"})
845
+ {'a'=>'A', 'B'=>'b'}.should eq hash
846
+ ['A','a'].should eq hash['a'].to_ary
293
847
 
294
- post_body = StringIO.new("1234567890")
295
- @client.post_content(@srv.u("servlet_redirect_413"), post_body).should eq ''
848
+ hash = check_query_get({"a"=>[StringIO.new("A"),StringIO.new("a")], "B"=>StringIO.new("b")})
849
+ {'a'=>'A', 'B'=>'b'}.should eq hash
850
+ ['A','a'].should eq hash['a'].to_ary
851
+ end
852
+
853
+ it "post body" do
854
+ check_query_post(1 => 2).should == {"1" => "2"}
855
+ check_query_post("a" => "A", "B" => "b").should == {"a" => "A", "B" => "b"}
856
+ check_query_post("&" => "&").should == {"&" => "&"}
857
+ check_query_post("= " => " =+").should == {"= " => " =+"}
858
+ check_query_post([["=", "="], ["=", "&"]])["="].to_ary.sort.should == ["=", "&"].sort
859
+ check_query_post("123=45").should == {"123" => "45"}
860
+ check_query_post("12+3=45&+=+").should == {"12 3" => "45", " " => " "}
861
+ check_query_post("").should == {}
862
+ post_body = StringIO.new("foo=bar&foo=baz")
863
+ check_query_post(post_body)["foo"].to_ary.sort.should == ["bar", "baz"]
864
+ end
865
+
866
+ it "extra headers" do
867
+ str = ""
868
+ @client.debug_dev = str
869
+ @client.head(@srv.u, nil, "ABC" => "DEF")
870
+ lines = str.split(/(?:\r?\n)+/)
871
+ lines[0].should == "= Request"
872
+ lines[4].should match "ABC: DEF"
873
+ str = ""
874
+ @client.debug_dev = str
875
+ @client.get(@srv.u, nil, [["ABC", "DEF"], ["ABC", "DEF"]])
876
+ lines = str.split(/(?:\r?\n)+/)
877
+ lines[0].should == "= Request"
878
+ lines[4].should match "ABC: DEF"
879
+ lines[5].should match "ABC: DEF"
880
+ end
881
+
882
+ it "http custom date header" do
883
+ @client.debug_dev = str = ""
884
+ res = @client.get(@srv.u("hello"), :header => {"Date" => "foo"})
885
+ lines = str.split(/(?:\r?\n)+/)
886
+ lines[4].should == "Date: foo"
887
+ end
888
+
889
+ it "timeout" do
890
+ @client.connect_timeout.should == 60
891
+ @client.send_timeout.should == 120
892
+ @client.receive_timeout.should == 60
893
+ @client.connect_timeout = 1
894
+ @client.send_timeout = 2
895
+ @client.receive_timeout = 3
896
+ @client.connect_timeout.should == 1
897
+ @client.send_timeout.should == 2
898
+ @client.receive_timeout.should == 3
899
+ end
900
+
901
+ it "connect timeout" do
902
+
903
+ end
904
+
905
+ it "send timeout" do
906
+
907
+ end
908
+
909
+ it "receive timeout" do
910
+ @client.get_content(@srv.u("sleep?sec=2")).should == "hello"
911
+ @client.receive_timeout = 1
912
+ @client.get_content(@srv.u("sleep?sec=0")).should == "hello"
913
+
914
+ expect {
915
+ @client.get_content(@srv.u("sleep?sec=2"))
916
+ }.to raise_error(HTTPClient::ReceiveTimeoutError)
917
+ @client.receive_timeout = 3
918
+ @client.get_content(@srv.u("sleep?sec=2")).should == "hello"
919
+ end
920
+
921
+ it "receive timeout post" do
922
+ @client.post(@srv.u("sleep"), :sec => 2).content.should == "hello"
923
+ @client.receive_timeout = 1
924
+ @client.post(@srv.u("sleep"), :sec => 0).content.should == "hello"
925
+
926
+ expect {
927
+ @client.post(@srv.u("sleep"), :sec => 2)\
928
+ }.to raise_error(HTTPClient::ReceiveTimeoutError)
296
929
 
297
- post_body = StringIO.new("1234567890")
298
- @client.post_content(@srv.u("servlet_temporary_redirect"), post_body).should eq 'post,1234567890'
930
+ @client.receive_timeout = 3
931
+ @client.post(@srv.u("sleep"), :sec => 2).content.should == "hello"
932
+ end
933
+
934
+ it "reset" do
935
+ url = @srv.u("servlet")
936
+ 5.times do
937
+ @client.get(url)
938
+ @client.reset(url)
939
+ end
940
+ end
941
+
942
+ it "reset all" do
943
+ 5.times do
944
+ @client.get(@srv.u("servlet"))
945
+ @client.reset_all
946
+ end
947
+ end
948
+
949
+ it "cookies" do
950
+ cookiefile = File.join(File.dirname(File.expand_path(__FILE__)), "test_cookies_file")
951
+ File.open(cookiefile, "wb") do |f|
952
+ f << "http://rubyforge.org/account/login.php session_ser LjEwMy45Ni40Ni0q%2A-fa0537de8cc31 2000000000 .rubyforge.org / 13
953
+ "
954
+ end
955
+
956
+ @client.set_cookie_store(cookiefile)
957
+ cookie = @client.cookie_manager.cookies.first
958
+ url = cookie.url
959
+ cookie.domain_match(url.host, cookie.domain).should be_true
960
+ @client.reset_all
961
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK
962
+ Set-Cookie: foo=bar; expires=#{Time.at(1924873200).gmtime.httpdate}
299
963
 
300
- post_body = StringIO.new("1234567890")
301
- @client.post_content(@srv.u("servlet_see_other"), post_body).should eq 'get'
964
+ OK"
965
+ @client.get_content("http://rubyforge.org/account/login.php")
966
+ @client.save_cookie_store
967
+ str = File.read(cookiefile)
968
+ str.should match /http:\/\/rubyforge.org\/account\/login.php\tfoo\tbar\t1924873200\trubyforge.org\t\/account\t1/
969
+ File.unlink(cookiefile)
970
+ end
971
+
972
+ it "eof error length" do
973
+ io = StringIO.new('')
974
+ def io.gets(*arg)
975
+ @buf ||= ["HTTP/1.0 200 OK\n", "content-length: 123\n", "\n"]
976
+ @buf.shift
977
+ end
978
+ def io.readpartial(size, buf)
979
+ @second ||= false
980
+ if !@second
981
+ @second = '1st'
982
+ buf << "abc"
983
+ buf
984
+ elsif @second == '1st'
985
+ @second = '2nd'
986
+ raise EOFError.new
987
+ else
988
+ raise Exception.new
302
989
  end
303
-
304
- it 'doesnt rewind' do
305
- post_body = StringIO.new("1234567890")
306
- post_body.read(5)
307
- @client.post_content(@srv.u("servlet_temporary_redirect"), post_body).should eq 'post,67890'
990
+ end
991
+ def io.eof?
992
+ true
993
+ end
994
+ @client.test_loopback_http_response << io
995
+ @client.get('http://foo/bar')
996
+ end
997
+
998
+ it "eof error rest" do
999
+ io = StringIO.new('')
1000
+ def io.gets(*arg)
1001
+ @buf ||= ["HTTP/1.0 200 OK\n", "\n"]
1002
+ @buf.shift
1003
+ end
1004
+ def io.readpartial(size, buf)
1005
+ @second ||= false
1006
+ if !@second
1007
+ @second = '1st'
1008
+ buf << "abc"
1009
+ buf
1010
+ elsif @second == '1st'
1011
+ @second = '2nd'
1012
+ raise EOFError.new
1013
+ else
1014
+ raise Exception.new
308
1015
  end
309
1016
  end
1017
+ def io.eof?
1018
+ true
1019
+ end
1020
+ @client.test_loopback_http_response << io
1021
+ @client.get('http://foo/bar')
1022
+ end
1023
+
1024
+ it "connection" do
1025
+ c = HTTPClient::Connection.new
1026
+ c.finished?.should be_true
1027
+ c.join.should be_nil
1028
+ end
1029
+
1030
+ it "site" do
1031
+ site = HTTPClient::Site.new
1032
+ site.scheme.should == "tcp"
1033
+ site.host.should == "0.0.0.0"
1034
+ site.port.should == 0
1035
+ site.addr.should == "tcp://0.0.0.0:0"
1036
+ site.to_s.should == "tcp://0.0.0.0:0"
1037
+
1038
+ site.inspect
1039
+ site = HTTPClient::Site.new(urify("http://localhost:12345/foo"))
1040
+ site.scheme.should == "http"
1041
+ site.host.should == "localhost"
1042
+ site.port.should == 12345
1043
+ site.addr.should == "http://localhost:12345"
1044
+ site.to_s.should == "http://localhost:12345"
1045
+
1046
+ site.inspect
1047
+ site1 = HTTPClient::Site.new(urify("http://localhost:12341/"))
1048
+ site2 = HTTPClient::Site.new(urify("http://localhost:12342/"))
1049
+ site3 = HTTPClient::Site.new(urify("http://localhost:12342/"))
1050
+ site1.should_not == site2
1051
+ h = {site1 => "site1", site2 => "site2"}
1052
+ h[site3] = "site3"
1053
+ h[site1].should == "site1"
1054
+ h[site2].should == "site3"
1055
+ end
1056
+
1057
+ it "http header" do
1058
+ res = @client.get(@srv.u("hello"))
1059
+ res.contenttype.should == "text/html"
1060
+ res.header.get(nil).size.should == 5
1061
+ res.header.delete("connection")
1062
+ res.header.get(nil).size.should == 4
1063
+ res.header["foo"] = "bar"
1064
+ res.header["foo"].should == ["bar"]
1065
+ res.header.get("foo").should == [["foo", "bar"]]
1066
+ res.header["foo"] = ["bar", "bar2"]
1067
+ res.header.get("foo").should == [["foo", "bar"], ["foo", "bar2"]]
1068
+ end
1069
+
1070
+ it "session manager" do
1071
+ mgr = HTTPClient::SessionManager.new(@client)
1072
+ (mgr.instance_eval do
1073
+ @proxy
1074
+ end).should be_nil
1075
+ mgr.debug_dev.should be_nil
1076
+ @client.debug_dev = Object.new
1077
+ @client.proxy = "http://myproxy:12345"
1078
+ mgr = HTTPClient::SessionManager.new(@client)
1079
+ mgr.instance_eval do
1080
+ @proxy
1081
+ end.to_s.should == "http://myproxy:12345"
1082
+ mgr.debug_dev.should == @client.debug_dev
1083
+ end
1084
+
1085
+ it "socket local" do
1086
+ @client.socket_local.host = '127.0.0.1'
1087
+ @client.get_content(@srv.u('hello')).should == 'hello'
1088
+ @client.reset_all
1089
+ @client.socket_local.port = @srv.port
1090
+ begin
1091
+ @client.get_content(@srv.u('hello'))
1092
+ rescue Errno::EADDRINUSE, SocketError
1093
+ end
1094
+ end
1095
+
1096
+ it "body param order" do
1097
+ ary = ("b".."d").map do |k|
1098
+ ["key2", k]
1099
+ end << ["key1", "a"] << ["key3", "z"]
1100
+ HTTP::Message.escape_query(ary).should == "key2=b&key2=c&key2=d&key1=a&key3=z"
1101
+ end
1102
+ it 'charset' do
1103
+ body = @client.get(@srv.u("charset")).body
1104
+ body.encoding.should == Encoding::EUC_JP
1105
+ body.should == "あいうえお".encode(Encoding::EUC_JP)
1106
+ end
1107
+ it 'continue' do
1108
+ @client.debug_dev = str = ''
1109
+ res = @client.get(@srv.u('continue'), :header => {:Expect => '100-continue'})
1110
+ res.status.should eq 200
1111
+ res.body.should eq 'done!'
1112
+ str.should match /Expect: 100-continue/
310
1113
  end
311
1114
 
312
- describe 'util' do
313
- it '#urify' do
314
- urify(nil).should be_nil
315
- uri = 'http://foo'
316
- # urify(uri).class.name.should eq 'HTTPClient::Util::AddressableURI'
317
- urify(uri).should eq urify(uri)
318
- urify(uri).to_s.should eq uri
319
- urify(urify(uri)).should eq urify(uri)
1115
+ it 'ipv6' do
1116
+ server = TCPServer.open('::1', 0) rescue return # Skip if IPv6 is unavailable.
1117
+ server_thread = Thread.new {
1118
+ Thread.abort_on_exception = true
1119
+ sock = server.accept
1120
+ while line = sock.gets
1121
+ break if line.chomp.empty?
1122
+ end
1123
+ sock.write("HTTP/1.1 200 OK\r\n")
1124
+ sock.write("Content-Length: 5\r\n")
1125
+ sock.write("\r\n")
1126
+ sock.write("12345")
1127
+ sock.close
1128
+ }
1129
+ uri = "http://[::1]:#{server.addr[1]}/"
1130
+ begin
1131
+ @client.get(uri).body.should eq '12345'
1132
+ ensure
1133
+ server.close
1134
+ server_thread.kill
1135
+ server_thread.join
320
1136
  end
321
1137
  end
322
1138
  end