httpclient 2.3.0.1 → 2.8.3
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 +7 -0
- data/README.md +85 -0
- data/bin/httpclient +18 -6
- data/bin/jsonclient +85 -0
- data/lib/http-access2.rb +1 -1
- data/lib/httpclient.rb +262 -88
- data/lib/httpclient/auth.rb +269 -244
- data/lib/httpclient/cacert.pem +3952 -0
- data/lib/httpclient/cacert1024.pem +3866 -0
- data/lib/httpclient/connection.rb +1 -1
- data/lib/httpclient/cookie.rb +161 -514
- data/lib/httpclient/http.rb +57 -21
- data/lib/httpclient/include_client.rb +2 -0
- data/lib/httpclient/jruby_ssl_socket.rb +588 -0
- data/lib/httpclient/session.rb +259 -317
- data/lib/httpclient/ssl_config.rb +141 -188
- data/lib/httpclient/ssl_socket.rb +150 -0
- data/lib/httpclient/timeout.rb +1 -1
- data/lib/httpclient/util.rb +62 -1
- data/lib/httpclient/version.rb +1 -1
- data/lib/httpclient/webagent-cookie.rb +459 -0
- data/lib/jsonclient.rb +63 -0
- data/lib/oauthclient.rb +2 -1
- data/sample/jsonclient.rb +67 -0
- data/sample/oauth_twitter.rb +4 -4
- data/test/{ca-chain.cert → ca-chain.pem} +0 -0
- data/test/client-pass.key +18 -0
- data/test/helper.rb +10 -8
- data/test/jruby_ssl_socket/test_pemutils.rb +32 -0
- data/test/test_auth.rb +175 -4
- data/test/test_cookie.rb +147 -243
- data/test/test_http-access2.rb +17 -16
- data/test/test_httpclient.rb +458 -77
- data/test/test_jsonclient.rb +80 -0
- data/test/test_ssl.rb +341 -17
- data/test/test_webagent-cookie.rb +465 -0
- metadata +57 -55
- data/README.txt +0 -721
- data/lib/httpclient/cacert.p7s +0 -1858
- data/lib/httpclient/cacert_sha1.p7s +0 -1858
- data/sample/oauth_salesforce_10.rb +0 -63
data/test/test_http-access2.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
1
2
|
require 'http-access2'
|
2
3
|
require File.expand_path('helper', File.dirname(__FILE__))
|
4
|
+
require 'tempfile'
|
3
5
|
|
4
6
|
|
5
7
|
module HTTPAccess2
|
@@ -47,7 +49,7 @@ class TestClient < Test::Unit::TestCase
|
|
47
49
|
@client.get(serverurl)
|
48
50
|
lines = str.split(/(?:\r?\n)+/)
|
49
51
|
assert_equal("= Request", lines[0])
|
50
|
-
assert_match(/^From: from_bar/, lines[
|
52
|
+
assert_match(/^From: from_bar/, lines[5])
|
51
53
|
end
|
52
54
|
|
53
55
|
def test_debug_dev
|
@@ -81,8 +83,8 @@ class TestClient < Test::Unit::TestCase
|
|
81
83
|
assert_equal("= Request", lines[0])
|
82
84
|
assert_equal("! CONNECTION ESTABLISHED", lines[2])
|
83
85
|
assert_equal("GET /hello HTTP/1.0", lines[3])
|
84
|
-
assert_equal("Connection: close", lines[
|
85
|
-
assert_equal("= Response", lines[
|
86
|
+
assert_equal("Connection: close", lines[7])
|
87
|
+
assert_equal("= Response", lines[8])
|
86
88
|
end
|
87
89
|
|
88
90
|
def test_protocol_version_http11
|
@@ -93,7 +95,7 @@ class TestClient < Test::Unit::TestCase
|
|
93
95
|
assert_equal("= Request", lines[0])
|
94
96
|
assert_equal("! CONNECTION ESTABLISHED", lines[2])
|
95
97
|
assert_equal("GET / HTTP/1.1", lines[3])
|
96
|
-
assert_equal("Host: localhost:#{serverport}", lines[
|
98
|
+
assert_equal("Host: localhost:#{serverport}", lines[7])
|
97
99
|
@client.protocol_version = 'HTTP/1.1'
|
98
100
|
str = ""
|
99
101
|
@client.debug_dev = str
|
@@ -116,9 +118,9 @@ class TestClient < Test::Unit::TestCase
|
|
116
118
|
setup_proxyserver
|
117
119
|
escape_noproxy do
|
118
120
|
begin
|
119
|
-
@client.proxy = "http
|
120
|
-
rescue
|
121
|
-
assert_match(/InvalidURIError/,
|
121
|
+
@client.proxy = "http://あ"
|
122
|
+
rescue => e
|
123
|
+
assert_match(/InvalidURIError/, e.class.to_s)
|
122
124
|
end
|
123
125
|
@client.proxy = ""
|
124
126
|
assert_nil(@client.proxy)
|
@@ -243,7 +245,7 @@ class TestClient < Test::Unit::TestCase
|
|
243
245
|
end
|
244
246
|
|
245
247
|
def test_post
|
246
|
-
assert_equal("post", @client.post(serverurl + 'servlet').content)
|
248
|
+
assert_equal("post", @client.post(serverurl + 'servlet', '').content)
|
247
249
|
param = {'1'=>'2', '3'=>'4'}
|
248
250
|
res = @client.get(serverurl + 'servlet', param)
|
249
251
|
assert_equal(param, params(res.header["x-query"][0]))
|
@@ -345,27 +347,26 @@ class TestClient < Test::Unit::TestCase
|
|
345
347
|
def test_receive_timeout
|
346
348
|
# this test takes 2 sec
|
347
349
|
assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=2'))
|
350
|
+
@client.reset_all
|
348
351
|
@client.receive_timeout = 1
|
349
352
|
assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=0'))
|
350
353
|
assert_raise(HTTPClient::ReceiveTimeoutError) do
|
351
354
|
@client.get_content(serverurl + 'sleep?sec=2')
|
352
355
|
end
|
356
|
+
@client.reset_all
|
353
357
|
@client.receive_timeout = 3
|
354
358
|
assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=2'))
|
355
359
|
end
|
356
360
|
|
357
361
|
def test_cookies
|
358
|
-
cookiefile =
|
359
|
-
'test_cookies_file')
|
362
|
+
cookiefile = Tempfile.new('test_cookies_file')
|
360
363
|
# from [ruby-talk:164079]
|
361
|
-
File.open(cookiefile, "wb") do |f|
|
362
|
-
f << "http://rubyforge.org//account/login.php session_ser LjEwMy45Ni40Ni0q%2A-fa0537de8cc31
|
364
|
+
File.open(cookiefile.path, "wb") do |f|
|
365
|
+
f << "http://rubyforge.org//account/login.php session_ser LjEwMy45Ni40Ni0q%2A-fa0537de8cc31 2131676286 .rubyforge.org / 13\n"
|
363
366
|
end
|
364
|
-
cm = WebAgent::CookieManager::new(cookiefile)
|
367
|
+
cm = WebAgent::CookieManager::new(cookiefile.path)
|
365
368
|
cm.load_cookies
|
366
|
-
|
367
|
-
url = cookie.url
|
368
|
-
assert(cookie.domain_match(url.host, cookie.domain))
|
369
|
+
assert_equal(1, cm.cookies.size)
|
369
370
|
end
|
370
371
|
|
371
372
|
private
|
data/test/test_httpclient.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
require File.expand_path('helper', File.dirname(__FILE__))
|
3
|
+
require 'tempfile'
|
3
4
|
|
4
5
|
|
5
6
|
class TestHTTPClient < Test::Unit::TestCase
|
@@ -44,7 +45,7 @@ class TestHTTPClient < Test::Unit::TestCase
|
|
44
45
|
@client.get(serverurl)
|
45
46
|
lines = str.split(/(?:\r?\n)+/)
|
46
47
|
assert_equal("= Request", lines[0])
|
47
|
-
assert_match(/^From: from_bar/, lines[
|
48
|
+
assert_match(/^From: from_bar/, lines[5])
|
48
49
|
end
|
49
50
|
|
50
51
|
def test_debug_dev
|
@@ -77,10 +78,10 @@ class TestHTTPClient < Test::Unit::TestCase
|
|
77
78
|
assert_equal("= Request", lines[0])
|
78
79
|
assert_equal("! CONNECTION ESTABLISHED", lines[2])
|
79
80
|
assert_equal("GET /hello HTTP/0.9", lines[3])
|
80
|
-
assert_equal("Connection: close", lines[
|
81
|
-
assert_equal("= Response", lines[
|
82
|
-
assert_match(/^hello$/, lines[
|
83
|
-
assert_match(/^world$/, lines[
|
81
|
+
assert_equal("Connection: close", lines[7])
|
82
|
+
assert_equal("= Response", lines[8])
|
83
|
+
assert_match(/^hello$/, lines[9])
|
84
|
+
assert_match(/^world$/, lines[10])
|
84
85
|
end
|
85
86
|
|
86
87
|
def test_protocol_version_http10
|
@@ -94,8 +95,8 @@ class TestHTTPClient < Test::Unit::TestCase
|
|
94
95
|
assert_equal("= Request", lines[0])
|
95
96
|
assert_equal("! CONNECTION ESTABLISHED", lines[2])
|
96
97
|
assert_equal("GET /hello HTTP/1.0", lines[3])
|
97
|
-
assert_equal("Connection: close", lines[
|
98
|
-
assert_equal("= Response", lines[
|
98
|
+
assert_equal("Connection: close", lines[7])
|
99
|
+
assert_equal("= Response", lines[8])
|
99
100
|
end
|
100
101
|
|
101
102
|
def test_header_accept_by_default
|
@@ -103,7 +104,7 @@ class TestHTTPClient < Test::Unit::TestCase
|
|
103
104
|
@client.debug_dev = str
|
104
105
|
@client.get(serverurl)
|
105
106
|
lines = str.split(/(?:\r?\n)+/)
|
106
|
-
assert_equal("Accept: */*", lines[
|
107
|
+
assert_equal("Accept: */*", lines[5])
|
107
108
|
end
|
108
109
|
|
109
110
|
def test_header_accept
|
@@ -114,6 +115,14 @@ class TestHTTPClient < Test::Unit::TestCase
|
|
114
115
|
assert_equal("Accept: text/html", lines[4])
|
115
116
|
end
|
116
117
|
|
118
|
+
def test_header_symbol
|
119
|
+
str = ""
|
120
|
+
@client.debug_dev = str
|
121
|
+
@client.post(serverurl + 'servlet', :header => {:'Content-Type' => 'application/json'}, :body => 'hello')
|
122
|
+
lines = str.split(/(?:\r?\n)+/).grep(/^Content-Type/)
|
123
|
+
assert_equal(2, lines.size) # 1 for both request and response
|
124
|
+
end
|
125
|
+
|
117
126
|
def test_host_given
|
118
127
|
str = ""
|
119
128
|
@client.debug_dev = str
|
@@ -122,7 +131,7 @@ class TestHTTPClient < Test::Unit::TestCase
|
|
122
131
|
assert_equal("= Request", lines[0])
|
123
132
|
assert_equal("! CONNECTION ESTABLISHED", lines[2])
|
124
133
|
assert_equal("GET / HTTP/1.1", lines[3])
|
125
|
-
assert_equal("Host: localhost:#{serverport}", lines[
|
134
|
+
assert_equal("Host: localhost:#{serverport}", lines[7])
|
126
135
|
#
|
127
136
|
@client.reset_all
|
128
137
|
str = ""
|
@@ -137,12 +146,24 @@ class TestHTTPClient < Test::Unit::TestCase
|
|
137
146
|
|
138
147
|
def test_redirect_returns_not_modified
|
139
148
|
assert_nothing_raised do
|
140
|
-
timeout(2) do
|
149
|
+
::Timeout.timeout(2) do
|
141
150
|
@client.get(serverurl + 'status', {:status => 306}, {:follow_redirect => true})
|
142
151
|
end
|
143
152
|
end
|
144
153
|
end
|
145
154
|
|
155
|
+
class LocationRemoveFilter
|
156
|
+
def filter_request(req); end
|
157
|
+
def filter_response(req, res); res.header.delete('Location'); end
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_redirect_without_location_should_gracefully_fail
|
161
|
+
@client.request_filter << LocationRemoveFilter.new
|
162
|
+
assert_raises(HTTPClient::BadResponseError) do
|
163
|
+
@client.get(serverurl + 'redirect1', :follow_redirect => true)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
146
167
|
def test_protocol_version_http11
|
147
168
|
assert_equal(nil, @client.protocol_version)
|
148
169
|
str = ""
|
@@ -152,7 +173,7 @@ class TestHTTPClient < Test::Unit::TestCase
|
|
152
173
|
assert_equal("= Request", lines[0])
|
153
174
|
assert_equal("! CONNECTION ESTABLISHED", lines[2])
|
154
175
|
assert_equal("GET / HTTP/1.1", lines[3])
|
155
|
-
assert_equal("Host: localhost:#{serverport}", lines[
|
176
|
+
assert_equal("Host: localhost:#{serverport}", lines[7])
|
156
177
|
@client.protocol_version = 'HTTP/1.1'
|
157
178
|
assert_equal('HTTP/1.1', @client.protocol_version)
|
158
179
|
str = ""
|
@@ -176,9 +197,9 @@ class TestHTTPClient < Test::Unit::TestCase
|
|
176
197
|
setup_proxyserver
|
177
198
|
escape_noproxy do
|
178
199
|
begin
|
179
|
-
@client.proxy = "http
|
180
|
-
rescue
|
181
|
-
assert_match(/InvalidURIError/,
|
200
|
+
@client.proxy = "http://あ"
|
201
|
+
rescue => e
|
202
|
+
assert_match(/InvalidURIError/, e.class.to_s)
|
182
203
|
end
|
183
204
|
@client.proxy = ""
|
184
205
|
assert_nil(@client.proxy)
|
@@ -518,7 +539,7 @@ EOS
|
|
518
539
|
|
519
540
|
def test_no_content
|
520
541
|
assert_nothing_raised do
|
521
|
-
timeout(2) do
|
542
|
+
::Timeout.timeout(2) do
|
522
543
|
@client.get(serverurl + 'status', :status => 101)
|
523
544
|
@client.get(serverurl + 'status', :status => 204)
|
524
545
|
@client.get(serverurl + 'status', :status => 304)
|
@@ -554,19 +575,46 @@ EOS
|
|
554
575
|
assert(called)
|
555
576
|
end
|
556
577
|
|
578
|
+
def test_get_content_with_base_url
|
579
|
+
@client = HTTPClient.new(:base_url => serverurl)
|
580
|
+
assert_equal('hello', @client.get_content('/hello'))
|
581
|
+
assert_equal('hello', @client.get_content('/redirect1'))
|
582
|
+
assert_equal('hello', @client.get_content('/redirect2'))
|
583
|
+
@client.reset('/')
|
584
|
+
assert_raises(HTTPClient::BadResponseError) do
|
585
|
+
@client.get_content('/notfound')
|
586
|
+
end
|
587
|
+
assert_raises(HTTPClient::BadResponseError) do
|
588
|
+
@client.get_content('/redirect_self')
|
589
|
+
end
|
590
|
+
called = false
|
591
|
+
@client.redirect_uri_callback = lambda { |uri, res|
|
592
|
+
newuri = res.header['location'][0]
|
593
|
+
called = true
|
594
|
+
newuri
|
595
|
+
}
|
596
|
+
assert_equal('hello', @client.get_content('/relative_redirect'))
|
597
|
+
assert(called)
|
598
|
+
end
|
599
|
+
|
557
600
|
GZIP_CONTENT = "\x1f\x8b\x08\x00\x1a\x96\xe0\x4c\x00\x03\xcb\x48\xcd\xc9\xc9\x07\x00\x86\xa6\x10\x36\x05\x00\x00\x00"
|
558
601
|
DEFLATE_CONTENT = "\x78\x9c\xcb\x48\xcd\xc9\xc9\x07\x00\x06\x2c\x02\x15"
|
559
|
-
|
560
|
-
DEFLATE_CONTENT.
|
602
|
+
DEFLATE_NOHEADER_CONTENT = "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15"
|
603
|
+
[GZIP_CONTENT, DEFLATE_CONTENT, DEFLATE_NOHEADER_CONTENT].each do |content|
|
604
|
+
content.force_encoding('BINARY') if content.respond_to?(:force_encoding)
|
605
|
+
end
|
561
606
|
def test_get_gzipped_content
|
562
607
|
@client.transparent_gzip_decompression = false
|
563
608
|
content = @client.get_content(serverurl + 'compressed?enc=gzip')
|
564
609
|
assert_not_equal('hello', content)
|
565
610
|
assert_equal(GZIP_CONTENT, content)
|
566
611
|
@client.transparent_gzip_decompression = true
|
612
|
+
@client.reset_all
|
567
613
|
assert_equal('hello', @client.get_content(serverurl + 'compressed?enc=gzip'))
|
568
614
|
assert_equal('hello', @client.get_content(serverurl + 'compressed?enc=deflate'))
|
615
|
+
assert_equal('hello', @client.get_content(serverurl + 'compressed?enc=deflate_noheader'))
|
569
616
|
@client.transparent_gzip_decompression = false
|
617
|
+
@client.reset_all
|
570
618
|
end
|
571
619
|
|
572
620
|
def test_get_content_with_block
|
@@ -640,6 +688,32 @@ EOS
|
|
640
688
|
assert_nil(res.contenttype)
|
641
689
|
end
|
642
690
|
|
691
|
+
def test_get_with_base_url
|
692
|
+
@client = HTTPClient.new(:base_url => serverurl)
|
693
|
+
assert_equal("get", @client.get('/servlet').content)
|
694
|
+
param = {'1'=>'2', '3'=>'4'}
|
695
|
+
res = @client.get('/servlet', param)
|
696
|
+
assert_equal(param, params(res.header["x-query"][0]))
|
697
|
+
assert_nil(res.contenttype)
|
698
|
+
#
|
699
|
+
@client.base_url = serverurl[0...-1] + '/servlet'
|
700
|
+
url = '?5=6&7=8'
|
701
|
+
res = @client.get(url, param)
|
702
|
+
assert_equal(param.merge("5"=>"6", "7"=>"8"), params(res.header["x-query"][0]))
|
703
|
+
assert_nil(res.contenttype)
|
704
|
+
end
|
705
|
+
|
706
|
+
def test_get_with_default_header
|
707
|
+
@client = HTTPClient.new(:base_url => serverurl, :default_header => {'x-header' => 'custom'})
|
708
|
+
assert_equal('custom', @client.get('/servlet').headers['X-Header'])
|
709
|
+
@client.default_header = {'x-header' => 'custom2'}
|
710
|
+
assert_equal('custom2', @client.get('/servlet').headers['X-Header'])
|
711
|
+
# passing Hash overrides
|
712
|
+
assert_equal('custom3', @client.get('/servlet', :header => {'x-header' => 'custom3'}).headers['X-Header'])
|
713
|
+
# passing Array does not override
|
714
|
+
assert_equal('custom2, custom4', @client.get('/servlet', :header => [['x-header', 'custom4']]).headers['X-Header'])
|
715
|
+
end
|
716
|
+
|
643
717
|
def test_head_follow_redirect
|
644
718
|
expected = urify(serverurl + 'hello')
|
645
719
|
assert_equal(expected, @client.head(serverurl + 'hello', :follow_redirect => true).header.request_uri)
|
@@ -650,7 +724,17 @@ EOS
|
|
650
724
|
def test_get_follow_redirect
|
651
725
|
assert_equal('hello', @client.get(serverurl + 'hello', :follow_redirect => true).body)
|
652
726
|
assert_equal('hello', @client.get(serverurl + 'redirect1', :follow_redirect => true).body)
|
653
|
-
|
727
|
+
|
728
|
+
res = @client.get(serverurl + 'redirect2', :follow_redirect => true)
|
729
|
+
assert_equal('hello', res.body)
|
730
|
+
assert_equal("http://localhost:#{@serverport}/hello", res.header.request_uri.to_s)
|
731
|
+
assert_equal("http://localhost:#{@serverport}/redirect3", res.previous.header.request_uri.to_s)
|
732
|
+
assert_equal("http://localhost:#{@serverport}/redirect2", res.previous.previous.header.request_uri.to_s)
|
733
|
+
assert_equal(nil, res.previous.previous.previous)
|
734
|
+
end
|
735
|
+
|
736
|
+
def test_get_follow_redirect_with_query
|
737
|
+
assert_equal('hello?1=2&3=4', @client.get(serverurl + 'redirect1', :query => {1 => 2, 3 => 4}, :follow_redirect => true).body)
|
654
738
|
end
|
655
739
|
|
656
740
|
def test_get_async
|
@@ -661,12 +745,44 @@ EOS
|
|
661
745
|
assert_equal(param, params(res.header["x-query"][0]))
|
662
746
|
end
|
663
747
|
|
748
|
+
def test_get_async_with_base_url
|
749
|
+
param = {'1'=>'2', '3'=>'4'}
|
750
|
+
@client = HTTPClient.new(:base_url => serverurl)
|
751
|
+
|
752
|
+
# Use preconfigured :base_url
|
753
|
+
conn = @client.get_async('servlet', param)
|
754
|
+
Thread.pass while !conn.finished?
|
755
|
+
res = conn.pop
|
756
|
+
assert_equal(param, params(res.header["x-query"][0]))
|
757
|
+
# full URL still works
|
758
|
+
conn = @client.get_async(serverurl + 'servlet', param)
|
759
|
+
Thread.pass while !conn.finished?
|
760
|
+
res = conn.pop
|
761
|
+
assert_equal(param, params(res.header["x-query"][0]))
|
762
|
+
end
|
763
|
+
|
664
764
|
def test_get_async_for_largebody
|
665
765
|
conn = @client.get_async(serverurl + 'largebody')
|
666
766
|
res = conn.pop
|
667
767
|
assert_equal(1000*1000, res.content.read.length)
|
668
768
|
end
|
669
769
|
|
770
|
+
if RUBY_VERSION > "1.9"
|
771
|
+
def test_post_async_with_default_internal
|
772
|
+
original_encoding = Encoding.default_internal
|
773
|
+
Encoding.default_internal = Encoding::UTF_8
|
774
|
+
begin
|
775
|
+
post_body = StringIO.new("こんにちは")
|
776
|
+
conn = @client.post_async(serverurl + 'servlet', post_body)
|
777
|
+
Thread.pass while !conn.finished?
|
778
|
+
res = conn.pop
|
779
|
+
assert_equal 'post,こんにちは', res.content.read
|
780
|
+
ensure
|
781
|
+
Encoding.default_internal = original_encoding
|
782
|
+
end
|
783
|
+
end
|
784
|
+
end
|
785
|
+
|
670
786
|
def test_get_with_block
|
671
787
|
called = false
|
672
788
|
res = @client.get(serverurl + 'servlet') { |str|
|
@@ -678,23 +794,101 @@ EOS
|
|
678
794
|
assert_nil(res.content)
|
679
795
|
end
|
680
796
|
|
681
|
-
def
|
797
|
+
def test_get_with_block_arity_2
|
798
|
+
called = false
|
799
|
+
res = @client.get(serverurl + 'servlet') { |blk_res, str|
|
800
|
+
assert_equal(200, blk_res.status)
|
801
|
+
assert_equal('get', str)
|
802
|
+
called = true
|
803
|
+
}
|
804
|
+
assert(called)
|
805
|
+
# res does not have a content
|
806
|
+
assert_nil(res.content)
|
807
|
+
end
|
808
|
+
|
809
|
+
def test_get_with_block_and_redirects
|
810
|
+
called = false
|
811
|
+
res = @client.get(serverurl + 'servlet', :follow_redirect => true) { |str|
|
812
|
+
assert_equal('get', str)
|
813
|
+
called = true
|
814
|
+
}
|
815
|
+
assert(called)
|
816
|
+
# res does not have a content
|
817
|
+
assert_nil(res.content)
|
818
|
+
end
|
819
|
+
|
820
|
+
def test_get_with_block_arity_2_and_redirects
|
821
|
+
called = false
|
822
|
+
res = @client.get(serverurl + 'servlet', :follow_redirect => true) { |blk_res, str|
|
823
|
+
assert_equal(200, blk_res.status)
|
824
|
+
assert_equal('get', str)
|
825
|
+
called = true
|
826
|
+
}
|
827
|
+
assert(called)
|
828
|
+
# res does not have a content
|
829
|
+
assert_nil(res.content)
|
830
|
+
end
|
831
|
+
|
832
|
+
def test_get_with_block_string_recycle
|
682
833
|
@client.read_block_size = 2
|
683
834
|
body = []
|
684
|
-
|
835
|
+
_res = @client.get(serverurl + 'servlet') { |str|
|
685
836
|
body << str
|
686
837
|
}
|
687
838
|
assert_equal(2, body.size)
|
688
839
|
assert_equal("get", body.join) # Was "tt" by String object recycle...
|
689
840
|
end
|
690
841
|
|
842
|
+
def test_get_with_block_chunked_string_recycle
|
843
|
+
server = TCPServer.open('localhost', 0)
|
844
|
+
server_thread = Thread.new {
|
845
|
+
Thread.abort_on_exception = true
|
846
|
+
sock = server.accept
|
847
|
+
create_keepalive_thread(1, sock)
|
848
|
+
}
|
849
|
+
url = "http://localhost:#{server.addr[1]}/"
|
850
|
+
body = []
|
851
|
+
begin
|
852
|
+
_res = @client.get(url + 'chunked') { |str|
|
853
|
+
body << str
|
854
|
+
}
|
855
|
+
ensure
|
856
|
+
server.close
|
857
|
+
server_thread.join
|
858
|
+
end
|
859
|
+
assert_equal('abcdefghijklmnopqrstuvwxyz1234567890abcdef', body.join)
|
860
|
+
end
|
861
|
+
|
691
862
|
def test_post
|
692
|
-
assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4])
|
863
|
+
assert_equal("post", @client.post(serverurl + 'servlet', '').content[0, 4])
|
693
864
|
param = {'1'=>'2', '3'=>'4'}
|
694
865
|
res = @client.post(serverurl + 'servlet', param)
|
695
866
|
assert_equal(param, params(res.header["x-query"][0]))
|
696
867
|
end
|
697
868
|
|
869
|
+
def test_post_empty
|
870
|
+
@client.debug_dev = str = ''
|
871
|
+
# nil body means 'no content' that is allowed but WEBrick cannot handle it.
|
872
|
+
@client.post(serverurl + 'servlet', :body => nil)
|
873
|
+
# request does not have 'Content-Type'
|
874
|
+
assert_equal(1, str.scan(/content-type/i).size)
|
875
|
+
end
|
876
|
+
|
877
|
+
def test_post_with_query
|
878
|
+
# this {:query => 'query'} recognized as body
|
879
|
+
res = @client.post(serverurl + 'servlet', :query => 'query')
|
880
|
+
assert_equal("post", res.content[0, 4])
|
881
|
+
assert_equal("query=query", res.headers["X-Query"])
|
882
|
+
assert_equal("", res.headers["X-Request-Query"])
|
883
|
+
end
|
884
|
+
|
885
|
+
def test_post_with_query_and_body
|
886
|
+
res = @client.post(serverurl + 'servlet', :query => {:query => 'query'}, :body => {:body => 'body'})
|
887
|
+
assert_equal("post", res.content[0, 4])
|
888
|
+
assert_equal("body=body", res.headers["X-Query"])
|
889
|
+
assert_equal("query=query", res.headers["X-Request-Query"])
|
890
|
+
end
|
891
|
+
|
698
892
|
def test_post_follow_redirect
|
699
893
|
assert_equal('hello', @client.post(serverurl + 'hello', :follow_redirect => true).body)
|
700
894
|
assert_equal('hello', @client.post(serverurl + 'redirect1', :follow_redirect => true).body)
|
@@ -704,18 +898,18 @@ EOS
|
|
704
898
|
def test_post_with_content_type
|
705
899
|
param = [['1', '2'], ['3', '4']]
|
706
900
|
ext = {'content-type' => 'application/x-www-form-urlencoded', 'hello' => 'world'}
|
707
|
-
assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext)
|
901
|
+
assert_equal("post", @client.post(serverurl + 'servlet', '').content[0, 4], ext)
|
708
902
|
res = @client.post(serverurl + 'servlet', param, ext)
|
709
903
|
assert_equal(Hash[param], params(res.header["x-query"][0]))
|
710
904
|
#
|
711
905
|
ext = [['content-type', 'multipart/form-data'], ['hello', 'world']]
|
712
|
-
assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext)
|
906
|
+
assert_equal("post", @client.post(serverurl + 'servlet', '').content[0, 4], ext)
|
713
907
|
res = @client.post(serverurl + 'servlet', param, ext)
|
714
908
|
assert_match(/Content-Disposition: form-data; name="1"/, res.content)
|
715
909
|
assert_match(/Content-Disposition: form-data; name="3"/, res.content)
|
716
910
|
#
|
717
911
|
ext = {'content-type' => 'multipart/form-data; boundary=hello'}
|
718
|
-
assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext)
|
912
|
+
assert_equal("post", @client.post(serverurl + 'servlet', '').content[0, 4], ext)
|
719
913
|
res = @client.post(serverurl + 'servlet', param, ext)
|
720
914
|
assert_match(/Content-Disposition: form-data; name="1"/, res.content)
|
721
915
|
assert_match(/Content-Disposition: form-data; name="3"/, res.content)
|
@@ -725,7 +919,7 @@ EOS
|
|
725
919
|
def test_post_with_custom_multipart_and_boolean_params
|
726
920
|
param = [['boolean_true', true]]
|
727
921
|
ext = { 'content-type' => 'multipart/form-data' }
|
728
|
-
assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext)
|
922
|
+
assert_equal("post", @client.post(serverurl + 'servlet', '').content[0, 4], ext)
|
729
923
|
res = @client.post(serverurl + 'servlet', param, ext)
|
730
924
|
assert_match(/Content-Disposition: form-data; name="boolean_true"\r\n\r\ntrue\r\n/, res.content)
|
731
925
|
#
|
@@ -777,7 +971,8 @@ EOS
|
|
777
971
|
assert_match(/\r\n2\r\n/m, res.content)
|
778
972
|
assert_match(/\r\nContent-Disposition: form-data; name="3"; filename=""\r\n/m, res.content)
|
779
973
|
assert_match(/\r\nContent-Length:/m, str.string)
|
780
|
-
|
974
|
+
# HTTPClient reads from head to 'size'; CHUNK_SIZE bytes then 1 byte, that's all.
|
975
|
+
assert_equal(2, myio.called)
|
781
976
|
end
|
782
977
|
|
783
978
|
def test_post_with_io_nosize # streaming + chunked post
|
@@ -794,6 +989,42 @@ EOS
|
|
794
989
|
assert_match(/\r\nTransfer-Encoding: chunked\r\n/m, str.string)
|
795
990
|
end
|
796
991
|
|
992
|
+
def test_post_with_sized_io
|
993
|
+
myio = StringIO.new("45")
|
994
|
+
def myio.size
|
995
|
+
1
|
996
|
+
end
|
997
|
+
res = @client.post(serverurl + 'servlet', myio)
|
998
|
+
assert_equal('post,4', res.content)
|
999
|
+
end
|
1000
|
+
|
1001
|
+
def test_post_with_sized_io_part
|
1002
|
+
myio = StringIO.new("45")
|
1003
|
+
def myio.size
|
1004
|
+
1
|
1005
|
+
end
|
1006
|
+
@client.debug_dev = str = StringIO.new
|
1007
|
+
_res = @client.post(serverurl + 'servlet', { :file => myio })
|
1008
|
+
assert_match(/\r\n4\r\n/, str.string, 'should send "4" not "45"')
|
1009
|
+
end
|
1010
|
+
|
1011
|
+
def test_post_with_unknown_sized_io_part
|
1012
|
+
myio1 = StringIO.new("123")
|
1013
|
+
myio2 = StringIO.new("45")
|
1014
|
+
class << myio1
|
1015
|
+
undef :size
|
1016
|
+
end
|
1017
|
+
class << myio2
|
1018
|
+
# This does not work because other file is 'unknown sized'
|
1019
|
+
def size
|
1020
|
+
1
|
1021
|
+
end
|
1022
|
+
end
|
1023
|
+
@client.debug_dev = str = StringIO.new
|
1024
|
+
_res = @client.post(serverurl + 'servlet', { :file1 => myio1, :file2 => myio2 })
|
1025
|
+
assert_match(/\r\n45\r\n/, str.string)
|
1026
|
+
end
|
1027
|
+
|
797
1028
|
def test_post_async
|
798
1029
|
param = {'1'=>'2', '3'=>'4'}
|
799
1030
|
conn = @client.post_async(serverurl + 'servlet', param)
|
@@ -804,7 +1035,7 @@ EOS
|
|
804
1035
|
|
805
1036
|
def test_post_with_block
|
806
1037
|
called = false
|
807
|
-
res = @client.post(serverurl + 'servlet') { |str|
|
1038
|
+
res = @client.post(serverurl + 'servlet', '') { |str|
|
808
1039
|
assert_equal('post,', str)
|
809
1040
|
called = true
|
810
1041
|
}
|
@@ -824,7 +1055,7 @@ EOS
|
|
824
1055
|
|
825
1056
|
def test_post_with_custom_multipart
|
826
1057
|
ext = {'content-type' => 'multipart/form-data'}
|
827
|
-
assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext)
|
1058
|
+
assert_equal("post", @client.post(serverurl + 'servlet', '').content[0, 4], ext)
|
828
1059
|
body = [{ 'Content-Disposition' => 'form-data; name="1"', :content => "2"},
|
829
1060
|
{ 'Content-Disposition' => 'form-data; name="3"', :content => "4"}]
|
830
1061
|
res = @client.post(serverurl + 'servlet', body, ext)
|
@@ -832,7 +1063,7 @@ EOS
|
|
832
1063
|
assert_match(/Content-Disposition: form-data; name="3"/, res.content)
|
833
1064
|
#
|
834
1065
|
ext = {'content-type' => 'multipart/form-data; boundary=hello'}
|
835
|
-
assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext)
|
1066
|
+
assert_equal("post", @client.post(serverurl + 'servlet', '').content[0, 4], ext)
|
836
1067
|
res = @client.post(serverurl + 'servlet', body, ext)
|
837
1068
|
assert_match(/Content-Disposition: form-data; name="1"/, res.content)
|
838
1069
|
assert_match(/Content-Disposition: form-data; name="3"/, res.content)
|
@@ -842,6 +1073,10 @@ EOS
|
|
842
1073
|
def test_post_with_custom_multipart_and_file
|
843
1074
|
STDOUT.sync = true
|
844
1075
|
File.open(__FILE__) do |file|
|
1076
|
+
def file.original_filename
|
1077
|
+
'file.txt'
|
1078
|
+
end
|
1079
|
+
|
845
1080
|
ext = { 'Content-Type' => 'multipart/alternative' }
|
846
1081
|
body = [{ 'Content-Type' => 'text/plain', :content => "this is only a test" },
|
847
1082
|
{ 'Content-Type' => 'application/x-ruby', :content => file }]
|
@@ -849,12 +1084,43 @@ EOS
|
|
849
1084
|
assert_match(/^Content-Type: text\/plain\r\n/m, res.content)
|
850
1085
|
assert_match(/^this is only a test\r\n/m, res.content)
|
851
1086
|
assert_match(/^Content-Type: application\/x-ruby\r\n/m, res.content)
|
1087
|
+
assert_match(/Content-Disposition: form-data; name="3"; filename="file.txt"/, res.content)
|
852
1088
|
assert_match(/FIND_TAG_IN_THIS_FILE/, res.content)
|
853
1089
|
end
|
854
1090
|
end
|
855
1091
|
|
1092
|
+
def test_patch
|
1093
|
+
assert_equal("patch", @client.patch(serverurl + 'servlet', '').content)
|
1094
|
+
param = {'1'=>'2', '3'=>'4'}
|
1095
|
+
@client.debug_dev = str = ''
|
1096
|
+
res = @client.patch(serverurl + 'servlet', param)
|
1097
|
+
assert_equal(param, params(res.header["x-query"][0]))
|
1098
|
+
assert_equal('Content-Type: application/x-www-form-urlencoded', str.split(/\r?\n/)[5])
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
def test_patch_with_query_and_body
|
1102
|
+
res = @client.patch(serverurl + 'servlet', :query => {:query => 'query'}, :body => {:body => 'body'})
|
1103
|
+
assert_equal("patch", res.content)
|
1104
|
+
assert_equal("body=body", res.headers["X-Query"])
|
1105
|
+
assert_equal("query=query", res.headers["X-Request-Query"])
|
1106
|
+
end
|
1107
|
+
|
1108
|
+
def test_patch_bytesize
|
1109
|
+
res = @client.patch(serverurl + 'servlet', 'txt' => 'あいうえお')
|
1110
|
+
assert_equal('txt=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A', res.header["x-query"][0])
|
1111
|
+
assert_equal('15', res.header["x-size"][0])
|
1112
|
+
end
|
1113
|
+
|
1114
|
+
def test_patch_async
|
1115
|
+
param = {'1'=>'2', '3'=>'4'}
|
1116
|
+
conn = @client.patch_async(serverurl + 'servlet', param)
|
1117
|
+
Thread.pass while !conn.finished?
|
1118
|
+
res = conn.pop
|
1119
|
+
assert_equal(param, params(res.header["x-query"][0]))
|
1120
|
+
end
|
1121
|
+
|
856
1122
|
def test_put
|
857
|
-
assert_equal("put", @client.put(serverurl + 'servlet').content)
|
1123
|
+
assert_equal("put", @client.put(serverurl + 'servlet', '').content)
|
858
1124
|
param = {'1'=>'2', '3'=>'4'}
|
859
1125
|
@client.debug_dev = str = ''
|
860
1126
|
res = @client.put(serverurl + 'servlet', param)
|
@@ -862,6 +1128,13 @@ EOS
|
|
862
1128
|
assert_equal('Content-Type: application/x-www-form-urlencoded', str.split(/\r?\n/)[5])
|
863
1129
|
end
|
864
1130
|
|
1131
|
+
def test_put_with_query_and_body
|
1132
|
+
res = @client.put(serverurl + 'servlet', :query => {:query => 'query'}, :body => {:body => 'body'})
|
1133
|
+
assert_equal("put", res.content)
|
1134
|
+
assert_equal("body=body", res.headers["X-Query"])
|
1135
|
+
assert_equal("query=query", res.headers["X-Request-Query"])
|
1136
|
+
end
|
1137
|
+
|
865
1138
|
def test_put_bytesize
|
866
1139
|
res = @client.put(serverurl + 'servlet', 'txt' => 'あいうえお')
|
867
1140
|
assert_equal('txt=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A', res.header["x-query"][0])
|
@@ -880,6 +1153,19 @@ EOS
|
|
880
1153
|
assert_equal("delete", @client.delete(serverurl + 'servlet').content)
|
881
1154
|
end
|
882
1155
|
|
1156
|
+
def test_delete_with_query
|
1157
|
+
res = @client.delete(serverurl + 'servlet', :query => {:query => 'query'})
|
1158
|
+
assert_equal("delete", res.content)
|
1159
|
+
assert_equal('query=query', res.headers['X-Request-Query'])
|
1160
|
+
end
|
1161
|
+
|
1162
|
+
def test_delete_with_query_and_body
|
1163
|
+
res = @client.delete(serverurl + 'servlet', :query => {:query => 'query'}, :body => {:body => 'body'})
|
1164
|
+
assert_equal("delete", res.content)
|
1165
|
+
assert_equal('query=query', res.headers['X-Request-Query'])
|
1166
|
+
assert_equal('body=body', res.headers['X-Query'])
|
1167
|
+
end
|
1168
|
+
|
883
1169
|
# Not prohibited by spec, but normally it's ignored
|
884
1170
|
def test_delete_with_body
|
885
1171
|
param = {'1'=>'2', '3'=>'4'}
|
@@ -896,7 +1182,23 @@ EOS
|
|
896
1182
|
end
|
897
1183
|
|
898
1184
|
def test_options
|
899
|
-
assert_equal(
|
1185
|
+
assert_equal('options', @client.options(serverurl + 'servlet').content)
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
def test_options_with_header
|
1189
|
+
res = @client.options(serverurl + 'servlet', {'x-header' => 'header'})
|
1190
|
+
assert_equal('header', res.headers['X-Header'])
|
1191
|
+
end
|
1192
|
+
|
1193
|
+
def test_options_with_body
|
1194
|
+
res = @client.options(serverurl + 'servlet', :body => 'body')
|
1195
|
+
assert_equal('body', res.headers['X-Body'])
|
1196
|
+
end
|
1197
|
+
|
1198
|
+
def test_options_with_body_and_header
|
1199
|
+
res = @client.options(serverurl + 'servlet', :body => 'body', :header => {'x-header' => 'header'})
|
1200
|
+
assert_equal('header', res.headers['X-Header'])
|
1201
|
+
assert_equal('body', res.headers['X-Body'])
|
900
1202
|
end
|
901
1203
|
|
902
1204
|
def test_options_async
|
@@ -951,6 +1253,7 @@ EOS
|
|
951
1253
|
|
952
1254
|
def test_chunked
|
953
1255
|
assert_equal('chunked', @client.get_content(serverurl + 'chunked', { 'msg' => 'chunked' }))
|
1256
|
+
assert_equal('あいうえお', @client.get_content(serverurl + 'chunked', { 'msg' => 'あいうえお' }))
|
954
1257
|
end
|
955
1258
|
|
956
1259
|
def test_chunked_empty
|
@@ -1024,7 +1327,7 @@ EOS
|
|
1024
1327
|
|
1025
1328
|
def test_http_custom_date_header
|
1026
1329
|
@client.debug_dev = (str = "")
|
1027
|
-
|
1330
|
+
_res = @client.get(serverurl + 'hello', :header => {'Date' => 'foo'})
|
1028
1331
|
lines = str.split(/(?:\r?\n)+/)
|
1029
1332
|
assert_equal('Date: foo', lines[4])
|
1030
1333
|
end
|
@@ -1052,35 +1355,32 @@ EOS
|
|
1052
1355
|
|
1053
1356
|
def test_receive_timeout
|
1054
1357
|
# this test takes 2 sec
|
1055
|
-
assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=2'))
|
1358
|
+
assert_equal('hello?sec=2', @client.get_content(serverurl + 'sleep?sec=2'))
|
1056
1359
|
@client.receive_timeout = 1
|
1057
|
-
|
1360
|
+
@client.reset_all
|
1361
|
+
assert_equal('hello?sec=0', @client.get_content(serverurl + 'sleep?sec=0'))
|
1058
1362
|
assert_raise(HTTPClient::ReceiveTimeoutError) do
|
1059
1363
|
@client.get_content(serverurl + 'sleep?sec=2')
|
1060
1364
|
end
|
1061
1365
|
@client.receive_timeout = 3
|
1062
|
-
|
1366
|
+
@client.reset_all
|
1367
|
+
assert_equal('hello?sec=2', @client.get_content(serverurl + 'sleep?sec=2'))
|
1063
1368
|
end
|
1064
1369
|
|
1065
1370
|
def test_receive_timeout_post
|
1066
1371
|
# this test takes 2 sec
|
1067
1372
|
assert_equal('hello', @client.post(serverurl + 'sleep', :sec => 2).content)
|
1068
1373
|
@client.receive_timeout = 1
|
1374
|
+
@client.reset_all
|
1069
1375
|
assert_equal('hello', @client.post(serverurl + 'sleep', :sec => 0).content)
|
1070
1376
|
assert_raise(HTTPClient::ReceiveTimeoutError) do
|
1071
1377
|
@client.post(serverurl + 'sleep', :sec => 2)
|
1072
1378
|
end
|
1073
1379
|
@client.receive_timeout = 3
|
1380
|
+
@client.reset_all
|
1074
1381
|
assert_equal('hello', @client.post(serverurl + 'sleep', :sec => 2).content)
|
1075
1382
|
end
|
1076
1383
|
|
1077
|
-
def test_async_error
|
1078
|
-
assert_raise( SocketError ) do
|
1079
|
-
conn = @client.get_async("http://non-existing-host/")
|
1080
|
-
conn.pop
|
1081
|
-
end
|
1082
|
-
end
|
1083
|
-
|
1084
1384
|
def test_reset
|
1085
1385
|
url = serverurl + 'servlet'
|
1086
1386
|
assert_nothing_raised do
|
@@ -1101,22 +1401,18 @@ EOS
|
|
1101
1401
|
end
|
1102
1402
|
|
1103
1403
|
def test_cookies
|
1104
|
-
cookiefile =
|
1105
|
-
File.open(cookiefile, "wb") do |f|
|
1106
|
-
f << "http://rubyforge.org/account/login.php\tsession_ser\tLjEwMy45Ni40Ni0q%2A-fa0537de8cc31\t2000000000\
|
1107
|
-
end
|
1108
|
-
@client.set_cookie_store(cookiefile)
|
1109
|
-
cookie = @client.cookie_manager.cookies.first
|
1110
|
-
url = cookie.url
|
1111
|
-
assert(cookie.domain_match(url.host, cookie.domain))
|
1404
|
+
cookiefile = Tempfile.new('test_cookies_file')
|
1405
|
+
File.open(cookiefile.path, "wb") do |f|
|
1406
|
+
f << "http://rubyforge.org/account/login.php\tsession_ser\tLjEwMy45Ni40Ni0q%2A-fa0537de8cc31\t2000000000\trubyforge.org\t/account/\t9\n"
|
1407
|
+
end
|
1408
|
+
@client.set_cookie_store(cookiefile.path)
|
1112
1409
|
#
|
1113
1410
|
@client.reset_all
|
1114
|
-
@client.test_loopback_http_response << "HTTP/1.0 200 OK\nSet-Cookie:
|
1411
|
+
@client.test_loopback_http_response << "HTTP/1.0 200 OK\nSet-Cookie: session_ser=bar; expires=#{Time.at(1924873200).gmtime.httpdate}\n\nOK"
|
1115
1412
|
@client.get_content('http://rubyforge.org/account/login.php')
|
1116
1413
|
@client.save_cookie_store
|
1117
|
-
str = File.read(cookiefile)
|
1118
|
-
assert_match(%r(http://rubyforge.org/account/login.php\
|
1119
|
-
File.unlink(cookiefile)
|
1414
|
+
str = File.read(cookiefile.path)
|
1415
|
+
assert_match(%r(http://rubyforge.org/account/login.php\tsession_ser\tbar\t1924873200\trubyforge.org\t/account/\t9), str)
|
1120
1416
|
end
|
1121
1417
|
|
1122
1418
|
def test_eof_error_length
|
@@ -1240,6 +1536,7 @@ EOS
|
|
1240
1536
|
assert_equal('text/plain', HTTP::Message.mime_type('foo.txt'))
|
1241
1537
|
assert_equal('text/html', HTTP::Message.mime_type('foo.html'))
|
1242
1538
|
assert_equal('text/html', HTTP::Message.mime_type('foo.htm'))
|
1539
|
+
assert_equal('text/xml', HTTP::Message.mime_type('foo.xml'))
|
1243
1540
|
assert_equal('application/msword', HTTP::Message.mime_type('foo.doc'))
|
1244
1541
|
assert_equal('image/png', HTTP::Message.mime_type('foo.png'))
|
1245
1542
|
assert_equal('image/gif', HTTP::Message.mime_type('foo.gif'))
|
@@ -1342,6 +1639,7 @@ EOS
|
|
1342
1639
|
res = HTTP::Message.new_response('response')
|
1343
1640
|
res.contenttype = 'text/plain'
|
1344
1641
|
res.header.body_date = Time.at(946652400)
|
1642
|
+
res.header.request_uri = 'http://www.example.com/'
|
1345
1643
|
assert_nil(res.cookies)
|
1346
1644
|
#
|
1347
1645
|
res.header['Set-Cookie'] = [
|
@@ -1418,8 +1716,11 @@ EOS
|
|
1418
1716
|
server = TCPServer.open('127.0.0.1', 0)
|
1419
1717
|
server.listen(30) # set enough backlogs
|
1420
1718
|
endpoint = "http://127.0.0.1:#{server.addr[1]}/"
|
1421
|
-
|
1719
|
+
queue = Queue.new
|
1720
|
+
Thread.new(queue) { |qs|
|
1422
1721
|
Thread.abort_on_exception = true
|
1722
|
+
# want 5 requests issued
|
1723
|
+
5.times { qs.pop }
|
1423
1724
|
# emulate 10 keep-alive connections
|
1424
1725
|
10.times do |idx|
|
1425
1726
|
sock = server.accept
|
@@ -1448,22 +1749,29 @@ EOS
|
|
1448
1749
|
sock.close
|
1449
1750
|
end
|
1450
1751
|
}
|
1451
|
-
# allocate 10 keep-alive connections
|
1752
|
+
# try to allocate 10 keep-alive connections; it's a race so some
|
1753
|
+
# threads can reuse the connection so actual number of keep-alive
|
1754
|
+
# connections should be smaller than 10.
|
1452
1755
|
(0...10).to_a.map {
|
1453
|
-
Thread.new {
|
1454
|
-
|
1756
|
+
Thread.new(queue) { |qc|
|
1757
|
+
Thread.abort_on_exception = true
|
1758
|
+
conn = client.get_async(endpoint)
|
1759
|
+
qc.push(true)
|
1760
|
+
assert_equal("12345", conn.pop.content.read)
|
1455
1761
|
}
|
1456
1762
|
}.each { |th| th.join }
|
1457
|
-
# send 5 requests,
|
1458
|
-
#
|
1763
|
+
# send 5 requests, some of these should get KeepAliveDesconnected
|
1764
|
+
# but should retry with new connection.
|
1459
1765
|
(0...5).to_a.map {
|
1460
1766
|
Thread.new {
|
1767
|
+
Thread.abort_on_exception = true
|
1461
1768
|
assert_equal("23456", client.get(endpoint).content)
|
1462
1769
|
}
|
1463
1770
|
}.each { |th| th.join }
|
1464
|
-
# rest requests won't get KeepAliveDisconnected
|
1771
|
+
# rest requests won't get KeepAliveDisconnected
|
1465
1772
|
(0...10).to_a.map {
|
1466
1773
|
Thread.new {
|
1774
|
+
Thread.abort_on_exception = true
|
1467
1775
|
assert_equal("34567", client.get(endpoint).content)
|
1468
1776
|
}
|
1469
1777
|
}.each { |th| th.join }
|
@@ -1522,6 +1830,19 @@ EOS
|
|
1522
1830
|
end
|
1523
1831
|
end
|
1524
1832
|
|
1833
|
+
def test_strict_response_size_check
|
1834
|
+
@client.strict_response_size_check = false
|
1835
|
+
@client.test_loopback_http_response << "HTTP/1.0 200 OK\r\nContent-Length: 12345\r\n\r\nhello world"
|
1836
|
+
assert_equal('hello world', @client.get_content('http://dummy'))
|
1837
|
+
|
1838
|
+
@client.reset_all
|
1839
|
+
@client.strict_response_size_check = true
|
1840
|
+
@client.test_loopback_http_response << "HTTP/1.0 200 OK\r\nContent-Length: 12345\r\n\r\nhello world"
|
1841
|
+
assert_raise(HTTPClient::BadResponseError) do
|
1842
|
+
@client.get_content('http://dummy')
|
1843
|
+
end
|
1844
|
+
end
|
1845
|
+
|
1525
1846
|
def test_socket_local
|
1526
1847
|
@client.socket_local.host = '127.0.0.1'
|
1527
1848
|
assert_equal('hello', @client.get_content(serverurl + 'hello'))
|
@@ -1557,6 +1878,48 @@ EOS
|
|
1557
1878
|
end
|
1558
1879
|
end
|
1559
1880
|
|
1881
|
+
def test_ipv6literaladdress_in_uri
|
1882
|
+
server = TCPServer.open('::1', 0) rescue return # Skip if IPv6 is unavailable.
|
1883
|
+
server_thread = Thread.new {
|
1884
|
+
Thread.abort_on_exception = true
|
1885
|
+
sock = server.accept
|
1886
|
+
while line = sock.gets
|
1887
|
+
break if line.chomp.empty?
|
1888
|
+
end
|
1889
|
+
sock.write("HTTP/1.1 200 OK\r\n")
|
1890
|
+
sock.write("Content-Length: 5\r\n")
|
1891
|
+
sock.write("\r\n")
|
1892
|
+
sock.write("12345")
|
1893
|
+
sock.close
|
1894
|
+
}
|
1895
|
+
uri = "http://[::1]:#{server.addr[1]}/"
|
1896
|
+
begin
|
1897
|
+
assert_equal('12345', @client.get(uri).body)
|
1898
|
+
ensure
|
1899
|
+
server.close
|
1900
|
+
server_thread.kill
|
1901
|
+
server_thread.join
|
1902
|
+
end
|
1903
|
+
end
|
1904
|
+
|
1905
|
+
def test_uri_no_schema
|
1906
|
+
assert_raise(ArgumentError) do
|
1907
|
+
@client.get_content("www.example.com")
|
1908
|
+
end
|
1909
|
+
end
|
1910
|
+
|
1911
|
+
def test_tcp_keepalive
|
1912
|
+
@client.tcp_keepalive = true
|
1913
|
+
@client.get(serverurl)
|
1914
|
+
|
1915
|
+
# expecting HTTP keepalive caches the socket
|
1916
|
+
session = @client.instance_variable_get(:@session_manager).send(:get_cached_session, HTTPClient::Site.new(URI.parse(serverurl)))
|
1917
|
+
socket = session.instance_variable_get(:@socket)
|
1918
|
+
|
1919
|
+
assert_true(session.tcp_keepalive)
|
1920
|
+
assert_equal(Socket::SO_KEEPALIVE, socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE).optname)
|
1921
|
+
end
|
1922
|
+
|
1560
1923
|
private
|
1561
1924
|
|
1562
1925
|
def check_query_get(query)
|
@@ -1594,53 +1957,53 @@ private
|
|
1594
1957
|
@server_thread = start_server_thread(@server)
|
1595
1958
|
end
|
1596
1959
|
|
1597
|
-
def
|
1598
|
-
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1960
|
+
def add_query_string(req)
|
1961
|
+
if req.query_string
|
1962
|
+
'?' + req.query_string
|
1963
|
+
else
|
1964
|
+
''
|
1965
|
+
end
|
1603
1966
|
end
|
1604
1967
|
|
1605
1968
|
def do_hello(req, res)
|
1606
1969
|
res['content-type'] = 'text/html'
|
1607
|
-
res.body = "hello"
|
1970
|
+
res.body = "hello" + add_query_string(req)
|
1608
1971
|
end
|
1609
1972
|
|
1610
1973
|
def do_sleep(req, res)
|
1611
1974
|
sec = req.query['sec'].to_i
|
1612
1975
|
sleep sec
|
1613
1976
|
res['content-type'] = 'text/html'
|
1614
|
-
res.body = "hello"
|
1977
|
+
res.body = "hello" + add_query_string(req)
|
1615
1978
|
end
|
1616
1979
|
|
1617
1980
|
def do_servlet_redirect(req, res)
|
1618
|
-
res.set_redirect(WEBrick::HTTPStatus::Found, serverurl + "servlet")
|
1981
|
+
res.set_redirect(WEBrick::HTTPStatus::Found, serverurl + "servlet" + add_query_string(req))
|
1619
1982
|
end
|
1620
1983
|
|
1621
1984
|
def do_redirect1(req, res)
|
1622
|
-
res.set_redirect(WEBrick::HTTPStatus::MovedPermanently, serverurl + "hello")
|
1985
|
+
res.set_redirect(WEBrick::HTTPStatus::MovedPermanently, serverurl + "hello" + add_query_string(req))
|
1623
1986
|
end
|
1624
1987
|
|
1625
1988
|
def do_redirect2(req, res)
|
1626
|
-
res.set_redirect(WEBrick::HTTPStatus::TemporaryRedirect, serverurl + "redirect3")
|
1989
|
+
res.set_redirect(WEBrick::HTTPStatus::TemporaryRedirect, serverurl + "redirect3" + add_query_string(req))
|
1627
1990
|
end
|
1628
1991
|
|
1629
1992
|
def do_redirect3(req, res)
|
1630
|
-
res.set_redirect(WEBrick::HTTPStatus::Found, serverurl + "hello")
|
1993
|
+
res.set_redirect(WEBrick::HTTPStatus::Found, serverurl + "hello" + add_query_string(req))
|
1631
1994
|
end
|
1632
1995
|
|
1633
1996
|
def do_redirect_self(req, res)
|
1634
|
-
res.set_redirect(WEBrick::HTTPStatus::Found, serverurl + "redirect_self")
|
1997
|
+
res.set_redirect(WEBrick::HTTPStatus::Found, serverurl + "redirect_self" + add_query_string(req))
|
1635
1998
|
end
|
1636
1999
|
|
1637
2000
|
def do_relative_redirect(req, res)
|
1638
|
-
res.set_redirect(WEBrick::HTTPStatus::Found, "hello")
|
2001
|
+
res.set_redirect(WEBrick::HTTPStatus::Found, "hello" + add_query_string(req))
|
1639
2002
|
end
|
1640
2003
|
|
1641
2004
|
def do_redirect_see_other(req, res)
|
1642
2005
|
if req.request_method == 'POST'
|
1643
|
-
res.set_redirect(WEBrick::HTTPStatus::SeeOther, serverurl + "redirect_see_other") # self
|
2006
|
+
res.set_redirect(WEBrick::HTTPStatus::SeeOther, serverurl + "redirect_see_other" + add_query_string(req)) # self
|
1644
2007
|
else
|
1645
2008
|
res.body = 'hello'
|
1646
2009
|
end
|
@@ -1648,6 +2011,7 @@ private
|
|
1648
2011
|
|
1649
2012
|
def do_chunked(req, res)
|
1650
2013
|
res.chunked = true
|
2014
|
+
res['content-type'] = 'text/plain; charset=UTF-8'
|
1651
2015
|
piper, pipew = IO.pipe
|
1652
2016
|
res.body = piper
|
1653
2017
|
pipew << req.query['msg']
|
@@ -1667,6 +2031,9 @@ private
|
|
1667
2031
|
elsif req.query['enc'] == 'deflate'
|
1668
2032
|
res['content-encoding'] = 'deflate'
|
1669
2033
|
res.body = DEFLATE_CONTENT
|
2034
|
+
elsif req.query['enc'] == 'deflate_noheader'
|
2035
|
+
res['content-encoding'] = 'deflate'
|
2036
|
+
res.body = DEFLATE_NOHEADER_CONTENT
|
1670
2037
|
end
|
1671
2038
|
end
|
1672
2039
|
|
@@ -1700,6 +2067,7 @@ private
|
|
1700
2067
|
|
1701
2068
|
def do_GET(req, res)
|
1702
2069
|
res.body = 'get'
|
2070
|
+
res['x-header'] = req['X-Header']
|
1703
2071
|
res["x-query"] = query_response(req)
|
1704
2072
|
end
|
1705
2073
|
|
@@ -1707,6 +2075,15 @@ private
|
|
1707
2075
|
res["content-type"] = "text/plain" # iso-8859-1, not US-ASCII
|
1708
2076
|
res.body = 'post,' + req.body.to_s
|
1709
2077
|
res["x-query"] = body_response(req)
|
2078
|
+
res["x-request-query"] = req.query_string
|
2079
|
+
end
|
2080
|
+
|
2081
|
+
def do_PATCH(req, res)
|
2082
|
+
res["x-query"] = body_response(req)
|
2083
|
+
param = WEBrick::HTTPUtils.parse_query(req.body) || {}
|
2084
|
+
res["x-size"] = (param['txt'] || '').size
|
2085
|
+
res.body = param['txt'] || 'patch'
|
2086
|
+
res["x-request-query"] = req.query_string
|
1710
2087
|
end
|
1711
2088
|
|
1712
2089
|
def do_PUT(req, res)
|
@@ -1714,15 +2091,19 @@ private
|
|
1714
2091
|
param = WEBrick::HTTPUtils.parse_query(req.body) || {}
|
1715
2092
|
res["x-size"] = (param['txt'] || '').size
|
1716
2093
|
res.body = param['txt'] || 'put'
|
2094
|
+
res["x-request-query"] = req.query_string
|
1717
2095
|
end
|
1718
2096
|
|
1719
2097
|
def do_DELETE(req, res)
|
1720
2098
|
res.body = 'delete'
|
2099
|
+
res["x-query"] = body_response(req)
|
2100
|
+
res["x-request-query"] = req.query_string
|
1721
2101
|
end
|
1722
2102
|
|
1723
2103
|
def do_OPTIONS(req, res)
|
1724
|
-
# check RFC for legal response.
|
1725
2104
|
res.body = 'options'
|
2105
|
+
res['x-header'] = req['X-Header']
|
2106
|
+
res['x-body'] = req.body
|
1726
2107
|
end
|
1727
2108
|
|
1728
2109
|
def do_PROPFIND(req, res)
|