diff options
Diffstat (limited to 'test/net/http')
-rw-r--r-- | test/net/http/test_http.rb | 140 | ||||
-rw-r--r-- | test/net/http/test_http_request.rb | 5 | ||||
-rw-r--r-- | test/net/http/test_httpheader.rb | 27 | ||||
-rw-r--r-- | test/net/http/test_httpresponse.rb | 287 | ||||
-rw-r--r-- | test/net/http/test_https.rb | 18 | ||||
-rw-r--r-- | test/net/http/test_https_proxy.rb | 2 |
6 files changed, 450 insertions, 29 deletions
diff --git a/test/net/http/test_http.rb b/test/net/http/test_http.rb index c859021956..f0f1bc2d8f 100644 --- a/test/net/http/test_http.rb +++ b/test/net/http/test_http.rb @@ -126,10 +126,10 @@ class TestNetHTTP < Test::Unit::TestCase def test_proxy_address_no_proxy TestNetHTTPUtils.clean_http_proxy_env do - http = Net::HTTP.new 'hostname.example', nil, 'proxy.example', nil, nil, nil, 'example' + http = Net::HTTP.new 'hostname.example', nil, 'proxy.com', nil, nil, nil, 'example' assert_nil http.proxy_address - http = Net::HTTP.new '10.224.1.1', nil, 'proxy.example', nil, nil, nil, 'example,10.224.0.0/22' + http = Net::HTTP.new '10.224.1.1', nil, 'proxy.com', nil, nil, nil, 'example,10.224.0.0/22' assert_nil http.proxy_address end end @@ -178,13 +178,8 @@ class TestNetHTTP < Test::Unit::TestCase http = Net::HTTP.new 'hostname.example' assert_equal true, http.proxy? - if Net::HTTP::ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE - assert_equal 'foo', http.proxy_user - assert_equal 'bar', http.proxy_pass - else - assert_nil http.proxy_user - assert_nil http.proxy_pass - end + assert_equal 'foo', http.proxy_user + assert_equal 'bar', http.proxy_pass end end @@ -195,13 +190,8 @@ class TestNetHTTP < Test::Unit::TestCase http = Net::HTTP.new 'hostname.example' assert_equal true, http.proxy? - if Net::HTTP::ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE - assert_equal "Y\\X", http.proxy_user - assert_equal "R%S] ?X", http.proxy_pass - else - assert_nil http.proxy_user - assert_nil http.proxy_pass - end + assert_equal "Y\\X", http.proxy_user + assert_equal "R%S] ?X", http.proxy_pass end end @@ -1168,6 +1158,30 @@ class TestNetHTTPKeepAlive < Test::Unit::TestCase } end + def test_keep_alive_reset_on_new_connection + # Using WEBrick's debug log output on accepting connection: + # + # "[2021-04-29 20:36:46] DEBUG accept: 127.0.0.1:50674\n" + @log_tester = nil + @server.logger.level = WEBrick::BasicLog::DEBUG + + start {|http| + res = http.get('/') + http.keep_alive_timeout = 1 + assert_kind_of Net::HTTPResponse, res + assert_kind_of String, res.body + http.finish + assert_equal 1, @log.grep(/accept/i).size + + sleep 1.5 + http.start + res = http.get('/') + assert_kind_of Net::HTTPResponse, res + assert_kind_of String, res.body + assert_equal 2, @log.grep(/accept/i).size + } + end + class MockSocket attr_reader :count def initialize(success_after: nil) @@ -1220,6 +1234,16 @@ class TestNetHTTPKeepAlive < Test::Unit::TestCase } end + def test_http_retry_failed_with_block + start {|http| + http.max_retries = 10 + called = 0 + assert_raise(Errno::ECONNRESET){ http.get('/'){called += 1; raise Errno::ECONNRESET} } + assert_equal 1, called + } + @log_tester = nil + end + def test_keep_alive_server_close def @server.run(sock) sock.close @@ -1270,3 +1294,87 @@ class TestNetHTTPLocalBind < Test::Unit::TestCase end end +class TestNetHTTPForceEncoding < Test::Unit::TestCase + CONFIG = { + 'host' => 'localhost', + 'proxy_host' => nil, + 'proxy_port' => nil, + } + + include TestNetHTTPUtils + + def fe_request(force_enc, content_type=nil) + @server.mount_proc('/fe') do |req, res| + res['Content-Type'] = content_type if content_type + res.body = "hello\u1234" + end + + http = Net::HTTP.new(config('host'), config('port')) + http.local_host = Addrinfo.tcp(config('host'), config('port')).ip_address + assert_not_nil(http.local_host) + assert_nil(http.local_port) + + http.response_body_encoding = force_enc + http.get('/fe') + end + + def test_response_body_encoding_false + res = fe_request(false) + assert_equal("hello\u1234".b, res.body) + assert_equal(Encoding::ASCII_8BIT, res.body.encoding) + end + + def test_response_body_encoding_true_without_content_type + res = fe_request(true) + assert_equal("hello\u1234".b, res.body) + assert_equal(Encoding::ASCII_8BIT, res.body.encoding) + end + + def test_response_body_encoding_true_with_content_type + res = fe_request(true, 'text/html; charset=utf-8') + assert_equal("hello\u1234", res.body) + assert_equal(Encoding::UTF_8, res.body.encoding) + end + + def test_response_body_encoding_string_without_content_type + res = fe_request('utf-8') + assert_equal("hello\u1234", res.body) + assert_equal(Encoding::UTF_8, res.body.encoding) + end + + def test_response_body_encoding_encoding_without_content_type + res = fe_request(Encoding::UTF_8) + assert_equal("hello\u1234", res.body) + assert_equal(Encoding::UTF_8, res.body.encoding) + end +end + +class TestNetHTTPPartialResponse < Test::Unit::TestCase + CONFIG = { + 'host' => '127.0.0.1', + 'proxy_host' => nil, + 'proxy_port' => nil, + } + + include TestNetHTTPUtils + + def test_partial_response + str = "0123456789" + @server.mount_proc('/') do |req, res| + res.status = 200 + res['Content-Type'] = 'text/plain' + + res.body = str + res['Content-Length'] = str.length + 1 + end + @server.mount_proc('/show_ip') { |req, res| res.body = req.remote_ip } + + http = Net::HTTP.new(config('host'), config('port')) + res = http.get('/') + assert_equal(str, res.body) + + http = Net::HTTP.new(config('host'), config('port')) + http.ignore_eof = false + assert_raise(EOFError) {http.get('/')} + end +end diff --git a/test/net/http/test_http_request.rb b/test/net/http/test_http_request.rb index 239b2d1009..7fd82b0353 100644 --- a/test/net/http/test_http_request.rb +++ b/test/net/http/test_http_request.rb @@ -46,8 +46,9 @@ class HTTPRequestTest < Test::Unit::TestCase assert_not_predicate req, :response_body_permitted? expected = { - 'accept' => %w[*/*], - 'user-agent' => %w[Ruby], + 'accept' => %w[*/*], + "accept-encoding" => %w[gzip;q=1.0,deflate;q=0.6,identity;q=0.3], + 'user-agent' => %w[Ruby], } assert_equal expected, req.to_hash diff --git a/test/net/http/test_httpheader.rb b/test/net/http/test_httpheader.rb index cfbe36bcfd..69563168db 100644 --- a/test/net/http/test_httpheader.rb +++ b/test/net/http/test_httpheader.rb @@ -28,7 +28,11 @@ class HTTPHeaderTest < Test::Unit::TestCase assert_raise(NoMethodError){ @c.initialize_http_header("foo"=>[]) } assert_raise(ArgumentError){ @c.initialize_http_header("foo"=>"a\nb") } assert_raise(ArgumentError){ @c.initialize_http_header("foo"=>"a\rb") } - assert_raise(ArgumentError){ @c.initialize_http_header("foo"=>"a\xff") } + end + + def test_initialize_with_broken_coderange + error = RUBY_VERSION >= "3.2" ? Encoding::CompatibilityError : ArgumentError + assert_raise(error){ @c.initialize_http_header("foo"=>"a\xff") } end def test_initialize_with_symbol @@ -308,6 +312,18 @@ class HTTPHeaderTest < Test::Unit::TestCase end def test_content_range + @c['Content-Range'] = "bytes 0-499/1000" + assert_equal 0..499, @c.content_range + @c['Content-Range'] = "bytes 1-500/1000" + assert_equal 1..500, @c.content_range + @c['Content-Range'] = "bytes 1-1/1000" + assert_equal 1..1, @c.content_range + @c['Content-Range'] = "tokens 1-1/1000" + assert_equal nil, @c.content_range + + try_invalid_content_range "invalid" + try_invalid_content_range "bytes 123-abc" + try_invalid_content_range "bytes abc-123" end def test_range_length @@ -317,6 +333,15 @@ class HTTPHeaderTest < Test::Unit::TestCase assert_equal 500, @c.range_length @c['Content-Range'] = "bytes 1-1/1000" assert_equal 1, @c.range_length + @c['Content-Range'] = "tokens 1-1/1000" + assert_equal nil, @c.range_length + + try_invalid_content_range "bytes 1-1/abc" + end + + def try_invalid_content_range(s) + @c['Content-Range'] = "#{s}" + assert_raise(Net::HTTPHeaderSyntaxError, s){ @c.content_range } end def test_chunked? diff --git a/test/net/http/test_httpresponse.rb b/test/net/http/test_httpresponse.rb index 00b0072e70..01281063cd 100644 --- a/test/net/http/test_httpresponse.rb +++ b/test/net/http/test_httpresponse.rb @@ -54,6 +54,241 @@ EOS assert_equal 'hello', body end + def test_read_body_body_encoding_false + body = "hello\u1234" + io = dummy_io(<<EOS) +HTTP/1.1 200 OK +Connection: close +Content-Length: #{body.bytesize} + +#{body} +EOS + + res = Net::HTTPResponse.read_new(io) + + body = nil + + res.reading_body io, true do + body = res.read_body + end + + assert_equal "hello\u1234".b, body + assert_equal Encoding::ASCII_8BIT, body.encoding + end + + def test_read_body_body_encoding_encoding + body = "hello\u1234" + io = dummy_io(<<EOS) +HTTP/1.1 200 OK +Connection: close +Content-Length: #{body.bytesize} + +#{body} +EOS + + res = Net::HTTPResponse.read_new(io) + res.body_encoding = Encoding.find('utf-8') + + body = nil + + res.reading_body io, true do + body = res.read_body + end + + assert_equal "hello\u1234", body + assert_equal Encoding::UTF_8, body.encoding + end + + def test_read_body_body_encoding_string + body = "hello\u1234" + io = dummy_io(<<EOS) +HTTP/1.1 200 OK +Connection: close +Content-Length: #{body.bytesize} + +#{body} +EOS + + res = Net::HTTPResponse.read_new(io) + res.body_encoding = 'utf-8' + + body = nil + + res.reading_body io, true do + body = res.read_body + end + + assert_equal "hello\u1234", body + assert_equal Encoding::UTF_8, body.encoding + end + + def test_read_body_body_encoding_true_without_content_type_header + body = "hello\u1234" + io = dummy_io(<<EOS) +HTTP/1.1 200 OK +Connection: close +Content-Length: #{body.bytesize} + +#{body} +EOS + + res = Net::HTTPResponse.read_new(io) + res.body_encoding = true + + body = nil + + res.reading_body io, true do + body = res.read_body + end + + assert_equal "hello\u1234".b, body + assert_equal Encoding::ASCII_8BIT, body.encoding + end + + def test_read_body_body_encoding_true_with_utf8_content_type_header + body = "hello\u1234" + io = dummy_io(<<EOS) +HTTP/1.1 200 OK +Connection: close +Content-Length: #{body.bytesize} +Content-Type: text/plain; charset=utf-8 + +#{body} +EOS + + res = Net::HTTPResponse.read_new(io) + res.body_encoding = true + + body = nil + + res.reading_body io, true do + body = res.read_body + end + + assert_equal "hello\u1234", body + assert_equal Encoding::UTF_8, body.encoding + end + + def test_read_body_body_encoding_true_with_iso_8859_1_content_type_header + body = "hello\u1234" + io = dummy_io(<<EOS) +HTTP/1.1 200 OK +Connection: close +Content-Length: #{body.bytesize} +Content-Type: text/plain; charset=iso-8859-1 + +#{body} +EOS + + res = Net::HTTPResponse.read_new(io) + res.body_encoding = true + + body = nil + + res.reading_body io, true do + body = res.read_body + end + + assert_equal "hello\u1234".force_encoding("ISO-8859-1"), body + assert_equal Encoding::ISO_8859_1, body.encoding + end + + def test_read_body_body_encoding_true_with_utf8_meta_charset + res_body = "<html><meta charset=\"utf-8\">hello\u1234</html>" + io = dummy_io(<<EOS) +HTTP/1.1 200 OK +Connection: close +Content-Length: #{res_body.bytesize} +Content-Type: text/html + +#{res_body} +EOS + + res = Net::HTTPResponse.read_new(io) + res.body_encoding = true + + body = nil + + res.reading_body io, true do + body = res.read_body + end + + assert_equal res_body, body + assert_equal Encoding::UTF_8, body.encoding + end + + def test_read_body_body_encoding_true_with_iso8859_1_meta_charset + res_body = "<html><meta charset=\"iso-8859-1\">hello\u1234</html>" + io = dummy_io(<<EOS) +HTTP/1.1 200 OK +Connection: close +Content-Length: #{res_body.bytesize} +Content-Type: text/html + +#{res_body} +EOS + + res = Net::HTTPResponse.read_new(io) + res.body_encoding = true + + body = nil + + res.reading_body io, true do + body = res.read_body + end + + assert_equal res_body.force_encoding("ISO-8859-1"), body + assert_equal Encoding::ISO_8859_1, body.encoding + end + + def test_read_body_body_encoding_true_with_utf8_meta_content_charset + res_body = "<meta http-equiv='content-type' content='text/html; charset=UTF-8'>hello\u1234</html>" + io = dummy_io(<<EOS) +HTTP/1.1 200 OK +Connection: close +Content-Length: #{res_body.bytesize} +Content-Type: text/html + +#{res_body} +EOS + + res = Net::HTTPResponse.read_new(io) + res.body_encoding = true + + body = nil + + res.reading_body io, true do + body = res.read_body + end + + assert_equal res_body, body + assert_equal Encoding::UTF_8, body.encoding + end + + def test_read_body_body_encoding_true_with_iso8859_1_meta_content_charset + res_body = "<meta http-equiv='content-type' content='text/html; charset=ISO-8859-1'>hello\u1234</html>" + io = dummy_io(<<EOS) +HTTP/1.1 200 OK +Connection: close +Content-Length: #{res_body.bytesize} +Content-Type: text/html + +#{res_body} +EOS + + res = Net::HTTPResponse.read_new(io) + res.body_encoding = true + + body = nil + + res.reading_body io, true do + body = res.read_body + end + + assert_equal res_body.force_encoding("ISO-8859-1"), body + assert_equal Encoding::ISO_8859_1, body.encoding + end + def test_read_body_block io = dummy_io(<<EOS) HTTP/1.1 200 OK @@ -77,8 +312,8 @@ EOS end def test_read_body_block_mod - # http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/3019353 - if defined?(RubyVM::JIT) ? RubyVM::JIT.enabled? : defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? + # http://ci.rvm.jp/results/trunk-rjit-wait@silicon-docker/3019353 + if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? omit 'too unstable with --jit-wait, and extending read_timeout did not help it' end IO.pipe do |r, w| @@ -127,9 +362,11 @@ EOS if Net::HTTP::HAVE_ZLIB assert_equal nil, res['content-encoding'] + assert_equal '5', res['content-length'] assert_equal 'hello', body else assert_equal 'deflate', res['content-encoding'] + assert_equal '13', res['content-length'] assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15", body end end @@ -155,9 +392,11 @@ EOS if Net::HTTP::HAVE_ZLIB assert_equal nil, res['content-encoding'] + assert_equal '5', res['content-length'] assert_equal 'hello', body else assert_equal 'DEFLATE', res['content-encoding'] + assert_equal '13', res['content-length'] assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15", body end end @@ -188,9 +427,11 @@ EOS if Net::HTTP::HAVE_ZLIB assert_equal nil, res['content-encoding'] + assert_equal nil, res['content-length'] assert_equal 'hello', body else assert_equal 'deflate', res['content-encoding'] + assert_equal nil, res['content-length'] assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15", body end end @@ -215,6 +456,7 @@ EOS end assert_equal 'deflate', res['content-encoding'], 'Bug #7831' + assert_equal '13', res['content-length'] assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15", body, 'Bug #7381' end @@ -238,9 +480,11 @@ EOS if Net::HTTP::HAVE_ZLIB assert_equal nil, res['content-encoding'] + assert_equal nil, res['content-length'] assert_equal 'hello', body else assert_equal 'deflate', res['content-encoding'] + assert_equal nil, res['content-length'] assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15\r\n", body end end @@ -288,9 +532,11 @@ EOS if Net::HTTP::HAVE_ZLIB assert_equal nil, res['content-encoding'] + assert_equal '0', res['content-length'] assert_equal '', body else assert_equal 'deflate', res['content-encoding'] + assert_equal '0', res['content-length'] assert_equal '', body end end @@ -314,9 +560,11 @@ EOS if Net::HTTP::HAVE_ZLIB assert_equal nil, res['content-encoding'] + assert_equal nil, res['content-length'] assert_equal '', body else assert_equal 'deflate', res['content-encoding'] + assert_equal nil, res['content-length'] assert_equal '', body end end @@ -341,6 +589,41 @@ EOS assert_equal 'hello', body end + def test_read_body_receiving_no_body + io = dummy_io(<<EOS) +HTTP/1.1 204 OK +Connection: close + +EOS + + res = Net::HTTPResponse.read_new(io) + res.body_encoding = 'utf-8' + + body = 'something to override' + + res.reading_body io, true do + body = res.read_body + end + + assert_equal nil, body + assert_equal nil, res.body + end + + def test_read_body_outside_of_reading_body + io = dummy_io(<<EOS) +HTTP/1.1 200 OK +Connection: close +Content-Length: 0 + +EOS + + res = Net::HTTPResponse.read_new(io) + + assert_raise IOError do + res.read_body + end + end + def test_uri_equals uri = URI 'http://example' diff --git a/test/net/http/test_https.rb b/test/net/http/test_https.rb index 4dc9f1b026..cf297f3755 100644 --- a/test/net/http/test_https.rb +++ b/test/net/http/test_https.rb @@ -137,7 +137,7 @@ class TestNetHTTPS < Test::Unit::TestCase def test_session_reuse # FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h. # See https://github.com/openssl/openssl/pull/5967 for details. - skip if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /OpenSSL 1.1.0h/ + omit if OpenSSL::OPENSSL_LIBRARY_VERSION.include?('OpenSSL 1.1.0h') http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true @@ -148,23 +148,27 @@ class TestNetHTTPS < Test::Unit::TestCase # support session resuse. Limiting the version to the TLSv1.2 stack allows # this test to continue to work on LibreSSL 3.2+. LibreSSL may eventually # support session reuse, but there are no current plans to do so. - http.ssl_version = :TLSv1 + http.ssl_version = :TLSv1_2 end http.start - assert_equal false, http.instance_variable_get(:@socket).io.session_reused? + session_reused = http.instance_variable_get(:@socket).io.session_reused? + assert_false session_reused unless session_reused.nil? # can not detect re-use under JRuby http.get("/") http.finish http.start - assert_equal true, http.instance_variable_get(:@socket).io.session_reused? + session_reused = http.instance_variable_get(:@socket).io.session_reused? + assert_true session_reused unless session_reused.nil? # can not detect re-use under JRuby assert_equal $test_net_http_data, http.get("/").body http.finish end def test_session_reuse_but_expire # FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h. - skip if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /OpenSSL 1.1.0h/ + omit if OpenSSL::OPENSSL_LIBRARY_VERSION.include?('OpenSSL 1.1.0h') + omit if OpenSSL::OPENSSL_LIBRARY_VERSION.include?('OpenSSL 3.2.') + omit if OpenSSL::OPENSSL_LIBRARY_VERSION.include?('OpenSSL 3.3.') http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true @@ -179,7 +183,7 @@ class TestNetHTTPS < Test::Unit::TestCase http.get("/") socket = http.instance_variable_get(:@socket).io - assert_equal false, socket.session_reused? + assert_equal false, socket.session_reused?, "NOTE: OpenSSL library version is #{OpenSSL::OPENSSL_LIBRARY_VERSION}" http.finish end @@ -301,7 +305,7 @@ class TestNetHTTPS < Test::Unit::TestCase ex = assert_raise(OpenSSL::SSL::SSLError){ http.request_get("/") {|res| } } - re_msg = /\ASSL_connect returned=1 errno=0 |SSL_CTX_set_max_proto_version/ + re_msg = /\ASSL_connect returned=1 errno=0 |SSL_CTX_set_max_proto_version|No appropriate protocol/ assert_match(re_msg, ex.message) end diff --git a/test/net/http/test_https_proxy.rb b/test/net/http/test_https_proxy.rb index f833f1a1e3..4c2a92ccd6 100644 --- a/test/net/http/test_https_proxy.rb +++ b/test/net/http/test_https_proxy.rb @@ -10,7 +10,7 @@ class HTTPSProxyTest < Test::Unit::TestCase begin OpenSSL rescue LoadError - skip 'autoload problem. see [ruby-dev:45021][Bug #5786]' + omit 'autoload problem. see [ruby-dev:45021][Bug #5786]' end TCPServer.open("127.0.0.1", 0) {|serv| |