2006-06-30 16:42:12 -04:00
|
|
|
# Copyright (c) 2005 Zed A. Shaw
|
|
|
|
# You can redistribute it and/or modify it under the same terms as Ruby.
|
|
|
|
#
|
|
|
|
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
|
|
|
# for more information.
|
2006-05-21 10:46:42 -04:00
|
|
|
|
2006-01-28 14:03:53 -05:00
|
|
|
require 'test/unit'
|
|
|
|
require 'http11'
|
2006-03-19 18:31:30 -05:00
|
|
|
require 'mongrel'
|
|
|
|
require 'benchmark'
|
2006-04-02 22:27:59 -04:00
|
|
|
require 'digest/sha1'
|
2006-01-28 14:03:53 -05:00
|
|
|
|
2006-03-19 18:31:30 -05:00
|
|
|
include Mongrel
|
2006-01-28 14:03:53 -05:00
|
|
|
|
|
|
|
class HttpParserTest < Test::Unit::TestCase
|
|
|
|
|
2006-01-30 01:25:20 -05:00
|
|
|
def test_parse_simple
|
|
|
|
parser = HttpParser.new
|
|
|
|
req = {}
|
|
|
|
http = "GET / HTTP/1.1\r\n\r\n"
|
2006-05-14 19:42:19 -04:00
|
|
|
nread = parser.execute(req, http, 0)
|
2006-01-30 01:25:20 -05:00
|
|
|
assert nread == http.length, "Failed to parse the full HTTP request"
|
|
|
|
assert parser.finished?, "Parser didn't finish"
|
|
|
|
assert !parser.error?, "Parser had error"
|
|
|
|
assert nread == parser.nread, "Number read returned from execute does not match"
|
|
|
|
parser.reset
|
|
|
|
assert parser.nread == 0, "Number read after reset should be 0"
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def test_parse_error
|
|
|
|
parser = HttpParser.new
|
|
|
|
req = {}
|
|
|
|
bad_http = "GET / SsUTF/1.1"
|
|
|
|
|
|
|
|
error = false
|
|
|
|
begin
|
2006-05-14 19:42:19 -04:00
|
|
|
nread = parser.execute(req, bad_http, 0)
|
2006-01-30 01:25:20 -05:00
|
|
|
rescue => details
|
|
|
|
error = true
|
2006-01-28 14:03:53 -05:00
|
|
|
end
|
2006-01-30 01:25:20 -05:00
|
|
|
|
|
|
|
assert error, "failed to throw exception"
|
|
|
|
assert !parser.finished?, "Parser shouldn't be finished"
|
|
|
|
assert parser.error?, "Parser SHOULD have error"
|
|
|
|
end
|
2006-03-19 18:31:30 -05:00
|
|
|
|
2006-04-02 22:27:59 -04:00
|
|
|
# lame random garbage maker
|
|
|
|
def rand_data(min, max, readable=true)
|
|
|
|
count = min + ((rand(max)+1) *10).to_i
|
|
|
|
res = count.to_s + "/"
|
|
|
|
|
|
|
|
if readable
|
|
|
|
res << Digest::SHA1.hexdigest(rand(count * 1000).to_s) * (count / 40)
|
|
|
|
else
|
|
|
|
res << Digest::SHA1.digest(rand(count * 1000).to_s) * (count / 20)
|
|
|
|
end
|
|
|
|
|
|
|
|
return res
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def test_horrible_queries
|
|
|
|
parser = HttpParser.new
|
|
|
|
|
|
|
|
# first verify that large random get requests fail
|
|
|
|
100.times do |c|
|
|
|
|
get = "GET /#{rand_data(1024, 1024+(c*1024))} HTTP/1.1\r\n"
|
|
|
|
assert_raises Mongrel::HttpParserError do
|
2006-05-14 19:42:19 -04:00
|
|
|
parser.execute({}, get, 0)
|
2006-04-02 22:27:59 -04:00
|
|
|
parser.reset
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# then that large header names are caught
|
|
|
|
100.times do |c|
|
|
|
|
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-#{rand_data(1024, 1024+(c*1024))}: Test\r\n\r\n"
|
|
|
|
assert_raises Mongrel::HttpParserError do
|
2006-05-14 19:42:19 -04:00
|
|
|
parser.execute({}, get, 0)
|
2006-04-02 22:27:59 -04:00
|
|
|
parser.reset
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# then that large mangled field values are caught
|
|
|
|
100.times do |c|
|
|
|
|
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-Test: #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
|
|
|
|
assert_raises Mongrel::HttpParserError do
|
2006-05-14 19:42:19 -04:00
|
|
|
parser.execute({}, get, 0)
|
2006-04-02 22:27:59 -04:00
|
|
|
parser.reset
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# then large headers are rejected too
|
|
|
|
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\n"
|
|
|
|
get << "X-Test: test\r\n" * (80 * 1024)
|
|
|
|
assert_raises Mongrel::HttpParserError do
|
2006-05-14 19:42:19 -04:00
|
|
|
parser.execute({}, get, 0)
|
2006-04-02 22:27:59 -04:00
|
|
|
parser.reset
|
|
|
|
end
|
|
|
|
|
|
|
|
# finally just that random garbage gets blocked all the time
|
|
|
|
10.times do |c|
|
|
|
|
get = "GET #{rand_data(1024, 1024+(c*1024), false)} #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
|
|
|
|
assert_raises Mongrel::HttpParserError do
|
2006-05-14 19:42:19 -04:00
|
|
|
parser.execute({}, get, 0)
|
2006-04-02 22:27:59 -04:00
|
|
|
parser.reset
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-03-19 18:31:30 -05:00
|
|
|
def test_query_parse
|
2006-05-23 08:46:05 -04:00
|
|
|
res = HttpRequest.query_parse("zed=1&frank=#{HttpRequest.escape('&&& ')}")
|
2006-04-01 04:09:10 -05:00
|
|
|
assert res["zed"], "didn't get the request right"
|
|
|
|
assert res["frank"], "no frank"
|
|
|
|
assert_equal "1", res["zed"], "wrong result"
|
2006-05-23 08:46:05 -04:00
|
|
|
assert_equal "&&& ", HttpRequest.unescape(res["frank"]), "wrong result"
|
2006-04-01 04:09:10 -05:00
|
|
|
|
|
|
|
res = HttpRequest.query_parse("zed=1&zed=2&zed=3&frank=11;zed=45")
|
|
|
|
assert res["zed"], "didn't get the request right"
|
|
|
|
assert res["frank"], "no frank"
|
|
|
|
assert_equal 4,res["zed"].length, "wrong number for zed"
|
|
|
|
assert_equal "11",res["frank"], "wrong number for frank"
|
2006-03-19 18:31:30 -05:00
|
|
|
end
|
2006-04-02 22:27:59 -04:00
|
|
|
|
2006-01-28 14:03:53 -05:00
|
|
|
end
|
|
|
|
|