glebtv-httpclient 3.2.4 → 3.2.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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