class TestHTTPClient < ActiveSupport::TestCase include Helper include HTTPClient::Util def setup super setup_server setup_client end def teardown super end def test_initialize setup_proxyserver escape_noproxy do @proxyio.string = "" @client = HTTPClient.new(proxyurl) assert_equal(urify(proxyurl), @client.proxy) assert_equal(200, @client.head(serverurl).status) assert(/accept/ =~ @proxyio.string) end end def test_agent_name @client = HTTPClient.new(nil, "agent_name_foo") str = "" @client.debug_dev = str @client.get(serverurl) lines = str.split(/(?:\r?\n)+/) assert_equal("= Request", lines[0]) assert_match(/^User-Agent: agent_name_foo \(#{HTTPClient::VERSION}/, lines[4]) end def test_from @client = HTTPClient.new(nil, nil, "from_bar") str = "" @client.debug_dev = str @client.get(serverurl) lines = str.split(/(?:\r?\n)+/) assert_equal("= Request", lines[0]) assert_match(/^From: from_bar/, lines[5]) end def test_debug_dev str = "" @client.debug_dev = str assert_equal(str.object_id, @client.debug_dev.object_id) assert(str.empty?) @client.get(serverurl) assert(!str.empty?) end def test_debug_dev_stream str = "" @client.debug_dev = str conn = @client.get_async(serverurl) Thread.pass while !conn.finished? assert(!str.empty?) end def test_host_given str = "" @client.debug_dev = str @client.get(serverurl) lines = str.split(/(?:\r?\n)+/) assert_equal("= Request", lines[0]) assert_equal("! CONNECTION ESTABLISHED", lines[2]) assert_equal("GET / HTTP/1.1", lines[3]) assert_equal("Host: localhost:#{serverport}", lines[7]) # @client.reset_all str = "" @client.debug_dev = str @client.get(serverurl, nil, {'Host' => 'foo'}) lines = str.split(/(?:\r?\n)+/) assert_equal("= Request", lines[0]) assert_equal("! CONNECTION ESTABLISHED", lines[2]) assert_equal("GET / HTTP/1.1", lines[3]) assert_equal("Host: foo", lines[4]) # use given param end def test_redirect_returns_not_modified assert_nothing_raised do timeout(2) do @client.get(serverurl + 'status', {:status => 306}, {:follow_redirect => true}) end end end def test_proxy setup_proxyserver escape_noproxy do begin @client.proxy = "http://" rescue assert_match(/InvalidURIError/, $!.class.to_s) end @client.proxy = "" assert_nil(@client.proxy) @client.proxy = "http://admin:admin@foo:1234" assert_equal(urify("http://admin:admin@foo:1234"), @client.proxy) uri = urify("http://bar:2345") @client.proxy = uri assert_equal(uri, @client.proxy) # @proxyio.string = "" @client.proxy = nil assert_equal(200, @client.head(serverurl).status) assert(/accept/ !~ @proxyio.string) # @proxyio.string = "" @client.proxy = proxyurl @client.debug_dev = str = "" assert_equal(200, @client.head(serverurl).status) assert(/accept/ =~ @proxyio.string) assert(/Host: localhost:#{serverport}/ =~ str) end end def test_host_header @client.proxy = proxyurl @client.debug_dev = str = "" @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n" assert_equal(200, @client.head('http://www.example.com/foo').status) # ensure no ':80' is added. some servers dislike that. assert(/\r\nHost: www\.example\.com\r\n/ =~ str) # @client.debug_dev = str = "" @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n" assert_equal(200, @client.head('http://www.example.com:12345/foo').status) # ensure ':12345' exists. assert(/\r\nHost: www\.example\.com:12345\r\n/ =~ str) end def test_proxy_env setup_proxyserver escape_env do ENV['http_proxy'] = "http://admin:admin@foo:1234" ENV['NO_PROXY'] = "foobar" client = HTTPClient.new assert_equal(urify("http://admin:admin@foo:1234"), client.proxy) assert_equal('foobar', client.no_proxy) end end def test_proxy_env_cgi setup_proxyserver escape_env do ENV['REQUEST_METHOD'] = 'GET' # CGI environment emulation ENV['http_proxy'] = "http://admin:admin@foo:1234" ENV['no_proxy'] = "foobar" client = HTTPClient.new assert_equal(nil, client.proxy) ENV['CGI_HTTP_PROXY'] = "http://admin:admin@foo:1234" client = HTTPClient.new assert_equal(urify("http://admin:admin@foo:1234"), client.proxy) end end def test_empty_proxy_env setup_proxyserver escape_env do ENV['http_proxy'] = "" client = HTTPClient.new assert_equal(nil, client.proxy) end end def test_noproxy_for_localhost @proxyio.string = "" @client.proxy = proxyurl assert_equal(200, @client.head(serverurl).status) assert(/accept/ !~ @proxyio.string) end def test_no_proxy setup_proxyserver escape_noproxy do # proxy is not set. assert_equal(nil, @client.no_proxy) @client.no_proxy = 'localhost' assert_equal('localhost', @client.no_proxy) @proxyio.string = "" @client.proxy = nil assert_equal(200, @client.head(serverurl).status) assert(/accept/ !~ @proxyio.string) # @proxyio.string = "" @client.proxy = proxyurl assert_equal(200, @client.head(serverurl).status) assert(/accept/ !~ @proxyio.string) # @client.no_proxy = 'foobar' @proxyio.string = "" @client.proxy = proxyurl assert_equal(200, @client.head(serverurl).status) assert(/accept/ =~ @proxyio.string) # @client.no_proxy = 'foobar,localhost:baz' @proxyio.string = "" @client.proxy = proxyurl assert_equal(200, @client.head(serverurl).status) assert(/accept/ !~ @proxyio.string) # @client.no_proxy = 'foobar,localhost:443' @proxyio.string = "" @client.proxy = proxyurl assert_equal(200, @client.head(serverurl).status) assert(/accept/ =~ @proxyio.string) # @client.no_proxy = "foobar,localhost:443:localhost:#{serverport},baz" @proxyio.string = "" @client.proxy = proxyurl assert_equal(200, @client.head(serverurl).status) assert(/accept/ !~ @proxyio.string) end end def test_no_proxy_with_initial_dot @client.debug_dev = str = "" @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n" @client.no_proxy = '' @client.proxy = proxyurl @client.head('http://www.foo.com') assert(/CONNECT TO localhost/ =~ str, 'via proxy') # @client.debug_dev = str = "" @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n" @client.no_proxy = '.foo.com' @client.proxy = proxyurl @client.head('http://www.foo.com') assert(/CONNECT TO www.foo.com/ =~ str, 'no proxy because .foo.com matches with www.foo.com') # @client.debug_dev = str = "" @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n" @client.no_proxy = '.foo.com' @client.proxy = proxyurl @client.head('http://foo.com') assert(/CONNECT TO localhost/ =~ str, 'via proxy because .foo.com does not matche with foo.com') # @client.debug_dev = str = "" @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\n\r\n" @client.no_proxy = 'foo.com' @client.proxy = proxyurl @client.head('http://foo.com') assert(/CONNECT TO foo.com/ =~ str, 'no proxy because foo.com matches with foo.com') end def test_cookie_update_while_authentication escape_noproxy do @client.test_loopback_http_response << < true).header.request_uri) assert_equal(expected, @client.get(serverurl + 'redirect2', :follow_redirect => true).header.request_uri) end def test_redirect_non_https url = serverurl + 'redirect1' https_url = urify(url) https_url.scheme = 'https' # redirect_to_http = "HTTP/1.0 302 OK\nLocation: #{url}\n\n" redirect_to_https = "HTTP/1.0 302 OK\nLocation: #{https_url}\n\n" # # https -> http is denied @client.test_loopback_http_response << redirect_to_http assert_raises(HTTPClient::BadResponseError) do @client.get_content(https_url) end # # http -> http is OK @client.reset_all @client.test_loopback_http_response << redirect_to_http assert_equal('hello', @client.get_content(url)) # # http -> https is OK @client.reset_all @client.test_loopback_http_response << redirect_to_https assert_raises(OpenSSL::SSL::SSLError) do # trying to normal endpoint with SSL -> SSL negotiation failure @client.get_content(url) end # # https -> https is OK @client.reset_all @client.test_loopback_http_response << redirect_to_https assert_raises(OpenSSL::SSL::SSLError) do # trying to normal endpoint with SSL -> SSL negotiation failure @client.get_content(https_url) end # # https -> http with strict_redirect_uri_callback @client.redirect_uri_callback = @client.method(:strict_redirect_uri_callback) @client.test_loopback_http_response << redirect_to_http assert_raises(HTTPClient::BadResponseError) do @client.get_content(https_url) end end def test_redirect_see_other assert_equal('hello', @client.post_content(serverurl + 'redirect_see_other')) end def test_redirect_relative @client.test_loopback_http_response << "HTTP/1.0 302 OK\nLocation: hello\n\n" silent do assert_equal('hello', @client.get_content(serverurl + 'redirect1')) end # @client.reset_all @client.redirect_uri_callback = @client.method(:strict_redirect_uri_callback) assert_equal('hello', @client.get_content(serverurl + 'redirect1')) @client.reset_all @client.test_loopback_http_response << "HTTP/1.0 302 OK\nLocation: hello\n\n" begin @client.get_content(serverurl + 'redirect1') assert(false) rescue HTTPClient::BadResponseError => e assert_equal(302, e.res.status) end end def test_redirect_https_relative url = serverurl + 'redirect1' https_url = urify(url) https_url.scheme = 'https' @client.test_loopback_http_response << "HTTP/1.0 302 OK\nLocation: /foo\n\n" @client.test_loopback_http_response << "HTTP/1.0 200 OK\n\nhello" silent do assert_equal('hello', @client.get_content(https_url)) end end def test_no_content assert_nothing_raised do timeout(2) do @client.get(serverurl + 'status', :status => 101) @client.get(serverurl + 'status', :status => 204) @client.get(serverurl + 'status', :status => 304) end end end def test_head assert_equal("head", @client.head(serverurl + 'servlet').header["x-head"][0]) param = {'1'=>'2', '3'=>'4'} res = @client.head(serverurl + 'servlet', param) assert_equal(param, params(res.header["x-query"][0])) end def test_head_async param = {'1'=>'2', '3'=>'4'} conn = @client.head_async(serverurl + 'servlet', param) Thread.pass while !conn.finished? res = conn.pop assert_equal(param, params(res.header["x-query"][0])) end def test_get assert_equal("get", @client.get(serverurl + 'servlet').content) param = {'1'=>'2', '3'=>'4'} res = @client.get(serverurl + 'servlet', param) assert_equal(param, params(res.header["x-query"][0])) assert_nil(res.contenttype) # url = serverurl.to_s + 'servlet?5=6&7=8' res = @client.get(url, param) assert_equal(param.merge("5"=>"6", "7"=>"8"), params(res.header["x-query"][0])) assert_nil(res.contenttype) end def test_head_follow_redirect expected = urify(serverurl + 'hello') assert_equal(expected, @client.head(serverurl + 'hello', :follow_redirect => true).header.request_uri) assert_equal(expected, @client.head(serverurl + 'redirect1', :follow_redirect => true).header.request_uri) assert_equal(expected, @client.head(serverurl + 'redirect2', :follow_redirect => true).header.request_uri) end def test_get_follow_redirect assert_equal('hello', @client.get(serverurl + 'hello', :follow_redirect => true).body) assert_equal('hello', @client.get(serverurl + 'redirect1', :follow_redirect => true).body) assert_equal('hello', @client.get(serverurl + 'redirect2', :follow_redirect => true).body) end def test_get_async param = {'1'=>'2', '3'=>'4'} conn = @client.get_async(serverurl + 'servlet', param) Thread.pass while !conn.finished? res = conn.pop assert_equal(param, params(res.header["x-query"][0])) end def test_get_async_for_largebody conn = @client.get_async(serverurl + 'largebody') res = conn.pop assert_equal(1000*1000, res.content.read.length) end def test_get_with_block called = false res = @client.get(serverurl + 'servlet') { |str| assert_equal('get', str) called = true } assert(called) # res does not have a content assert_nil(res.content) end def test_get_with_block_chunk_string_recycle @client.read_block_size = 2 body = [] res = @client.get(serverurl + 'servlet') { |str| body << str } assert_equal(2, body.size) assert_equal("get", body.join) # Was "tt" by String object recycle... end def test_post assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4]) param = {'1'=>'2', '3'=>'4'} res = @client.post(serverurl + 'servlet', param) assert_equal(param, params(res.header["x-query"][0])) end def test_post_follow_redirect assert_equal('hello', @client.post(serverurl + 'hello', :follow_redirect => true).body) assert_equal('hello', @client.post(serverurl + 'redirect1', :follow_redirect => true).body) assert_equal('hello', @client.post(serverurl + 'redirect2', :follow_redirect => true).body) end def test_post_with_content_type param = [['1', '2'], ['3', '4']] ext = {'content-type' => 'application/x-www-form-urlencoded', 'hello' => 'world'} assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext) res = @client.post(serverurl + 'servlet', param, ext) assert_equal(Hash[param], params(res.header["x-query"][0])) # ext = [['content-type', 'multipart/form-data'], ['hello', 'world']] assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext) res = @client.post(serverurl + 'servlet', param, ext) assert_match(/Content-Disposition: form-data; name="1"/, res.content) assert_match(/Content-Disposition: form-data; name="3"/, res.content) # ext = {'content-type' => 'multipart/form-data; boundary=hello'} assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext) res = @client.post(serverurl + 'servlet', param, ext) assert_match(/Content-Disposition: form-data; name="1"/, res.content) assert_match(/Content-Disposition: form-data; name="3"/, res.content) assert_equal("post,--hello\r\nContent-Disposition: form-data; name=\"1\"\r\n\r\n2\r\n--hello\r\nContent-Disposition: form-data; name=\"3\"\r\n\r\n4\r\n--hello--\r\n\r\n", res.content) end def test_post_with_custom_multipart_and_boolean_params param = [['boolean_true', true]] ext = { 'content-type' => 'multipart/form-data' } assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext) res = @client.post(serverurl + 'servlet', param, ext) assert_match(/Content-Disposition: form-data; name="boolean_true"\r\n\r\ntrue\r\n/, res.content) # param = [['boolean_false', false]] res = @client.post(serverurl + 'servlet', param, ext) assert_match(/Content-Disposition: form-data; name="boolean_false"\r\n\r\nfalse\r\n/, res.content) # param = [['nil', nil]] res = @client.post(serverurl + 'servlet', param, ext) assert_match(/Content-Disposition: form-data; name="nil"\r\n\r\n\r\n/, res.content) end def test_post_with_file STDOUT.sync = true File.open(__FILE__) do |file| res = @client.post(serverurl + 'servlet', {1=>2, 3=>file}) assert_match(/^Content-Disposition: form-data; name="1"\r\n/nm, res.content) assert_match(/^Content-Disposition: form-data; name="3";/, res.content) assert_match(/FIND_TAG_IN_THIS_FILE/, res.content) end end def test_post_with_file_without_size STDOUT.sync = true File.open(__FILE__) do |file| def file.size # Simulates some strange Windows behaviour raise SystemCallError.new "Unknown Error (20047)" end assert_nothing_raised do @client.post(serverurl + 'servlet', {1=>2, 3=>file}) end end end def test_post_with_io # streaming, but not chunked myio = StringIO.new("X" * (HTTP::Message::Body::DEFAULT_CHUNK_SIZE + 1)) def myio.read(*args) @called ||= 0 @called += 1 super end def myio.called @called end @client.debug_dev = str = StringIO.new res = @client.post(serverurl + 'servlet', {1=>2, 3=>myio}) assert_match(/\r\nContent-Disposition: form-data; name="1"\r\n/m, res.content) assert_match(/\r\n2\r\n/m, res.content) assert_match(/\r\nContent-Disposition: form-data; name="3"; filename=""\r\n/m, res.content) assert_match(/\r\nContent-Length:/m, str.string) assert_equal(3, myio.called) end def test_post_with_io_nosize # streaming + chunked post myio = StringIO.new("4") def myio.size nil end @client.debug_dev = str = StringIO.new res = @client.post(serverurl + 'servlet', {1=>2, 3=>myio}) assert_match(/\r\nContent-Disposition: form-data; name="1"\r\n/m, res.content) assert_match(/\r\n2\r\n/m, res.content) assert_match(/\r\nContent-Disposition: form-data; name="3"; filename=""\r\n/m, res.content) assert_match(/\r\n4\r\n/m, res.content) assert_match(/\r\nTransfer-Encoding: chunked\r\n/m, str.string) end def test_post_async param = {'1'=>'2', '3'=>'4'} conn = @client.post_async(serverurl + 'servlet', param) Thread.pass while !conn.finished? res = conn.pop assert_equal(param, params(res.header["x-query"][0])) end def test_post_with_block called = false res = @client.post(serverurl + 'servlet') { |str| assert_equal('post,', str) called = true } assert(called) assert_nil(res.content) # called = false param = [['1', '2'], ['3', '4']] res = @client.post(serverurl + 'servlet', param) { |str| assert_equal('post,1=2&3=4', str) called = true } assert(called) assert_equal('1=2&3=4', res.header["x-query"][0]) assert_nil(res.content) end def test_post_with_custom_multipart ext = {'content-type' => 'multipart/form-data'} assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext) body = [{ 'Content-Disposition' => 'form-data; name="1"', :content => "2"}, { 'Content-Disposition' => 'form-data; name="3"', :content => "4"}] res = @client.post(serverurl + 'servlet', body, ext) assert_match(/Content-Disposition: form-data; name="1"/, res.content) assert_match(/Content-Disposition: form-data; name="3"/, res.content) # ext = {'content-type' => 'multipart/form-data; boundary=hello'} assert_equal("post", @client.post(serverurl + 'servlet').content[0, 4], ext) res = @client.post(serverurl + 'servlet', body, ext) assert_match(/Content-Disposition: form-data; name="1"/, res.content) assert_match(/Content-Disposition: form-data; name="3"/, res.content) assert_equal("post,--hello\r\nContent-Disposition: form-data; name=\"1\"\r\n\r\n2\r\n--hello\r\nContent-Disposition: form-data; name=\"3\"\r\n\r\n4\r\n--hello--\r\n\r\n", res.content) end def test_post_with_custom_multipart_and_file STDOUT.sync = true File.open(__FILE__) do |file| ext = { 'Content-Type' => 'multipart/alternative' } body = [{ 'Content-Type' => 'text/plain', :content => "this is only a test" }, { 'Content-Type' => 'application/x-ruby', :content => file }] res = @client.post(serverurl + 'servlet', body, ext) assert_match(/^Content-Type: text\/plain\r\n/m, res.content) assert_match(/^this is only a test\r\n/m, res.content) assert_match(/^Content-Type: application\/x-ruby\r\n/m, res.content) assert_match(/FIND_TAG_IN_THIS_FILE/, res.content) end end def test_put assert_equal("put", @client.put(serverurl + 'servlet').content) param = {'1'=>'2', '3'=>'4'} @client.debug_dev = str = '' res = @client.put(serverurl + 'servlet', param) assert_equal(param, params(res.header["x-query"][0])) assert_equal('Content-Type: application/x-www-form-urlencoded', str.split(/\r?\n/)[5]) end def test_put_bytesize res = @client.put(serverurl + 'servlet', 'txt' => 'あいうえお') assert_equal('txt=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A', res.header["x-query"][0]) assert_equal('15', res.header["x-size"][0]) end def test_put_async param = {'1'=>'2', '3'=>'4'} conn = @client.put_async(serverurl + 'servlet', param) Thread.pass while !conn.finished? res = conn.pop assert_equal(param, params(res.header["x-query"][0])) end def test_patch assert_equal("patch", @client.patch(serverurl + 'servlet').content) param = {'1'=>'2', '3'=>'4'} @client.debug_dev = str = '' res = @client.patch(serverurl + 'servlet', param) assert_equal(param, params(res.header["x-query"][0])) assert_equal('Content-Type: application/x-www-form-urlencoded', str.split(/\r?\n/)[5]) end def test_patch_async param = {'1'=>'2', '3'=>'4'} conn = @client.patch_async(serverurl + 'servlet', param) Thread.pass while !conn.finished? res = conn.pop assert_equal(param, params(res.header["x-query"][0])) end def test_delete assert_equal("delete", @client.delete(serverurl + 'servlet').content) end # Not prohibited by spec, but normally it's ignored def test_delete_with_body param = {'1'=>'2', '3'=>'4'} @client.debug_dev = str = '' assert_equal("delete", @client.delete(serverurl + 'servlet', param).content) assert_equal({'1' => ['2'], '3' => ['4']}, HTTP::Message.parse(str.split(/\r?\n\r?\n/)[2])) end def test_delete_async conn = @client.delete_async(serverurl + 'servlet') Thread.pass while !conn.finished? res = conn.pop assert_equal('delete', res.content.read) end def test_options assert_equal("options", @client.options(serverurl + 'servlet').content) end def test_options_async conn = @client.options_async(serverurl + 'servlet') Thread.pass while !conn.finished? res = conn.pop assert_equal('options', res.content.read) end def test_propfind assert_equal("propfind", @client.propfind(serverurl + 'servlet').content) end def test_propfind_async conn = @client.propfind_async(serverurl + 'servlet') Thread.pass while !conn.finished? res = conn.pop assert_equal('propfind', res.content.read) end def test_proppatch assert_equal("proppatch", @client.proppatch(serverurl + 'servlet').content) param = {'1'=>'2', '3'=>'4'} res = @client.proppatch(serverurl + 'servlet', param) assert_equal('proppatch', res.content) assert_equal(param, params(res.header["x-query"][0])) end def test_proppatch_async param = {'1'=>'2', '3'=>'4'} conn = @client.proppatch_async(serverurl + 'servlet', param) Thread.pass while !conn.finished? res = conn.pop assert_equal('proppatch', res.content.read) assert_equal(param, params(res.header["x-query"][0])) end def test_trace assert_equal("trace", @client.trace(serverurl + 'servlet').content) param = {'1'=>'2', '3'=>'4'} res = @client.trace(serverurl + 'servlet', param) assert_equal(param, params(res.header["x-query"][0])) end def test_trace_async param = {'1'=>'2', '3'=>'4'} conn = @client.trace_async(serverurl + 'servlet', param) Thread.pass while !conn.finished? res = conn.pop assert_equal(param, params(res.header["x-query"][0])) end def test_chunked assert_equal('chunked', @client.get_content(serverurl + 'chunked', { 'msg' => 'chunked' })) assert_equal('あいうえお', @client.get_content(serverurl + 'chunked', { 'msg' => 'あいうえお' })) end def test_chunked_empty assert_equal('', @client.get_content(serverurl + 'chunked', { 'msg' => '' })) end def test_get_query assert_equal({'1'=>'2'}, check_query_get({1=>2})) assert_equal({'a'=>'A', 'B'=>'b'}, check_query_get({"a"=>"A", "B"=>"b"})) assert_equal({'&'=>'&'}, check_query_get({"&"=>"&"})) assert_equal({'= '=>' =+'}, check_query_get({"= "=>" =+"})) assert_equal( ['=', '&'].sort, check_query_get([["=", "="], ["=", "&"]])['='].to_ary.sort ) assert_equal({'123'=>'45'}, check_query_get('123=45')) assert_equal({'12 3'=>'45', ' '=>' '}, check_query_get('12+3=45&+=+')) assert_equal({}, check_query_get('')) assert_equal({'1'=>'2'}, check_query_get({1=>StringIO.new('2')})) assert_equal({'1'=>'2', '3'=>'4'}, check_query_get(StringIO.new('3=4&1=2'))) hash = check_query_get({"a"=>["A","a"], "B"=>"b"}) assert_equal({'a'=>'A', 'B'=>'b'}, hash) assert_equal(['A','a'], hash['a'].to_ary) hash = check_query_get({"a"=>WEBrick::HTTPUtils::FormData.new("A","a"), "B"=>"b"}) assert_equal({'a'=>'A', 'B'=>'b'}, hash) assert_equal(['A','a'], hash['a'].to_ary) hash = check_query_get({"a"=>[StringIO.new("A"),StringIO.new("a")], "B"=>StringIO.new("b")}) assert_equal({'a'=>'A', 'B'=>'b'}, hash) assert_equal(['A','a'], hash['a'].to_ary) end def test_post_body assert_equal({'1'=>'2'}, check_query_post({1=>2})) assert_equal({'a'=>'A', 'B'=>'b'}, check_query_post({"a"=>"A", "B"=>"b"})) assert_equal({'&'=>'&'}, check_query_post({"&"=>"&"})) assert_equal({'= '=>' =+'}, check_query_post({"= "=>" =+"})) assert_equal( ['=', '&'].sort, check_query_post([["=", "="], ["=", "&"]])['='].to_ary.sort ) assert_equal({'123'=>'45'}, check_query_post('123=45')) assert_equal({'12 3'=>'45', ' '=>' '}, check_query_post('12+3=45&+=+')) assert_equal({}, check_query_post('')) # post_body = StringIO.new("foo=bar&foo=baz") assert_equal( ["bar", "baz"], check_query_post(post_body)["foo"].to_ary.sort ) end def test_extra_headers str = "" @client.debug_dev = str @client.head(serverurl, nil, {"ABC" => "DEF"}) lines = str.split(/(?:\r?\n)+/) assert_equal("= Request", lines[0]) assert_match("ABC: DEF", lines[4]) # str = "" @client.debug_dev = str @client.get(serverurl, nil, [["ABC", "DEF"], ["ABC", "DEF"]]) lines = str.split(/(?:\r?\n)+/) assert_equal("= Request", lines[0]) assert_match("ABC: DEF", lines[4]) assert_match("ABC: DEF", lines[5]) end def test_http_custom_date_header @client.debug_dev = (str = "") res = @client.get(serverurl + 'hello', :header => {'Date' => 'foo'}) lines = str.split(/(?:\r?\n)+/) assert_equal('Date: foo', lines[4]) end def test_timeout assert_equal(60, @client.connect_timeout) assert_equal(120, @client.send_timeout) assert_equal(60, @client.receive_timeout) # @client.connect_timeout = 1 @client.send_timeout = 2 @client.receive_timeout = 3 assert_equal(1, @client.connect_timeout) assert_equal(2, @client.send_timeout) assert_equal(3, @client.receive_timeout) end def test_connect_timeout # ToDo end def test_send_timeout # ToDo end def test_receive_timeout # this test takes 2 sec assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=2')) @client.receive_timeout = 1 assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=0')) assert_raise(HTTPClient::ReceiveTimeoutError) do @client.get_content(serverurl + 'sleep?sec=2') end @client.receive_timeout = 3 assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=2')) end def test_receive_timeout_post # this test takes 2 sec assert_equal('hello', @client.post(serverurl + 'sleep', :sec => 2).content) @client.receive_timeout = 1 assert_equal('hello', @client.post(serverurl + 'sleep', :sec => 0).content) assert_raise(HTTPClient::ReceiveTimeoutError) do @client.post(serverurl + 'sleep', :sec => 2) end @client.receive_timeout = 3 assert_equal('hello', @client.post(serverurl + 'sleep', :sec => 2).content) end def test_reset url = serverurl + 'servlet' assert_nothing_raised do 5.times do @client.get(url) @client.reset(url) end end end def test_reset_all assert_nothing_raised do 5.times do @client.get(serverurl + 'servlet') @client.reset_all end end end def test_cookies cookiefile = File.join(File.dirname(File.expand_path(__FILE__)), 'test_cookies_file') File.open(cookiefile, "wb") do |f| f << "http://rubyforge.org/account/login.php\tsession_ser\tLjEwMy45Ni40Ni0q%2A-fa0537de8cc31\t2000000000\t.rubyforge.org\t/\t13\n" end @client.set_cookie_store(cookiefile) cookie = @client.cookie_manager.cookies.first url = cookie.url assert(cookie.domain_match(url.host, cookie.domain)) # @client.reset_all @client.test_loopback_http_response << "HTTP/1.0 200 OK\nSet-Cookie: foo=bar; expires=#{Time.at(1924873200).gmtime.httpdate}\n\nOK" @client.get_content('http://rubyforge.org/account/login.php') @client.save_cookie_store str = File.read(cookiefile) assert_match(%r(http://rubyforge.org/account/login.php\tfoo\tbar\t1924873200\trubyforge.org\t/account\t1), str) File.unlink(cookiefile) end def test_eof_error_length io = StringIO.new('') def io.gets(*arg) @buf ||= ["HTTP/1.0 200 OK\n", "content-length: 123\n", "\n"] @buf.shift end def io.readpartial(size, buf) @second ||= false if !@second @second = '1st' buf << "abc" buf elsif @second == '1st' @second = '2nd' raise EOFError.new else raise Exception.new end end def io.eof? true end @client.test_loopback_http_response << io assert_nothing_raised do @client.get('http://foo/bar') end end def test_eof_error_rest io = StringIO.new('') def io.gets(*arg) @buf ||= ["HTTP/1.0 200 OK\n", "\n"] @buf.shift end def io.readpartial(size, buf) @second ||= false if !@second @second = '1st' buf << "abc" buf elsif @second == '1st' @second = '2nd' raise EOFError.new else raise Exception.new end end def io.eof? true end @client.test_loopback_http_response << io assert_nothing_raised do @client.get('http://foo/bar') end end def test_connection c = HTTPClient::Connection.new assert(c.finished?) assert_nil(c.join) end def test_site site = HTTPClient::Site.new assert_equal('tcp', site.scheme) assert_equal('0.0.0.0', site.host) assert_equal(0, site.port) assert_equal('tcp://0.0.0.0:0', site.addr) assert_equal('tcp://0.0.0.0:0', site.to_s) assert_nothing_raised do site.inspect end # site = HTTPClient::Site.new(urify('http://localhost:12345/foo')) assert_equal('http', site.scheme) assert_equal('localhost', site.host) assert_equal(12345, site.port) assert_equal('http://localhost:12345', site.addr) assert_equal('http://localhost:12345', site.to_s) assert_nothing_raised do site.inspect end # site1 = HTTPClient::Site.new(urify('http://localhost:12341/')) site2 = HTTPClient::Site.new(urify('http://localhost:12342/')) site3 = HTTPClient::Site.new(urify('http://localhost:12342/')) assert(!(site1 == site2)) h = { site1 => 'site1', site2 => 'site2' } h[site3] = 'site3' assert_equal('site1', h[site1]) assert_equal('site3', h[site2]) end def test_http_header res = @client.get(serverurl + 'hello') assert_equal('text/html', res.contenttype) assert_equal(5, res.header.get(nil).size) # res.header.delete('connection') assert_equal(4, res.header.get(nil).size) # res.header['foo'] = 'bar' assert_equal(['bar'], res.header['foo']) # assert_equal([['foo', 'bar']], res.header.get('foo')) res.header['foo'] = ['bar', 'bar2'] assert_equal([['foo', 'bar'], ['foo', 'bar2']], res.header.get('foo')) end def test_session_manager mgr = HTTPClient::SessionManager.new(@client) assert_nil(mgr.instance_eval { @proxy }) assert_nil(mgr.debug_dev) @client.debug_dev = Object.new @client.proxy = 'http://myproxy:12345' mgr = HTTPClient::SessionManager.new(@client) assert_equal('http://myproxy:12345', mgr.instance_eval { @proxy }.to_s) assert_equal(@client.debug_dev, mgr.debug_dev) end def test_socket_local @client.socket_local.host = '127.0.0.1' assert_equal('hello', @client.get_content(serverurl + 'hello')) @client.reset_all @client.socket_local.port = serverport begin @client.get_content(serverurl + 'hello') rescue Errno::EADDRINUSE, SocketError assert(true) end end def test_body_param_order ary = ('b'..'d').map { |k| ['key2', k] } << ['key1', 'a'] << ['key3', 'z'] assert_equal("key2=b&key2=c&key2=d&key1=a&key3=z", HTTP::Message.escape_query(ary)) end if RUBY_VERSION > "1.9" def test_charset body = @client.get(serverurl + 'charset').body assert_equal(Encoding::EUC_JP, body.encoding) assert_equal('あいうえお'.encode(Encoding::EUC_JP), body) end end if RUBY_VERSION >= "1.9.3" def test_continue @client.debug_dev = str = '' res = @client.get(serverurl + 'continue', :header => {:Expect => '100-continue'}) assert_equal(200, res.status) assert_equal('done!', res.body) assert_match(/Expect: 100-continue/, str) end end def test_ipv6literaladdress_in_uri server = TCPServer.open('::1', 0) rescue return # Skip if IPv6 is unavailable. server_thread = Thread.new { Thread.abort_on_exception = true sock = server.accept while line = sock.gets break if line.chomp.empty? end sock.write("HTTP/1.1 200 OK\r\n") sock.write("Content-Length: 5\r\n") sock.write("\r\n") sock.write("12345") sock.close } uri = "http://[::1]:#{server.addr[1]}/" begin assert_equal('12345', @client.get(uri).body) ensure server.close server_thread.kill server_thread.join end end private def check_query_get(query) WEBrick::HTTPUtils.parse_query( @client.get(serverurl + 'servlet', query).header["x-query"][0] ) end def check_query_post(query) WEBrick::HTTPUtils.parse_query( @client.post(serverurl + 'servlet', query).header["x-query"][0] ) end end