Feature #15657 ยป remove-webrick.patch
gems/bundled_gems | ||
---|---|---|
power_assert 1.1.3 https://github.com/k-tsj/power_assert
|
||
rake 12.3.2 https://github.com/ruby/rake
|
||
test-unit 3.2.9 https://github.com/test-unit/test-unit
|
||
webrick 1.4.2 https://github.com/ruby/webrick
|
||
xmlrpc 0.3.0 https://github.com/ruby/xmlrpc
|
/dev/null | ||
---|---|---|
this file should not be published.
|
/dev/null | ||
---|---|---|
# coding: US-ASCII
|
||
# frozen_string_literal: false
|
||
require_relative "utils"
|
||
require "webrick"
|
||
require "test/unit"
|
||
class TestWEBrickCGI < Test::Unit::TestCase
|
||
CRLF = "\r\n"
|
||
def teardown
|
||
WEBrick::Utils::TimeoutHandler.terminate
|
||
super
|
||
end
|
||
def start_cgi_server(log_tester=TestWEBrick::DefaultLogTester, &block)
|
||
config = {
|
||
:CGIInterpreter => TestWEBrick::RubyBin,
|
||
:DocumentRoot => File.dirname(__FILE__),
|
||
:DirectoryIndex => ["webrick.cgi"],
|
||
:RequestCallback => Proc.new{|req, res|
|
||
def req.meta_vars
|
||
meta = super
|
||
meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR)
|
||
meta[RbConfig::CONFIG['LIBPATHENV']] = ENV[RbConfig::CONFIG['LIBPATHENV']] if RbConfig::CONFIG['LIBPATHENV']
|
||
return meta
|
||
end
|
||
},
|
||
}
|
||
if RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin32/
|
||
config[:CGIPathEnv] = ENV['PATH'] # runtime dll may not be in system dir.
|
||
end
|
||
TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
|
||
block.call(server, addr, port, log)
|
||
}
|
||
end
|
||
def test_cgi
|
||
start_cgi_server{|server, addr, port, log|
|
||
http = Net::HTTP.new(addr, port)
|
||
req = Net::HTTP::Get.new("/webrick.cgi")
|
||
http.request(req){|res| assert_equal("/webrick.cgi", res.body, log.call)}
|
||
req = Net::HTTP::Get.new("/webrick.cgi/path/info")
|
||
http.request(req){|res| assert_equal("/path/info", res.body, log.call)}
|
||
req = Net::HTTP::Get.new("/webrick.cgi/%3F%3F%3F?foo=bar")
|
||
http.request(req){|res| assert_equal("/???", res.body, log.call)}
|
||
unless RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin32/
|
||
# Path info of res.body is passed via ENV.
|
||
# ENV[] returns different value on Windows depending on locale.
|
||
req = Net::HTTP::Get.new("/webrick.cgi/%A4%DB%A4%B2/%A4%DB%A4%B2")
|
||
http.request(req){|res|
|
||
assert_equal("/\xA4\xDB\xA4\xB2/\xA4\xDB\xA4\xB2", res.body, log.call)}
|
||
end
|
||
req = Net::HTTP::Get.new("/webrick.cgi?a=1;a=2;b=x")
|
||
http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body, log.call)}
|
||
req = Net::HTTP::Get.new("/webrick.cgi?a=1&a=2&b=x")
|
||
http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body, log.call)}
|
||
req = Net::HTTP::Post.new("/webrick.cgi?a=x;a=y;b=1")
|
||
req["Content-Type"] = "application/x-www-form-urlencoded"
|
||
http.request(req, "a=1;a=2;b=x"){|res|
|
||
assert_equal("a=1, a=2, b=x", res.body, log.call)}
|
||
req = Net::HTTP::Post.new("/webrick.cgi?a=x&a=y&b=1")
|
||
req["Content-Type"] = "application/x-www-form-urlencoded"
|
||
http.request(req, "a=1&a=2&b=x"){|res|
|
||
assert_equal("a=1, a=2, b=x", res.body, log.call)}
|
||
req = Net::HTTP::Get.new("/")
|
||
http.request(req){|res|
|
||
ary = res.body.lines.to_a
|
||
assert_match(%r{/$}, ary[0], log.call)
|
||
assert_match(%r{/webrick.cgi$}, ary[1], log.call)
|
||
}
|
||
req = Net::HTTP::Get.new("/webrick.cgi")
|
||
req["Cookie"] = "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001"
|
||
http.request(req){|res|
|
||
assert_equal(
|
||
"CUSTOMER=WILE_E_COYOTE\nPART_NUMBER=ROCKET_LAUNCHER_0001\n",
|
||
res.body, log.call)
|
||
}
|
||
req = Net::HTTP::Get.new("/webrick.cgi")
|
||
cookie = %{$Version="1"; }
|
||
cookie << %{Customer="WILE_E_COYOTE"; $Path="/acme"; }
|
||
cookie << %{Part_Number="Rocket_Launcher_0001"; $Path="/acme"; }
|
||
cookie << %{Shipping="FedEx"; $Path="/acme"}
|
||
req["Cookie"] = cookie
|
||
http.request(req){|res|
|
||
assert_equal("Customer=WILE_E_COYOTE, Shipping=FedEx",
|
||
res["Set-Cookie"], log.call)
|
||
assert_equal("Customer=WILE_E_COYOTE\n" +
|
||
"Part_Number=Rocket_Launcher_0001\n" +
|
||
"Shipping=FedEx\n", res.body, log.call)
|
||
}
|
||
}
|
||
end
|
||
def test_bad_request
|
||
log_tester = lambda {|log, access_log|
|
||
assert_match(/BadRequest/, log.join)
|
||
}
|
||
start_cgi_server(log_tester) {|server, addr, port, log|
|
||
sock = TCPSocket.new(addr, port)
|
||
begin
|
||
sock << "POST /webrick.cgi HTTP/1.0" << CRLF
|
||
sock << "Content-Type: application/x-www-form-urlencoded" << CRLF
|
||
sock << "Content-Length: 1024" << CRLF
|
||
sock << CRLF
|
||
sock << "a=1&a=2&b=x"
|
||
sock.close_write
|
||
assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, sock.read, log.call)
|
||
ensure
|
||
sock.close
|
||
end
|
||
}
|
||
end
|
||
def test_cgi_env
|
||
start_cgi_server do |server, addr, port, log|
|
||
http = Net::HTTP.new(addr, port)
|
||
req = Net::HTTP::Get.new("/webrick.cgi/dumpenv")
|
||
req['proxy'] = 'http://example.com/'
|
||
req['hello'] = 'world'
|
||
http.request(req) do |res|
|
||
env = Marshal.load(res.body)
|
||
assert_equal 'world', env['HTTP_HELLO']
|
||
assert_not_operator env, :include?, 'HTTP_PROXY'
|
||
end
|
||
end
|
||
end
|
||
CtrlSeq = [0x7f, *(1..31)].pack("C*").gsub(/\s+/, '')
|
||
CtrlPat = /#{Regexp.quote(CtrlSeq)}/o
|
||
DumpPat = /#{Regexp.quote(CtrlSeq.dump[1...-1])}/o
|
||
def test_bad_uri
|
||
log_tester = lambda {|log, access_log|
|
||
assert_equal(1, log.length)
|
||
assert_match(/ERROR bad URI/, log[0])
|
||
}
|
||
start_cgi_server(log_tester) {|server, addr, port, log|
|
||
res = TCPSocket.open(addr, port) {|sock|
|
||
sock << "GET /#{CtrlSeq}#{CRLF}#{CRLF}"
|
||
sock.close_write
|
||
sock.read
|
||
}
|
||
assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, res)
|
||
s = log.call.each_line.grep(/ERROR bad URI/)[0]
|
||
assert_match(DumpPat, s)
|
||
assert_not_match(CtrlPat, s)
|
||
}
|
||
end
|
||
def test_bad_header
|
||
log_tester = lambda {|log, access_log|
|
||
assert_equal(1, log.length)
|
||
assert_match(/ERROR bad header/, log[0])
|
||
}
|
||
start_cgi_server(log_tester) {|server, addr, port, log|
|
||
res = TCPSocket.open(addr, port) {|sock|
|
||
sock << "GET / HTTP/1.0#{CRLF}#{CtrlSeq}#{CRLF}#{CRLF}"
|
||
sock.close_write
|
||
sock.read
|
||
}
|
||
assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, res)
|
||
s = log.call.each_line.grep(/ERROR bad header/)[0]
|
||
assert_match(DumpPat, s)
|
||
assert_not_match(CtrlPat, s)
|
||
}
|
||
end
|
||
end
|
/dev/null | ||
---|---|---|
# frozen_string_literal: false
|
||
require "test/unit"
|
||
require "webrick/config"
|
||
class TestWEBrickConfig < Test::Unit::TestCase
|
||
def test_server_name_default
|
||
config = WEBrick::Config::General.dup
|
||
assert_equal(false, config.key?(:ServerName))
|
||
assert_equal(WEBrick::Utils.getservername, config[:ServerName])
|
||
assert_equal(true, config.key?(:ServerName))
|
||
end
|
||
def test_server_name_set_nil
|
||
config = WEBrick::Config::General.dup.update(ServerName: nil)
|
||
assert_equal(nil, config[:ServerName])
|
||
end
|
||
end
|
/dev/null | ||
---|---|---|
# frozen_string_literal: false
|
||
require "test/unit"
|
||
require "webrick/cookie"
|
||
class TestWEBrickCookie < Test::Unit::TestCase
|
||
def test_new
|
||
cookie = WEBrick::Cookie.new("foo","bar")
|
||
assert_equal("foo", cookie.name)
|
||
assert_equal("bar", cookie.value)
|
||
assert_equal("foo=bar", cookie.to_s)
|
||
end
|
||
def test_time
|
||
cookie = WEBrick::Cookie.new("foo","bar")
|
||
t = 1000000000
|
||
cookie.max_age = t
|
||
assert_match(t.to_s, cookie.to_s)
|
||
cookie = WEBrick::Cookie.new("foo","bar")
|
||
t = Time.at(1000000000)
|
||
cookie.expires = t
|
||
assert_equal(Time, cookie.expires.class)
|
||
assert_equal(t, cookie.expires)
|
||
ts = t.httpdate
|
||
cookie.expires = ts
|
||
assert_equal(Time, cookie.expires.class)
|
||
assert_equal(t, cookie.expires)
|
||
assert_match(ts, cookie.to_s)
|
||
end
|
||
def test_parse
|
||
data = ""
|
||
data << '$Version="1"; '
|
||
data << 'Customer="WILE_E_COYOTE"; $Path="/acme"; '
|
||
data << 'Part_Number="Rocket_Launcher_0001"; $Path="/acme"; '
|
||
data << 'Shipping="FedEx"; $Path="/acme"'
|
||
cookies = WEBrick::Cookie.parse(data)
|
||
assert_equal(3, cookies.size)
|
||
assert_equal(1, cookies[0].version)
|
||
assert_equal("Customer", cookies[0].name)
|
||
assert_equal("WILE_E_COYOTE", cookies[0].value)
|
||
assert_equal("/acme", cookies[0].path)
|
||
assert_equal(1, cookies[1].version)
|
||
assert_equal("Part_Number", cookies[1].name)
|
||
assert_equal("Rocket_Launcher_0001", cookies[1].value)
|
||
assert_equal(1, cookies[2].version)
|
||
assert_equal("Shipping", cookies[2].name)
|
||
assert_equal("FedEx", cookies[2].value)
|
||
data = "hoge=moge; __div__session=9865ecfd514be7f7"
|
||
cookies = WEBrick::Cookie.parse(data)
|
||
assert_equal(2, cookies.size)
|
||
assert_equal(0, cookies[0].version)
|
||
assert_equal("hoge", cookies[0].name)
|
||
assert_equal("moge", cookies[0].value)
|
||
assert_equal("__div__session", cookies[1].name)
|
||
assert_equal("9865ecfd514be7f7", cookies[1].value)
|
||
# don't allow ,-separator
|
||
data = "hoge=moge, __div__session=9865ecfd514be7f7"
|
||
cookies = WEBrick::Cookie.parse(data)
|
||
assert_equal(1, cookies.size)
|
||
assert_equal(0, cookies[0].version)
|
||
assert_equal("hoge", cookies[0].name)
|
||
assert_equal("moge, __div__session=9865ecfd514be7f7", cookies[0].value)
|
||
end
|
||
def test_parse_no_whitespace
|
||
data = [
|
||
'$Version="1"; ',
|
||
'Customer="WILE_E_COYOTE";$Path="/acme";', # no SP between cookie-string
|
||
'Part_Number="Rocket_Launcher_0001";$Path="/acme";', # no SP between cookie-string
|
||
'Shipping="FedEx";$Path="/acme"'
|
||
].join
|
||
cookies = WEBrick::Cookie.parse(data)
|
||
assert_equal(1, cookies.size)
|
||
end
|
||
def test_parse_too_much_whitespaces
|
||
# According to RFC6265,
|
||
# cookie-string = cookie-pair *( ";" SP cookie-pair )
|
||
# So single 0x20 is needed after ';'. We allow multiple spaces here for
|
||
# compatibility with older WEBrick versions.
|
||
data = [
|
||
'$Version="1"; ',
|
||
'Customer="WILE_E_COYOTE";$Path="/acme"; ', # no SP between cookie-string
|
||
'Part_Number="Rocket_Launcher_0001";$Path="/acme"; ', # no SP between cookie-string
|
||
'Shipping="FedEx";$Path="/acme"'
|
||
].join
|
||
cookies = WEBrick::Cookie.parse(data)
|
||
assert_equal(3, cookies.size)
|
||
end
|
||
def test_parse_set_cookie
|
||
data = %(Customer="WILE_E_COYOTE"; Version="1"; Path="/acme")
|
||
cookie = WEBrick::Cookie.parse_set_cookie(data)
|
||
assert_equal("Customer", cookie.name)
|
||
assert_equal("WILE_E_COYOTE", cookie.value)
|
||
assert_equal(1, cookie.version)
|
||
assert_equal("/acme", cookie.path)
|
||
data = %(Shipping="FedEx"; Version="1"; Path="/acme"; Secure)
|
||
cookie = WEBrick::Cookie.parse_set_cookie(data)
|
||
assert_equal("Shipping", cookie.name)
|
||
assert_equal("FedEx", cookie.value)
|
||
assert_equal(1, cookie.version)
|
||
assert_equal("/acme", cookie.path)
|
||
assert_equal(true, cookie.secure)
|
||
end
|
||
def test_parse_set_cookies
|
||
data = %(Shipping="FedEx"; Version="1"; Path="/acme"; Secure)
|
||
data << %(, CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT; path=/; Secure)
|
||
data << %(, name="Aaron"; Version="1"; path="/acme")
|
||
cookies = WEBrick::Cookie.parse_set_cookies(data)
|
||
assert_equal(3, cookies.length)
|
||
fed_ex = cookies.find { |c| c.name == 'Shipping' }
|
||
assert_not_nil(fed_ex)
|
||
assert_equal("Shipping", fed_ex.name)
|
||
assert_equal("FedEx", fed_ex.value)
|
||
assert_equal(1, fed_ex.version)
|
||
assert_equal("/acme", fed_ex.path)
|
||
assert_equal(true, fed_ex.secure)
|
||
name = cookies.find { |c| c.name == 'name' }
|
||
assert_not_nil(name)
|
||
assert_equal("name", name.name)
|
||
assert_equal("Aaron", name.value)
|
||
assert_equal(1, name.version)
|
||
assert_equal("/acme", name.path)
|
||
customer = cookies.find { |c| c.name == 'CUSTOMER' }
|
||
assert_not_nil(customer)
|
||
assert_equal("CUSTOMER", customer.name)
|
||
assert_equal("WILE_E_COYOTE", customer.value)
|
||
assert_equal(0, customer.version)
|
||
assert_equal("/", customer.path)
|
||
assert_equal(Time.utc(1999, 11, 9, 23, 12, 40), customer.expires)
|
||
end
|
||
end
|
/dev/null | ||
---|---|---|
# frozen_string_literal: false
|
||
require "test/unit"
|
||
require "webrick"
|
||
require_relative "utils"
|
||
class TestDoNotReverseLookup < Test::Unit::TestCase
|
||
class DNRL < WEBrick::GenericServer
|
||
def run(sock)
|
||
sock << sock.do_not_reverse_lookup.to_s
|
||
end
|
||
end
|
||
@@original_do_not_reverse_lookup_value = Socket.do_not_reverse_lookup
|
||
def teardown
|
||
Socket.do_not_reverse_lookup = @@original_do_not_reverse_lookup_value
|
||
end
|
||
def do_not_reverse_lookup?(config)
|
||
result = nil
|
||
TestWEBrick.start_server(DNRL, config) do |server, addr, port, log|
|
||
TCPSocket.open(addr, port) do |sock|
|
||
result = {'true' => true, 'false' => false}[sock.gets]
|
||
end
|
||
end
|
||
result
|
||
end
|
||
# +--------------------------------------------------------------------------+
|
||
# | Expected interaction between Socket.do_not_reverse_lookup |
|
||
# | and WEBrick::Config::General[:DoNotReverseLookup] |
|
||
# +----------------------------+---------------------------------------------+
|
||
# | |WEBrick::Config::General[:DoNotReverseLookup]|
|
||
# +----------------------------+--------------+---------------+--------------+
|
||
# |Socket.do_not_reverse_lookup| TRUE | FALSE | NIL |
|
||
# +----------------------------+--------------+---------------+--------------+
|
||
# | TRUE | true | false | true |
|
||
# +----------------------------+--------------+---------------+--------------+
|
||
# | FALSE | true | false | false |
|
||
# +----------------------------+--------------+---------------+--------------+
|
||
def test_socket_dnrl_true_server_dnrl_true
|
||
Socket.do_not_reverse_lookup = true
|
||
assert_equal(true, do_not_reverse_lookup?(:DoNotReverseLookup => true))
|
||
end
|
||
def test_socket_dnrl_true_server_dnrl_false
|
||
Socket.do_not_reverse_lookup = true
|
||
assert_equal(false, do_not_reverse_lookup?(:DoNotReverseLookup => false))
|
||
end
|
||
def test_socket_dnrl_true_server_dnrl_nil
|
||
Socket.do_not_reverse_lookup = true
|
||
assert_equal(true, do_not_reverse_lookup?(:DoNotReverseLookup => nil))
|
||
end
|
||
def test_socket_dnrl_false_server_dnrl_true
|
||
Socket.do_not_reverse_lookup = false
|
||
assert_equal(true, do_not_reverse_lookup?(:DoNotReverseLookup => true))
|
||
end
|
||
def test_socket_dnrl_false_server_dnrl_false
|
||
Socket.do_not_reverse_lookup = false
|
||
assert_equal(false, do_not_reverse_lookup?(:DoNotReverseLookup => false))
|
||
end
|
||
def test_socket_dnrl_false_server_dnrl_nil
|
||
Socket.do_not_reverse_lookup = false
|
||
assert_equal(false, do_not_reverse_lookup?(:DoNotReverseLookup => nil))
|
||
end
|
||
end
|
/dev/null | ||
---|---|---|
# frozen_string_literal: false
|
||
require "test/unit"
|
||
require_relative "utils.rb"
|
||
require "webrick"
|
||
require "stringio"
|
||
class WEBrick::TestFileHandler < Test::Unit::TestCase
|
||
def teardown
|
||
WEBrick::Utils::TimeoutHandler.terminate
|
||
super
|
||
end
|
||
def default_file_handler(filename)
|
||
klass = WEBrick::HTTPServlet::DefaultFileHandler
|
||
klass.new(WEBrick::Config::HTTP, filename)
|
||
end
|
||
def windows?
|
||
File.directory?("\\")
|
||
end
|
||
def get_res_body(res)
|
||
sio = StringIO.new
|
||
sio.binmode
|
||
res.send_body(sio)
|
||
sio.string
|
||
end
|
||
def make_range_request(range_spec)
|
||
msg = <<-END_OF_REQUEST
|
||
GET / HTTP/1.0
|
||
Range: #{range_spec}
|
||
END_OF_REQUEST
|
||
return StringIO.new(msg.gsub(/^ {6}/, ""))
|
||
end
|
||
def make_range_response(file, range_spec)
|
||
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
|
||
req.parse(make_range_request(range_spec))
|
||
res = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP)
|
||
size = File.size(file)
|
||
handler = default_file_handler(file)
|
||
handler.make_partial_content(req, res, file, size)
|
||
return res
|
||
end
|
||
def test_make_partial_content
|
||
filename = __FILE__
|
||
filesize = File.size(filename)
|
||
res = make_range_response(filename, "bytes=#{filesize-100}-")
|
||
assert_match(%r{^text/plain}, res["content-type"])
|
||
assert_equal(100, get_res_body(res).size)
|
||
res = make_range_response(filename, "bytes=-100")
|
||
assert_match(%r{^text/plain}, res["content-type"])
|
||
assert_equal(100, get_res_body(res).size)
|
||
res = make_range_response(filename, "bytes=0-99")
|
||
assert_match(%r{^text/plain}, res["content-type"])
|
||
assert_equal(100, get_res_body(res).size)
|
||
res = make_range_response(filename, "bytes=100-199")
|
||
assert_match(%r{^text/plain}, res["content-type"])
|
||
assert_equal(100, get_res_body(res).size)
|
||
res = make_range_response(filename, "bytes=0-0")
|
||
assert_match(%r{^text/plain}, res["content-type"])
|
||
assert_equal(1, get_res_body(res).size)
|
||
res = make_range_response(filename, "bytes=-1")
|
||
assert_match(%r{^text/plain}, res["content-type"])
|
||
assert_equal(1, get_res_body(res).size)
|
||
res = make_range_response(filename, "bytes=0-0, -2")
|
||
assert_match(%r{^multipart/byteranges}, res["content-type"])
|
||
body = get_res_body(res)
|
||
boundary = /; boundary=(.+)/.match(res['content-type'])[1]
|
||
off = filesize - 2
|
||
last = filesize - 1
|
||
exp = "--#{boundary}\r\n" \
|
||
"Content-Type: text/plain\r\n" \
|
||
"Content-Range: bytes 0-0/#{filesize}\r\n" \
|
||
"\r\n" \
|
||
"#{IO.read(__FILE__, 1)}\r\n" \
|
||
"--#{boundary}\r\n" \
|
||
"Content-Type: text/plain\r\n" \
|
||
"Content-Range: bytes #{off}-#{last}/#{filesize}\r\n" \
|
||
"\r\n" \
|
||
"#{IO.read(__FILE__, 2, off)}\r\n" \
|
||
"--#{boundary}--\r\n"
|
||
assert_equal exp, body
|
||
end
|
||
def test_filehandler
|
||
config = { :DocumentRoot => File.dirname(__FILE__), }
|
||
this_file = File.basename(__FILE__)
|
||
filesize = File.size(__FILE__)
|
||
this_data = File.binread(__FILE__)
|
||
range = nil
|
||
bug2593 = '[ruby-dev:40030]'
|
||
TestWEBrick.start_httpserver(config) do |server, addr, port, log|
|
||
http = Net::HTTP.new(addr, port)
|
||
req = Net::HTTP::Get.new("/")
|
||
http.request(req){|res|
|
||
assert_equal("200", res.code, log.call)
|
||
assert_equal("text/html", res.content_type, log.call)
|
||
assert_match(/HREF="#{this_file}"/, res.body, log.call)
|
||
}
|
||
req = Net::HTTP::Get.new("/#{this_file}")
|
||
http.request(req){|res|
|
||
assert_equal("200", res.code, log.call)
|
||
assert_equal("text/plain", res.content_type, log.call)
|
||
assert_equal(this_data, res.body, log.call)
|
||
}
|
||
req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=#{filesize-100}-")
|
||
http.request(req){|res|
|
||
assert_equal("206", res.code, log.call)
|
||
assert_equal("text/plain", res.content_type, log.call)
|
||
assert_nothing_raised(bug2593) {range = res.content_range}
|
||
assert_equal((filesize-100)..(filesize-1), range, log.call)
|
||
assert_equal(this_data[-100..-1], res.body, log.call)
|
||
}
|
||
req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-100")
|
||
http.request(req){|res|
|
||
assert_equal("206", res.code, log.call)
|
||
assert_equal("text/plain", res.content_type, log.call)
|
||
assert_nothing_raised(bug2593) {range = res.content_range}
|
||
assert_equal((filesize-100)..(filesize-1), range, log.call)
|
||
assert_equal(this_data[-100..-1], res.body, log.call)
|
||
}
|
||
req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-99")
|
||
http.request(req){|res|
|
||
assert_equal("206", res.code, log.call)
|
||
assert_equal("text/plain", res.content_type, log.call)
|
||
assert_nothing_raised(bug2593) {range = res.content_range}
|
||
assert_equal(0..99, range, log.call)
|
||
assert_equal(this_data[0..99], res.body, log.call)
|
||
}
|
||
req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=100-199")
|
||
http.request(req){|res|
|
||
assert_equal("206", res.code, log.call)
|
||
assert_equal("text/plain", res.content_type, log.call)
|
||
assert_nothing_raised(bug2593) {range = res.content_range}
|
||
assert_equal(100..199, range, log.call)
|
||
assert_equal(this_data[100..199], res.body, log.call)
|
||
}
|
||
req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0")
|
||
http.request(req){|res|
|
||
assert_equal("206", res.code, log.call)
|
||
assert_equal("text/plain", res.content_type, log.call)
|
||
assert_nothing_raised(bug2593) {range = res.content_range}
|
||
assert_equal(0..0, range, log.call)
|
||
assert_equal(this_data[0..0], res.body, log.call)
|
||
}
|
||
req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-1")
|
||
http.request(req){|res|
|
||
assert_equal("206", res.code, log.call)
|
||
assert_equal("text/plain", res.content_type, log.call)
|
||
assert_nothing_raised(bug2593) {range = res.content_range}
|
||
assert_equal((filesize-1)..(filesize-1), range, log.call)
|
||
assert_equal(this_data[-1, 1], res.body, log.call)
|
||
}
|
||
req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0, -2")
|
||
http.request(req){|res|
|
||
assert_equal("206", res.code, log.call)
|
||
assert_equal("multipart/byteranges", res.content_type, log.call)
|
||
}
|
||
end
|
||
end
|
||
def test_non_disclosure_name
|
||
config = { :DocumentRoot => File.dirname(__FILE__), }
|
||
log_tester = lambda {|log, access_log|
|
||
log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
|
||
log = log.reject {|s| /WARN the request refers nondisclosure name/ =~ s }
|
||
assert_equal([], log)
|
||
}
|
||
this_file = File.basename(__FILE__)
|
||
TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
|
||
http = Net::HTTP.new(addr, port)
|
||
doc_root_opts = server[:DocumentRootOptions]
|
||
doc_root_opts[:NondisclosureName] = %w(.ht* *~ test_*)
|
||
req = Net::HTTP::Get.new("/")
|
||
http.request(req){|res|
|
||
assert_equal("200", res.code, log.call)
|
||
assert_equal("text/html", res.content_type, log.call)
|
||
assert_no_match(/HREF="#{File.basename(__FILE__)}"/, res.body)
|
||
}
|
||
req = Net::HTTP::Get.new("/#{this_file}")
|
||
http.request(req){|res|
|
||
assert_equal("404", res.code, log.call)
|
||
}
|
||
doc_root_opts[:NondisclosureName] = %w(.ht* *~ TEST_*)
|
||
http.request(req){|res|
|
||
assert_equal("404", res.code, log.call)
|
||
}
|
||
end
|
||
end
|
||
def test_directory_traversal
|
||
return if File.executable?(__FILE__) # skip on strange file system
|
||
config = { :DocumentRoot => File.dirname(__FILE__), }
|
||
log_tester = lambda {|log, access_log|
|
||
log = log.reject {|s| /ERROR bad URI/ =~ s }
|
||
log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
|
||
assert_equal([], log)
|
||
}
|
||
TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
|
||
http = Net::HTTP.new(addr, port)
|
||
req = Net::HTTP::Get.new("/../../")
|
||
http.request(req){|res| assert_equal("400", res.code, log.call) }
|
||
req = Net::HTTP::Get.new("/..%5c../#{File.basename(__FILE__)}")
|
||
http.request(req){|res| assert_equal(windows? ? "200" : "404", res.code, log.call) }
|
||
req = Net::HTTP::Get.new("/..%5c..%5cruby.c")
|
||
http.request(req){|res| assert_equal("404", res.code, log.call) }
|
||
end
|
||
end
|
||
def test_unwise_in_path
|
||
if windows?
|
||
config = { :DocumentRoot => File.dirname(__FILE__), }
|
||
TestWEBrick.start_httpserver(config) do |server, addr, port, log|
|
||
http = Net::HTTP.new(addr, port)
|
||
req = Net::HTTP::Get.new("/..%5c..")
|
||
http.request(req){|res| assert_equal("301", res.code, log.call) }
|
||
end
|
||
end
|
||
end
|
||
def test_short_filename
|
||
return if File.executable?(__FILE__) # skip on strange file system
|
||
config = {
|
||
:CGIInterpreter => TestWEBrick::RubyBin,
|
||
:DocumentRoot => File.dirname(__FILE__),
|
||
:CGIPathEnv => ENV['PATH'],
|
||
}
|
||
log_tester = lambda {|log, access_log|
|
||
log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
|
||
log = log.reject {|s| /WARN the request refers nondisclosure name/ =~ s }
|
||
assert_equal([], log)
|
||
}
|
||
TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
|
||
http = Net::HTTP.new(addr, port)
|
||
if windows?
|
||
root = config[:DocumentRoot].tr("/", "\\")
|
||
fname = IO.popen(%W[dir /x #{root}\\webrick_long_filename.cgi], &:read)
|
||
fname.sub!(/\A.*$^$.*$^$/m, '')
|
||
if fname
|
||
fname = fname[/\s(w.+?cgi)\s/i, 1]
|
||
fname.downcase!
|
||
end
|
||
else
|
||
fname = "webric~1.cgi"
|
||
end
|
||
req = Net::HTTP::Get.new("/#{fname}/test")
|
||
http.request(req) do |res|
|
||
if windows?
|
||
assert_equal("200", res.code, log.call)
|
||
assert_equal("/test", res.body, log.call)
|
||
else
|
||
assert_equal("404", res.code, log.call)
|
||
end
|
||
end
|
||
req = Net::HTTP::Get.new("/.htaccess")
|
||
http.request(req) {|res| assert_equal("404", res.code, log.call) }
|
||
req = Net::HTTP::Get.new("/htacce~1")
|
||
http.request(req) {|res| assert_equal("404", res.code, log.call) }
|
||
req = Net::HTTP::Get.new("/HTACCE~1")
|
||
http.request(req) {|res| assert_equal("404", res.code, log.call) }
|
||
end
|
||
end
|
||
def test_script_disclosure
|
||
return if File.executable?(__FILE__) # skip on strange file system
|
||
config = {
|
||
:CGIInterpreter => TestWEBrick::RubyBin,
|
||
:DocumentRoot => File.dirname(__FILE__),
|
||
:CGIPathEnv => ENV['PATH'],
|
||
:RequestCallback => Proc.new{|req, res|
|
||
def req.meta_vars
|
||
meta = super
|
||
meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR)
|
||
meta[RbConfig::CONFIG['LIBPATHENV']] = ENV[RbConfig::CONFIG['LIBPATHENV']] if RbConfig::CONFIG['LIBPATHENV']
|
||
return meta
|
||
end
|
||
},
|
||
}
|
||
log_tester = lambda {|log, access_log|
|
||
log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
|
||
assert_equal([], log)
|
||
}
|
||
TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
|
||
http = Net::HTTP.new(addr, port)
|
||
req = Net::HTTP::Get.new("/webrick.cgi/test")
|
||
http.request(req) do |res|
|
||
assert_equal("200", res.code, log.call)
|
||
assert_equal("/test", res.body, log.call)
|
||
end
|
||
resok = windows?
|
||
response_assertion = Proc.new do |res|
|
||
if resok
|
||
assert_equal("200", res.code, log.call)
|
||
assert_equal("/test", res.body, log.call)
|
||
else
|
||
assert_equal("404", res.code, log.call)
|
||
end
|
||
end
|
||
req = Net::HTTP::Get.new("/webrick.cgi%20/test")
|
||
http.request(req, &response_assertion)
|
||
req = Net::HTTP::Get.new("/webrick.cgi./test")
|
||
http.request(req, &response_assertion)
|
||
resok &&= File.exist?(__FILE__+"::$DATA")
|
||
req = Net::HTTP::Get.new("/webrick.cgi::$DATA/test")
|
||
http.request(req, &response_assertion)
|
||
end
|
||
end
|
||
def test_erbhandler
|
||
config = { :DocumentRoot => File.dirname(__FILE__) }
|
||
log_tester = lambda {|log, access_log|
|
||
log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
|
||
assert_equal([], log)
|
||
}
|
||
TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
|
||
http = Net::HTTP.new(addr, port)
|
||
req = Net::HTTP::Get.new("/webrick.rhtml")
|
||
http.request(req) do |res|
|
||
assert_equal("200", res.code, log.call)
|
||
assert_match %r!\Areq to http://[^/]+/webrick\.rhtml {}\n!, res.body
|
||
end
|
||
end
|
||
end
|
||
end
|
/dev/null | ||
---|---|---|
require "tempfile"
|
||
require "test/unit"
|
||
require "webrick/httpauth/htgroup"
|
||
class TestHtgroup < Test::Unit::TestCase
|
||
def test_htgroup
|
||
Tempfile.create('test_htgroup') do |tmpfile|
|
||
tmpfile.close
|
||
tmp_group = WEBrick::HTTPAuth::Htgroup.new(tmpfile.path)
|
||
tmp_group.add 'superheroes', %w[spiderman batman]
|
||
tmp_group.add 'supervillains', %w[joker]
|
||
tmp_group.flush
|
||
htgroup = WEBrick::HTTPAuth::Htgroup.new(tmpfile.path)
|
||
assert_equal(htgroup.members('superheroes'), %w[spiderman batman])
|
||
assert_equal(htgroup.members('supervillains'), %w[joker])
|
||
end
|
||
end
|
||
end
|
/dev/null | ||
---|---|---|
# frozen_string_literal: false
|
||
require "test/unit"
|
||
require "webrick/htmlutils"
|
||
class TestWEBrickHTMLUtils < Test::Unit::TestCase
|
||
include WEBrick::HTMLUtils
|
||
def test_escape
|
||
assert_equal("foo", escape("foo"))
|
||
assert_equal("foo bar", escape("foo bar"))
|
||
assert_equal("foo&bar", escape("foo&bar"))
|
||
assert_equal("foo"bar", escape("foo\"bar"))
|
||
assert_equal("foo>bar", escape("foo>bar"))
|
||
assert_equal("foo<bar", escape("foo<bar"))
|
||
assert_equal("\u{3053 3093 306B 3061 306F}", escape("\u{3053 3093 306B 3061 306F}"))
|
||
bug8425 = '[Bug #8425] [ruby-core:55052]'
|
||
assert_nothing_raised(ArgumentError, Encoding::CompatibilityError, bug8425) {
|
||
assert_equal("\u{3053 3093 306B}\xff<", escape("\u{3053 3093 306B}\xff<"))
|
||
}
|
||
end
|
||
end
|
/dev/null | ||
---|---|---|
# frozen_string_literal: false
|
||
require "test/unit"
|
||
require "net/http"
|
||
require "tempfile"
|
||
require "webrick"
|
||
require "webrick/httpauth/basicauth"
|
||
require "stringio"
|
||
require_relative "utils"
|
||
class TestWEBrickHTTPAuth < Test::Unit::TestCase
|
||
def teardown
|
||
WEBrick::Utils::TimeoutHandler.terminate
|
||
super
|
||
end
|
||
def test_basic_auth
|
||
log_tester = lambda {|log, access_log|
|
||
assert_equal(1, log.length)
|
||
assert_match(/ERROR WEBrick::HTTPStatus::Unauthorized/, log[0])
|
||
}
|
||
TestWEBrick.start_httpserver({}, log_tester) {|server, addr, port, log|
|
||
realm = "WEBrick's realm"
|
||
path = "/basic_auth"
|
||
server.mount_proc(path){|req, res|
|
||
WEBrick::HTTPAuth.basic_auth(req, res, realm){|user, pass|
|
||
user == "webrick" && pass == "supersecretpassword"
|
||
}
|
||
res.body = "hoge"
|
||
}
|
||
http = Net::HTTP.new(addr, port)
|
||
g = Net::HTTP::Get.new(path)
|
||
g.basic_auth("webrick", "supersecretpassword")
|
||
http.request(g){|res| assert_equal("hoge", res.body, log.call)}
|
||
g.basic_auth("webrick", "not super")
|
||
http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
|
||
}
|
||
end
|
||
def test_basic_auth_sha
|
||
Tempfile.create("test_webrick_auth") {|tmpfile|
|
||
tmpfile.puts("webrick:{SHA}GJYFRpBbdchp595jlh3Bhfmgp8k=")
|
||
tmpfile.flush
|
||
assert_raise(NotImplementedError){
|
||
WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
|
||
}
|
||
}
|
||
end
|
||
def test_basic_auth_md5
|
||
Tempfile.create("test_webrick_auth") {|tmpfile|
|
||
tmpfile.puts("webrick:$apr1$IOVMD/..$rmnOSPXr0.wwrLPZHBQZy0")
|
||
tmpfile.flush
|
||
assert_raise(NotImplementedError){
|
||
WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
|
||
}
|
||
}
|
||
end
|
||
[nil, :crypt, :bcrypt].each do |hash_algo|
|
||
begin
|
||
case hash_algo
|
||
when :crypt
|
||
# require 'string/crypt'
|
||
when :bcrypt
|
||
require 'bcrypt'
|
||
end
|
||
rescue LoadError
|
||
next
|
||
end
|
||
define_method(:"test_basic_auth_htpasswd_#{hash_algo}") do
|
||
log_tester = lambda {|log, access_log|
|
||
log.reject! {|line| /\A\s*\z/ =~ line }
|
||
pats = [
|
||
/ERROR Basic WEBrick's realm: webrick: password unmatch\./,
|
||
/ERROR WEBrick::HTTPStatus::Unauthorized/
|
||
]
|
||
pats.each {|pat|
|
||
assert(!log.grep(pat).empty?, "webrick log doesn't have expected error: #{pat.inspect}")
|
||
log.reject! {|line| pat =~ line }
|
||
}
|
||
assert_equal([], log)
|
||
}
|
||
TestWEBrick.start_httpserver({}, log_tester) {|server, addr, port, log|
|
||
realm = "WEBrick's realm"
|
||
path = "/basic_auth2"
|
||
Tempfile.create("test_webrick_auth") {|tmpfile|
|
||
tmpfile.close
|
||
tmp_pass = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path, password_hash: hash_algo)
|
||
tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
|
||
tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
|
||
tmp_pass.flush
|
||
htpasswd = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path, password_hash: hash_algo)
|
||
users = []
|
||
htpasswd.each{|user, pass| users << user }
|
||
assert_equal(2, users.size, log.call)
|
||
assert(users.member?("webrick"), log.call)
|
||
assert(users.member?("foo"), log.call)
|
||
server.mount_proc(path){|req, res|
|
||
auth = WEBrick::HTTPAuth::BasicAuth.new(
|
||
:Realm => realm, :UserDB => htpasswd,
|
||
:Logger => server.logger
|
||
)
|
||
auth.authenticate(req, res)
|
||
res.body = "hoge"
|
||
}
|
||
http = Net::HTTP.new(addr, port)
|
||
g = Net::HTTP::Get.new(path)
|
||
g.basic_auth("webrick", "supersecretpassword")
|
||
http.request(g){|res| assert_equal("hoge", res.body, log.call)}
|
||
g.basic_auth("webrick", "not super")
|
||
http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
|
||
}
|
||
}
|
||
end
|
||
define_method(:"test_basic_auth_bad_username_htpasswd_#{hash_algo}") do
|
||
log_tester = lambda {|log, access_log|
|
||
assert_equal(2, log.length)
|
||
assert_match(/ERROR Basic WEBrick's realm: foo\\ebar: the user is not allowed\./, log[0])
|
||
assert_match(/ERROR WEBrick::HTTPStatus::Unauthorized/, log[1])
|
||
}
|
||
TestWEBrick.start_httpserver({}, log_tester) {|server, addr, port, log|
|
||
realm = "WEBrick's realm"
|
||
path = "/basic_auth"
|
||
Tempfile.create("test_webrick_auth") {|tmpfile|
|
||
tmpfile.close
|
||
tmp_pass = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path, password_hash: hash_algo)
|
||
tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
|
||
tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
|
||
tmp_pass.flush
|
||
htpasswd = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path, password_hash: hash_algo)
|
||
users = []
|
||
htpasswd.each{|user, pass| users << user }
|
||
server.mount_proc(path){|req, res|
|
||
auth = WEBrick::HTTPAuth::BasicAuth.new(
|
||
:Realm => realm, :UserDB => htpasswd,
|
||
:Logger => server.logger
|
||
)
|
||
auth.authenticate(req, res)
|
||
res.body = "hoge"
|
||
}
|
||
http = Net::HTTP.new(addr, port)
|
||
g = Net::HTTP::Get.new(path)
|
||
g.basic_auth("foo\ebar", "passwd")
|
||
http.request(g){|res| assert_not_equal("hoge", res.body, log.call) }
|
||
}
|
||
}
|
||
end
|
||
end
|
||
DIGESTRES_ = /
|
||
([a-zA-Z\-]+)
|
||
[ \t]*(?:\r\n[ \t]*)*
|
||
=
|
||
[ \t]*(?:\r\n[ \t]*)*
|
||
(?:
|
||
"((?:[^"]+|\\[\x00-\x7F])*)" |
|
||
([!\#$%&'*+\-.0-9A-Z^_`a-z|~]+)
|
||
)/x
|
||
def test_digest_auth
|
||
log_tester = lambda {|log, access_log|
|
||
log.reject! {|line| /\A\s*\z/ =~ line }
|
||
pats = [
|
||
/ERROR Digest WEBrick's realm: no credentials in the request\./,
|
||
/ERROR WEBrick::HTTPStatus::Unauthorized/,
|
||
/ERROR Digest WEBrick's realm: webrick: digest unmatch\./
|
||
]
|
||
pats.each {|pat|
|
||
assert(!log.grep(pat).empty?, "webrick log doesn't have expected error: #{pat.inspect}")
|
||
log.reject! {|line| pat =~ line }
|
||
}
|
||
assert_equal([], log)
|
||
}
|
||
TestWEBrick.start_httpserver({}, log_tester) {|server, addr, port, log|
|
||
realm = "WEBrick's realm"
|
||
path = "/digest_auth"
|
||
Tempfile.create("test_webrick_auth") {|tmpfile|
|
||
tmpfile.close
|
||
tmp_pass = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path)
|
||
tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
|
||
tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
|
||
tmp_pass.flush
|
||
htdigest = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path)
|
||
users = []
|
||
htdigest.each{|user, pass| users << user }
|
||
assert_equal(2, users.size, log.call)
|
||
assert(users.member?("webrick"), log.call)
|
||
assert(users.member?("foo"), log.call)
|
||
auth = WEBrick::HTTPAuth::DigestAuth.new(
|
||
:Realm => realm, :UserDB => htdigest,
|
||
:Algorithm => 'MD5',
|
||
:Logger => server.logger
|
||
)
|
||
server.mount_proc(path){|req, res|
|
||
auth.authenticate(req, res)
|
||
res.body = "hoge"
|
||
}
|
||
Net::HTTP.start(addr, port) do |http|
|
||
g = Net::HTTP::Get.new(path)
|
||
params = {}
|
||
http.request(g) do |res|
|
||
assert_equal('401', res.code, log.call)
|
||
res["www-authenticate"].scan(DIGESTRES_) do |key, quoted, token|
|
||
params[key.downcase] = token || quoted.delete('\\')
|
||
end
|
||
params['uri'] = "http://#{addr}:#{port}#{path}"
|
||
end
|
||
g['Authorization'] = credentials_for_request('webrick', "supersecretpassword", params)
|
||
http.request(g){|res| assert_equal("hoge", res.body, log.call)}
|
||
params['algorithm'].downcase! #4936
|
||
g['Authorization'] = credentials_for_request('webrick', "supersecretpassword", params)
|
||
http.request(g){|res| assert_equal("hoge", res.body, log.call)}
|
||
g['Authorization'] = credentials_for_request('webrick', "not super", params)
|
||
http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
|
||
end
|
||
}
|
||
}
|
||
end
|
||
def test_digest_auth_int
|
||
log_tester = lambda {|log, access_log|
|
||
log.reject! {|line| /\A\s*\z/ =~ line }
|
||
pats = [
|
||
/ERROR Digest wb auth-int realm: no credentials in the request\./,
|
||
/ERROR WEBrick::HTTPStatus::Unauthorized/,
|
||
/ERROR Digest wb auth-int realm: foo: digest unmatch\./
|
||
]
|
||
pats.each {|pat|
|
||
assert(!log.grep(pat).empty?, "webrick log doesn't have expected error: #{pat.inspect}")
|
||
log.reject! {|line| pat =~ line }
|
||
}
|
||
assert_equal([], log)
|
||
}
|
||
TestWEBrick.start_httpserver({}, log_tester) {|server, addr, port, log|
|
||
realm = "wb auth-int realm"
|
||
path = "/digest_auth_int"
|
||
Tempfile.create("test_webrick_auth_int") {|tmpfile|
|
||
tmpfile.close
|
||
tmp_pass = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path)
|
||
tmp_pass.set_passwd(realm, "foo", "Hunter2")
|
||
tmp_pass.flush
|
||
htdigest = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path)
|
||
users = []
|
||
htdigest.each{|user, pass| users << user }
|
||
assert_equal %w(foo), users
|
||
auth = WEBrick::HTTPAuth::DigestAuth.new(
|
||
:Realm => realm, :UserDB => htdigest,
|
||
:Algorithm => 'MD5',
|
||
:Logger => server.logger,
|
||
:Qop => %w(auth-int),
|
||
)
|
||
server.mount_proc(path){|req, res|
|
||
auth.authenticate(req, res)
|
||
res.body = "bbb"
|
||
}
|
||
Net::HTTP.start(addr, port) do |http|
|
||
post = Net::HTTP::Post.new(path)
|
||
params = {}
|
||
data = 'hello=world'
|
||
body = StringIO.new(data)
|
||
post.content_length = data.bytesize
|
||
post['Content-Type'] = 'application/x-www-form-urlencoded'
|
||
post.body_stream = body
|
||
http.request(post) do |res|
|
||
assert_equal('401', res.code, log.call)
|
||
res["www-authenticate"].scan(DIGESTRES_) do |key, quoted, token|
|
||
params[key.downcase] = token || quoted.delete('\\')
|
||
end
|
||
params['uri'] = "http://#{addr}:#{port}#{path}"
|
||
end
|
||
body.rewind
|
||
cred = credentials_for_request('foo', 'Hunter3', params, body)
|
||
post['Authorization'] = cred
|
||
post.body_stream = body
|
||
http.request(post){|res|
|
||
assert_equal('401', res.code, log.call)
|
||
assert_not_equal("bbb", res.body, log.call)
|
||
}
|
||
body.rewind
|
||
cred = credentials_for_request('foo', 'Hunter2', params, body)
|
||
post['Authorization'] = cred
|
||
post.body_stream = body
|
||
http.request(post){|res| assert_equal("bbb", res.body, log.call)}
|
||
end
|
||
}
|
||
}
|
||
end
|
||
private
|
||
def credentials_for_request(user, password, params, body = nil)
|
||
cnonce = "hoge"
|
||
nonce_count = 1
|
||
ha1 = "#{user}:#{params['realm']}:#{password}"
|
||
if body
|
||
dig = Digest::MD5.new
|
||
while buf = body.read(16384)
|
||
dig.update(buf)
|
||
end
|
||
body.rewind
|
||
ha2 = "POST:#{params['uri']}:#{dig.hexdigest}"
|
||
else
|
||
ha2 = "GET:#{params['uri']}"
|
||
end
|
||
request_digest =
|
||
"#{Digest::MD5.hexdigest(ha1)}:" \
|
||
"#{params['nonce']}:#{'%08x' % nonce_count}:#{cnonce}:#{params['qop']}:" \
|
||
"#{Digest::MD5.hexdigest(ha2)}"
|
||
"Digest username=\"#{user}\"" \
|
||
", realm=\"#{params['realm']}\"" \
|
||
", nonce=\"#{params['nonce']}\"" \
|
||
", uri=\"#{params['uri']}\"" \
|
||
", qop=#{params['qop']}" \
|
||
", nc=#{'%08x' % nonce_count}" \
|
||
", cnonce=\"#{cnonce}\"" \
|
||
", response=\"#{Digest::MD5.hexdigest(request_digest)}\"" \
|
||
", opaque=\"#{params['opaque']}\"" \
|
||
", algorithm=#{params['algorithm']}"
|
||
end
|
||
end
|
/dev/null | ||
---|---|---|
# frozen_string_literal: false
|
||
require "test/unit"
|
||
require "net/http"
|
||
require "webrick"
|
||
require "webrick/httpproxy"
|
||
begin
|
||
require "webrick/ssl"
|
||
require "net/https"
|
||
rescue LoadError
|
||
# test_connect will be skipped
|
||
end
|
||
require File.expand_path("utils.rb", File.dirname(__FILE__))
|
||
class TestWEBrickHTTPProxy < Test::Unit::TestCase
|
||
def teardown
|
||
WEBrick::Utils::TimeoutHandler.terminate
|
||
super
|
||
end
|
||
def test_fake_proxy
|
||
assert_nil(WEBrick::FakeProxyURI.scheme)
|
||
assert_nil(WEBrick::FakeProxyURI.host)
|
||
assert_nil(WEBrick::FakeProxyURI.port)
|
||
assert_nil(WEBrick::FakeProxyURI.path)
|
||
assert_nil(WEBrick::FakeProxyURI.userinfo)
|
||
assert_raise(NoMethodError){ WEBrick::FakeProxyURI.foo }
|
||
end
|
||
def test_proxy
|
||
# Testing GET or POST to the proxy server
|
||
# Note that the proxy server works as the origin server.
|
||
# +------+
|
||
# V |
|
||
# client -------> proxy ---+
|
||
# GET / POST GET / POST
|
||
#
|
||
proxy_handler_called = request_handler_called = 0
|
||
config = {
|
||
:ServerName => "localhost.localdomain",
|
||
:ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
|
||
:RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
|
||
}
|
||
TestWEBrick.start_httpproxy(config){|server, addr, port, log|
|
||
server.mount_proc("/"){|req, res|
|
||
res.body = "#{req.request_method} #{req.path} #{req.body}"
|
||
}
|
||
http = Net::HTTP.new(addr, port, addr, port)
|
||
req = Net::HTTP::Get.new("/")
|
||
http.request(req){|res|
|
||
assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
|
||
assert_equal("GET / ", res.body, log.call)
|
||
}
|
||
assert_equal(1, proxy_handler_called, log.call)
|
||
assert_equal(2, request_handler_called, log.call)
|
||
req = Net::HTTP::Head.new("/")
|
||
http.request(req){|res|
|
||
assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
|
||
assert_nil(res.body, log.call)
|
||
}
|
||
assert_equal(2, proxy_handler_called, log.call)
|
||
assert_equal(4, request_handler_called, log.call)
|
||
req = Net::HTTP::Post.new("/")
|
||
req.body = "post-data"
|
||
req.content_type = "application/x-www-form-urlencoded"
|
||
http.request(req){|res|
|
||
assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
|
||
assert_equal("POST / post-data", res.body, log.call)
|
||
}
|
||
assert_equal(3, proxy_handler_called, log.call)
|
||
assert_equal(6, request_handler_called, log.call)
|
||
}
|
||
end
|
||
def test_no_proxy
|
||
# Testing GET or POST to the proxy server without proxy request.
|
||
#
|
||
# client -------> proxy
|
||
# GET / POST
|
||
#
|
||
proxy_handler_called = request_handler_called = 0
|
||
config = {
|
||
:ServerName => "localhost.localdomain",
|
||
:ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
|
||
:RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
|
||
}
|
||
TestWEBrick.start_httpproxy(config){|server, addr, port, log|
|
||
server.mount_proc("/"){|req, res|
|
||
res.body = "#{req.request_method} #{req.path} #{req.body}"
|
||
}
|
||
http = Net::HTTP.new(addr, port)
|
||
req = Net::HTTP::Get.new("/")
|
||
http.request(req){|res|
|
||
assert_nil(res["via"], log.call)
|
||
assert_equal("GET / ", res.body, log.call)
|
||
}
|
||
assert_equal(0, proxy_handler_called, log.call)
|
||
assert_equal(1, request_handler_called, log.call)
|
||
req = Net::HTTP::Head.new("/")
|
||
http.request(req){|res|
|
||
assert_nil(res["via"], log.call)
|
||
assert_nil(res.body, log.call)
|
||
}
|
||
assert_equal(0, proxy_handler_called, log.call)
|
||
assert_equal(2, request_handler_called, log.call)
|
||
req = Net::HTTP::Post.new("/")
|
||
req.content_type = "application/x-www-form-urlencoded"
|
||
req.body = "post-data"
|
||
http.request(req){|res|
|
||
assert_nil(res["via"], log.call)
|
||
assert_equal("POST / post-data", res.body, log.call)
|
||
}
|
||
assert_equal(0, proxy_handler_called, log.call)
|
||
assert_equal(3, request_handler_called, log.call)
|
||
}
|
||
end
|
||
def test_big_bodies
|
||
require 'digest/md5'
|
||
rand_str = File.read(__FILE__)
|
||
rand_str.freeze
|
||
nr = 1024 ** 2 / rand_str.size # bigger works, too
|
||
exp = Digest::MD5.new
|
||
nr.times { exp.update(rand_str) }
|
||
exp = exp.hexdigest
|
||
TestWEBrick.start_httpserver do |o_server, o_addr, o_port, o_log|
|
||
o_server.mount_proc('/') do |req, res|
|
||
case req.request_method
|
||
when 'GET'
|
||
res['content-type'] = 'application/octet-stream'
|
||
if req.path == '/length'
|
||
res['content-length'] = (nr * rand_str.size).to_s
|
||
else
|
||
res.chunked = true
|
||
end
|
||
res.body = ->(socket) { nr.times { socket.write(rand_str) } }
|
||
when 'POST'
|
||
dig = Digest::MD5.new
|
||
req.body { |buf| dig.update(buf); buf.clear }
|
||
res['content-type'] = 'text/plain'
|
||
res['content-length'] = '32'
|
||
res.body = dig.hexdigest
|
||
end
|
||
end
|
||
http = Net::HTTP.new(o_addr, o_port)
|