summaryrefslogtreecommitdiff
path: root/test/webrick/test_httpserver.rb
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2020-11-02 13:44:28 +0900
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2020-12-10 18:06:25 +0900
commit5dc786bf86bb6e0da2639f88659598ec8b9db30d (patch)
tree87cc4d68088fc7c2616c7c1bef44c36ca10fa01f /test/webrick/test_httpserver.rb
parent46d3ea2c2569e2e5a9ee3e7e206f07f0f8b693f5 (diff)
Move webrick library into internal test toolchain
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3729
Diffstat (limited to 'test/webrick/test_httpserver.rb')
-rw-r--r--test/webrick/test_httpserver.rb543
1 files changed, 0 insertions, 543 deletions
diff --git a/test/webrick/test_httpserver.rb b/test/webrick/test_httpserver.rb
deleted file mode 100644
index 4133be85ad..0000000000
--- a/test/webrick/test_httpserver.rb
+++ /dev/null
@@ -1,543 +0,0 @@
-# frozen_string_literal: false
-require "test/unit"
-require "net/http"
-require "webrick"
-require_relative "utils"
-
-class TestWEBrickHTTPServer < Test::Unit::TestCase
- empty_log = Object.new
- def empty_log.<<(str)
- assert_equal('', str)
- self
- end
- NoLog = WEBrick::Log.new(empty_log, WEBrick::BasicLog::WARN)
-
- def teardown
- WEBrick::Utils::TimeoutHandler.terminate
- super
- end
-
- def test_mount
- httpd = WEBrick::HTTPServer.new(
- :Logger => NoLog,
- :DoNotListen=>true
- )
- httpd.mount("/", :Root)
- httpd.mount("/foo", :Foo)
- httpd.mount("/foo/bar", :Bar, :bar1)
- httpd.mount("/foo/bar/baz", :Baz, :baz1, :baz2)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/")
- assert_equal(:Root, serv)
- assert_equal([], opts)
- assert_equal("", script_name)
- assert_equal("/", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/sub")
- assert_equal(:Root, serv)
- assert_equal([], opts)
- assert_equal("", script_name)
- assert_equal("/sub", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/sub/")
- assert_equal(:Root, serv)
- assert_equal([], opts)
- assert_equal("", script_name)
- assert_equal("/sub/", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/foo")
- assert_equal(:Foo, serv)
- assert_equal([], opts)
- assert_equal("/foo", script_name)
- assert_equal("", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/foo/")
- assert_equal(:Foo, serv)
- assert_equal([], opts)
- assert_equal("/foo", script_name)
- assert_equal("/", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/foo/sub")
- assert_equal(:Foo, serv)
- assert_equal([], opts)
- assert_equal("/foo", script_name)
- assert_equal("/sub", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/foo/bar")
- assert_equal(:Bar, serv)
- assert_equal([:bar1], opts)
- assert_equal("/foo/bar", script_name)
- assert_equal("", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/foo/bar/baz")
- assert_equal(:Baz, serv)
- assert_equal([:baz1, :baz2], opts)
- assert_equal("/foo/bar/baz", script_name)
- assert_equal("", path_info)
- end
-
- class Req
- attr_reader :port, :host
- def initialize(addr, port, host)
- @addr, @port, @host = addr, port, host
- end
- def addr
- [0,0,0,@addr]
- end
- end
-
- def httpd(addr, port, host, ali)
- config ={
- :Logger => NoLog,
- :DoNotListen => true,
- :BindAddress => addr,
- :Port => port,
- :ServerName => host,
- :ServerAlias => ali,
- }
- return WEBrick::HTTPServer.new(config)
- end
-
- def assert_eql?(v1, v2)
- assert_equal(v1.object_id, v2.object_id)
- end
-
- def test_lookup_server
- addr1 = "192.168.100.1"
- addr2 = "192.168.100.2"
- addrz = "192.168.100.254"
- local = "127.0.0.1"
- port1 = 80
- port2 = 8080
- port3 = 10080
- portz = 32767
- name1 = "www.example.com"
- name2 = "www2.example.com"
- name3 = "www3.example.com"
- namea = "www.example.co.jp"
- nameb = "www.example.jp"
- namec = "www2.example.co.jp"
- named = "www2.example.jp"
- namez = "foobar.example.com"
- alias1 = [namea, nameb]
- alias2 = [namec, named]
-
- host1 = httpd(nil, port1, name1, nil)
- hosts = [
- host2 = httpd(addr1, port1, name1, nil),
- host3 = httpd(addr1, port1, name2, alias1),
- host4 = httpd(addr1, port2, name1, nil),
- host5 = httpd(addr1, port2, name2, alias1),
- httpd(addr1, port2, name3, alias2),
- host7 = httpd(addr2, nil, name1, nil),
- host8 = httpd(addr2, nil, name2, alias1),
- httpd(addr2, nil, name3, alias2),
- host10 = httpd(local, nil, nil, nil),
- host11 = httpd(nil, port3, nil, nil),
- ].sort_by{ rand }
- hosts.each{|h| host1.virtual_host(h) }
-
- # connect to addr1
- assert_eql?(host2, host1.lookup_server(Req.new(addr1, port1, name1)))
- assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, name2)))
- assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, namea)))
- assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, port1, namez)))
- assert_eql?(host4, host1.lookup_server(Req.new(addr1, port2, name1)))
- assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, name2)))
- assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, namea)))
- assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, port2, namez)))
- assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, name1)))
- assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, name2)))
- assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, namea)))
- assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, nameb)))
- assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, namez)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, name1)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, name2)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, namea)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, namez)))
-
- # connect to addr2
- assert_eql?(host7, host1.lookup_server(Req.new(addr2, port1, name1)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, name2)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, namea)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr2, port1, namez)))
- assert_eql?(host7, host1.lookup_server(Req.new(addr2, port2, name1)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, name2)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, namea)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr2, port2, namez)))
- assert_eql?(host7, host1.lookup_server(Req.new(addr2, port3, name1)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, name2)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, namea)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, nameb)))
- assert_eql?(host11, host1.lookup_server(Req.new(addr2, port3, namez)))
- assert_eql?(host7, host1.lookup_server(Req.new(addr2, portz, name1)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, name2)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, namea)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr2, portz, namez)))
-
- # connect to addrz
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, name1)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, name2)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, namea)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, namez)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, name1)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, name2)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, namea)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, namez)))
- assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, name1)))
- assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, name2)))
- assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, namea)))
- assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, nameb)))
- assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, namez)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, name1)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, name2)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, namea)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, namez)))
-
- # connect to localhost
- assert_eql?(host10, host1.lookup_server(Req.new(local, port1, name1)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port1, name2)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port1, namea)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port1, nameb)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port1, namez)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port2, name1)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port2, name2)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port2, namea)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port2, nameb)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port2, namez)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port3, name1)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port3, name2)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port3, namea)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port3, nameb)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port3, namez)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, portz, name1)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, portz, name2)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, portz, namea)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, portz, nameb)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, portz, namez)))
- end
-
- def test_callbacks
- accepted = started = stopped = 0
- requested0 = requested1 = 0
- config = {
- :ServerName => "localhost",
- :AcceptCallback => Proc.new{ accepted += 1 },
- :StartCallback => Proc.new{ started += 1 },
- :StopCallback => Proc.new{ stopped += 1 },
- :RequestCallback => Proc.new{|req, res| requested0 += 1 },
- }
- log_tester = lambda {|log, access_log|
- assert(log.find {|s| %r{ERROR `/' not found\.} =~ s })
- assert_equal([], log.reject {|s| %r{ERROR `/' not found\.} =~ s })
- }
- TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
- vhost_config = {
- :ServerName => "myhostname",
- :BindAddress => addr,
- :Port => port,
- :DoNotListen => true,
- :Logger => NoLog,
- :AccessLog => [],
- :RequestCallback => Proc.new{|req, res| requested1 += 1 },
- }
- server.virtual_host(WEBrick::HTTPServer.new(vhost_config))
-
- Thread.pass while server.status != :Running
- sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # server.status behaves unexpectedly with --jit-wait
- assert_equal(1, started, log.call)
- assert_equal(0, stopped, log.call)
- assert_equal(0, accepted, log.call)
-
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/")
- req["Host"] = "myhostname:#{port}"
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- req["Host"] = "localhost:#{port}"
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- assert_equal(6, accepted, log.call)
- assert_equal(3, requested0, log.call)
- assert_equal(3, requested1, log.call)
- }
- assert_equal(started, 1)
- assert_equal(stopped, 1)
- end
-
- class CustomRequest < ::WEBrick::HTTPRequest; end
- class CustomResponse < ::WEBrick::HTTPResponse; end
- class CustomServer < ::WEBrick::HTTPServer
- def create_request(config)
- CustomRequest.new(config)
- end
-
- def create_response(config)
- CustomResponse.new(config)
- end
- end
-
- def test_custom_server_request_and_response
- config = { :ServerName => "localhost" }
- TestWEBrick.start_server(CustomServer, config){|server, addr, port, log|
- server.mount_proc("/", lambda {|req, res|
- assert_kind_of(CustomRequest, req)
- assert_kind_of(CustomResponse, res)
- res.body = "via custom response"
- })
- Thread.pass while server.status != :Running
-
- Net::HTTP.start(addr, port) do |http|
- req = Net::HTTP::Get.new("/")
- http.request(req){|res|
- assert_equal("via custom response", res.body)
- }
- server.shutdown
- end
- }
- end
-
- # This class is needed by test_response_io_with_chunked_set method
- class EventManagerForChunkedResponseTest
- def initialize
- @listeners = []
- end
- def add_listener( &block )
- @listeners << block
- end
- def raise_str_event( str )
- @listeners.each{ |e| e.call( :str, str ) }
- end
- def raise_close_event()
- @listeners.each{ |e| e.call( :cls ) }
- end
- end
- def test_response_io_with_chunked_set
- evt_man = EventManagerForChunkedResponseTest.new
- t = Thread.new do
- begin
- config = {
- :ServerName => "localhost"
- }
- TestWEBrick.start_httpserver(config) do |server, addr, port, log|
- body_strs = [ 'aaaaaa', 'bb', 'cccc' ]
- server.mount_proc( "/", ->( req, res ){
- # Test for setting chunked...
- res.chunked = true
- r,w = IO.pipe
- evt_man.add_listener do |type,str|
- type == :cls ? ( w.close ) : ( w << str )
- end
- res.body = r
- } )
- Thread.pass while server.status != :Running
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/")
- http.request(req) do |res|
- i = 0
- evt_man.raise_str_event( body_strs[i] )
- res.read_body do |s|
- assert_equal( body_strs[i], s )
- i += 1
- if i < body_strs.length
- evt_man.raise_str_event( body_strs[i] )
- else
- evt_man.raise_close_event()
- end
- end
- assert_equal( body_strs.length, i )
- end
- end
- rescue => err
- flunk( 'exception raised in thread: ' + err.to_s )
- end
- end
- if t.join( 3 ).nil?
- evt_man.raise_close_event()
- flunk( 'timeout' )
- if t.join( 1 ).nil?
- Thread.kill t
- end
- end
- end
-
- def test_response_io_without_chunked_set
- config = {
- :ServerName => "localhost"
- }
- log_tester = lambda {|log, access_log|
- assert_equal(1, log.length)
- assert_match(/WARN Could not determine content-length of response body./, log[0])
- }
- TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
- server.mount_proc("/", lambda { |req, res|
- r,w = IO.pipe
- # Test for not setting chunked...
- # res.chunked = true
- res.body = r
- w << "foo"
- w.close
- })
- Thread.pass while server.status != :Running
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/")
- req['Connection'] = 'Keep-Alive'
- begin
- Timeout.timeout(2) do
- http.request(req){|res| assert_equal("foo", res.body) }
- end
- rescue Timeout::Error
- flunk('corrupted response')
- end
- }
- end
-
- def test_request_handler_callback_is_deprecated
- requested = 0
- config = {
- :ServerName => "localhost",
- :RequestHandler => Proc.new{|req, res| requested += 1 },
- }
- log_tester = lambda {|log, access_log|
- assert_equal(2, log.length)
- assert_match(/WARN :RequestHandler is deprecated, please use :RequestCallback/, log[0])
- assert_match(%r{ERROR `/' not found\.}, log[1])
- }
- TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
- Thread.pass while server.status != :Running
-
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/")
- req["Host"] = "localhost:#{port}"
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- assert_match(%r{:RequestHandler is deprecated, please use :RequestCallback$}, log.call, log.call)
- }
- assert_equal(1, requested)
- end
-
- def test_shutdown_with_busy_keepalive_connection
- requested = 0
- config = {
- :ServerName => "localhost",
- }
- TestWEBrick.start_httpserver(config){|server, addr, port, log|
- server.mount_proc("/", lambda {|req, res| res.body = "heffalump" })
- Thread.pass while server.status != :Running
-
- Net::HTTP.start(addr, port) do |http|
- req = Net::HTTP::Get.new("/")
- http.request(req){|res| assert_equal('Keep-Alive', res['Connection'], log.call) }
- server.shutdown
- begin
- 10.times {|n| http.request(req); requested += 1 }
- rescue
- # Errno::ECONNREFUSED or similar
- end
- end
- }
- assert_equal(0, requested, "Server responded to #{requested} requests after shutdown")
- end
-
- def test_cntrl_in_path
- log_ary = []
- access_log_ary = []
- config = {
- :Port => 0,
- :BindAddress => '127.0.0.1',
- :Logger => WEBrick::Log.new(log_ary, WEBrick::BasicLog::WARN),
- :AccessLog => [[access_log_ary, '']],
- }
- s = WEBrick::HTTPServer.new(config)
- s.mount('/foo', WEBrick::HTTPServlet::FileHandler, __FILE__)
- th = Thread.new { s.start }
- addr = s.listeners[0].addr
-
- http = Net::HTTP.new(addr[3], addr[1])
- req = Net::HTTP::Get.new('/notexist%0a/foo')
- http.request(req) { |res| assert_equal('404', res.code) }
- exp = %Q(ERROR `/notexist\\n/foo' not found.\n)
- assert_equal 1, log_ary.size
- assert_include log_ary[0], exp
- ensure
- s&.shutdown
- th&.join
- end
-
- def test_gigantic_request_header
- log_tester = lambda {|log, access_log|
- assert_equal 1, log.size
- assert_include log[0], 'ERROR headers too large'
- }
- TestWEBrick.start_httpserver({}, log_tester){|server, addr, port, log|
- server.mount('/', WEBrick::HTTPServlet::FileHandler, __FILE__)
- TCPSocket.open(addr, port) do |c|
- c.write("GET / HTTP/1.0\r\n")
- junk = -"X-Junk: #{' ' * 1024}\r\n"
- assert_raise(Errno::ECONNRESET, Errno::EPIPE, Errno::EPROTOTYPE) do
- loop { c.write(junk) }
- end
- end
- }
- end
-
- def test_eof_in_chunk
- log_tester = lambda do |log, access_log|
- assert_equal 1, log.size
- assert_include log[0], 'ERROR bad chunk data size'
- end
- TestWEBrick.start_httpserver({}, log_tester){|server, addr, port, log|
- server.mount_proc('/', ->(req, res) { res.body = req.body })
- TCPSocket.open(addr, port) do |c|
- c.write("POST / HTTP/1.1\r\nHost: example.com\r\n" \
- "Transfer-Encoding: chunked\r\n\r\n5\r\na")
- c.shutdown(Socket::SHUT_WR) # trigger EOF in server
- res = c.read
- assert_match %r{\AHTTP/1\.1 400 }, res
- end
- }
- end
-
- def test_big_chunks
- nr_out = 3
- buf = 'big' # 3 bytes is bigger than 2!
- config = { :InputBufferSize => 2 }.freeze
- total = 0
- all = ''
- TestWEBrick.start_httpserver(config){|server, addr, port, log|
- server.mount_proc('/', ->(req, res) {
- err = []
- ret = req.body do |chunk|
- n = chunk.bytesize
- n > config[:InputBufferSize] and err << "#{n} > :InputBufferSize"
- total += n
- all << chunk
- end
- ret.nil? or err << 'req.body should return nil'
- (buf * nr_out) == all or err << 'input body does not match expected'
- res.header['connection'] = 'close'
- res.body = err.join("\n")
- })
- TCPSocket.open(addr, port) do |c|
- c.write("POST / HTTP/1.1\r\nHost: example.com\r\n" \
- "Transfer-Encoding: chunked\r\n\r\n")
- chunk = "#{buf.bytesize.to_s(16)}\r\n#{buf}\r\n"
- nr_out.times { c.write(chunk) }
- c.write("0\r\n\r\n")
- head, body = c.read.split("\r\n\r\n")
- assert_match %r{\AHTTP/1\.1 200 OK}, head
- assert_nil body
- end
- }
- end
-end