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.
- checksums.yaml +4 -4
- data/Gemfile.lock +31 -2
- data/httpclient.gemspec +2 -0
- data/lib/httpclient/session.rb +14 -11
- data/lib/httpclient/version.rb +1 -1
- data/lib/httpclient.rb +8 -0
- data/spec/basic_spec.rb +326 -0
- data/spec/hexdump_spec.rb +11 -0
- data/spec/httpclient_spec.rb +1074 -258
- data/spec/spec_helper.rb +1 -0
- data/spec/support/base_server.rb +2 -2
- data/spec/support/ht_helpers.rb +24 -1
- data/spec/support/test_servlet.rb +5 -0
- data/test/test_httpclient.rb +1 -5
- metadata +34 -4
- data/test/test_hexdump.rb +0 -14
data/spec/httpclient_spec.rb
CHANGED
@@ -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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
30
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
49
|
-
|
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
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
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
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
105
|
-
|
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
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
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
|
-
|
113
|
-
|
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
|
-
|
116
|
-
|
117
|
-
|
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
|
-
|
120
|
-
|
434
|
+
"
|
435
|
+
@client.test_loopback_http_response << "HTTP/1.0 200 OK
|
121
436
|
|
122
|
-
|
123
|
-
|
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
|
-
|
126
|
-
|
127
|
-
|
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
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
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
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
@
|
150
|
-
|
151
|
-
|
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
|
-
|
156
|
-
|
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
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
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
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
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
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
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
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
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
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
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
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
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
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
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
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
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
|
-
|
284
|
-
|
285
|
-
|
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
|
-
|
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
|
-
|
295
|
-
|
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
|
-
|
298
|
-
|
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
|
-
|
301
|
-
|
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
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
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
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
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
|