engineyard-mongrel 1.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +16 -0
- data/CONTRIBUTORS +17 -0
- data/COPYING +55 -0
- data/LICENSE +55 -0
- data/Manifest +71 -0
- data/README +74 -0
- data/bin/mongrel_rails +285 -0
- data/examples/builder.rb +29 -0
- data/examples/camping/README +3 -0
- data/examples/camping/blog.rb +294 -0
- data/examples/camping/tepee.rb +149 -0
- data/examples/httpd.conf +474 -0
- data/examples/mime.yaml +3 -0
- data/examples/mongrel.conf +9 -0
- data/examples/mongrel_simple_ctrl.rb +92 -0
- data/examples/mongrel_simple_service.rb +116 -0
- data/examples/monitrc +57 -0
- data/examples/random_thrash.rb +19 -0
- data/examples/simpletest.rb +52 -0
- data/examples/webrick_compare.rb +20 -0
- data/ext/http11/ext_help.h +15 -0
- data/ext/http11/extconf.rb +6 -0
- data/ext/http11/http11.c +527 -0
- data/ext/http11/http11_parser.c +1243 -0
- data/ext/http11/http11_parser.h +49 -0
- data/ext/http11/http11_parser.java.rl +171 -0
- data/ext/http11/http11_parser.rl +152 -0
- data/ext/http11/http11_parser_common.rl +54 -0
- data/ext/http11_java/Http11Service.java +13 -0
- data/ext/http11_java/org/jruby/mongrel/Http11.java +266 -0
- data/ext/http11_java/org/jruby/mongrel/Http11Parser.java +474 -0
- data/lib/mongrel.rb +360 -0
- data/lib/mongrel/camping.rb +107 -0
- data/lib/mongrel/cgi.rb +181 -0
- data/lib/mongrel/command.rb +222 -0
- data/lib/mongrel/configurator.rb +389 -0
- data/lib/mongrel/const.rb +110 -0
- data/lib/mongrel/debug.rb +203 -0
- data/lib/mongrel/gems.rb +22 -0
- data/lib/mongrel/handlers.rb +468 -0
- data/lib/mongrel/header_out.rb +28 -0
- data/lib/mongrel/http_request.rb +155 -0
- data/lib/mongrel/http_response.rb +166 -0
- data/lib/mongrel/init.rb +10 -0
- data/lib/mongrel/mime_types.yml +616 -0
- data/lib/mongrel/rails.rb +214 -0
- data/lib/mongrel/stats.rb +89 -0
- data/lib/mongrel/tcphack.rb +18 -0
- data/lib/mongrel/uri_classifier.rb +76 -0
- data/mongrel-public_cert.pem +20 -0
- data/setup.rb +1585 -0
- data/test/benchmark/previous.rb +11 -0
- data/test/benchmark/simple.rb +11 -0
- data/test/benchmark/utils.rb +82 -0
- data/test/mime.yaml +3 -0
- data/test/mongrel.conf +1 -0
- data/test/test_helper.rb +79 -0
- data/test/tools/trickletest.rb +45 -0
- data/test/unit/test_cgi_wrapper.rb +26 -0
- data/test/unit/test_command.rb +86 -0
- data/test/unit/test_conditional.rb +107 -0
- data/test/unit/test_configurator.rb +88 -0
- data/test/unit/test_debug.rb +25 -0
- data/test/unit/test_handlers.rb +136 -0
- data/test/unit/test_http_parser.rb +156 -0
- data/test/unit/test_redirect_handler.rb +45 -0
- data/test/unit/test_request_progress.rb +100 -0
- data/test/unit/test_response.rb +127 -0
- data/test/unit/test_stats.rb +35 -0
- data/test/unit/test_uriclassifier.rb +261 -0
- data/test/unit/test_ws.rb +116 -0
- metadata +158 -0
@@ -0,0 +1,88 @@
|
|
1
|
+
# Copyright (c) 2005 Zed A. Shaw
|
2
|
+
# You can redistribute it and/or modify it under the same terms as Ruby.
|
3
|
+
#
|
4
|
+
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
5
|
+
# for more information.
|
6
|
+
|
7
|
+
require 'test/test_helper'
|
8
|
+
|
9
|
+
$test_plugin_fired = 0
|
10
|
+
|
11
|
+
class TestPlugin < GemPlugin::Plugin "/handlers"
|
12
|
+
include Mongrel::HttpHandlerPlugin
|
13
|
+
|
14
|
+
def process(request, response)
|
15
|
+
$test_plugin_fired += 1
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
class Sentinel < GemPlugin::Plugin "/handlers"
|
21
|
+
include Mongrel::HttpHandlerPlugin
|
22
|
+
|
23
|
+
def process(request, response)
|
24
|
+
raise "This Sentinel plugin shouldn't run."
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
class ConfiguratorTest < Test::Unit::TestCase
|
30
|
+
|
31
|
+
def test_base_handler_config
|
32
|
+
@port = process_based_port
|
33
|
+
@config = nil
|
34
|
+
|
35
|
+
redirect_test_io do
|
36
|
+
@config = Mongrel::Configurator.new :host => "localhost" do
|
37
|
+
listener :port => process_based_port do
|
38
|
+
# 2 in front should run, but the sentinel shouldn't since dirhandler processes the request
|
39
|
+
uri "/", :handler => plugin("/handlers/testplugin")
|
40
|
+
uri "/", :handler => plugin("/handlers/testplugin")
|
41
|
+
uri "/", :handler => Mongrel::DirHandler.new(".")
|
42
|
+
uri "/", :handler => plugin("/handlers/testplugin")
|
43
|
+
|
44
|
+
uri "/test", :handler => plugin("/handlers/testplugin")
|
45
|
+
uri "/test", :handler => plugin("/handlers/testplugin")
|
46
|
+
uri "/test", :handler => Mongrel::DirHandler.new(".")
|
47
|
+
uri "/test", :handler => plugin("/handlers/testplugin")
|
48
|
+
|
49
|
+
debug "/"
|
50
|
+
setup_signals
|
51
|
+
|
52
|
+
run_config(HERE + "/mongrel.conf")
|
53
|
+
load_mime_map(HERE + "/mime.yaml")
|
54
|
+
|
55
|
+
run
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# pp @config.listeners.values.first.classifier.routes
|
61
|
+
|
62
|
+
@config.listeners.each do |host,listener|
|
63
|
+
assert listener.classifier.uris.length == 3, "Wrong number of registered URIs"
|
64
|
+
assert listener.classifier.uris.include?("/"), "/ not registered"
|
65
|
+
assert listener.classifier.uris.include?("/test"), "/test not registered"
|
66
|
+
end
|
67
|
+
|
68
|
+
res = Net::HTTP.get(URI.parse("http://localhost:#{@port}/test"))
|
69
|
+
assert res != nil, "Didn't get a response"
|
70
|
+
assert $test_plugin_fired == 3, "Test filter plugin didn't run 3 times."
|
71
|
+
|
72
|
+
redirect_test_io do
|
73
|
+
res = Net::HTTP.get(URI.parse("http://localhost:#{@port}/"))
|
74
|
+
|
75
|
+
assert res != nil, "Didn't get a response"
|
76
|
+
assert $test_plugin_fired == 6, "Test filter plugin didn't run 6 times."
|
77
|
+
end
|
78
|
+
|
79
|
+
redirect_test_io do
|
80
|
+
@config.stop(false, true)
|
81
|
+
end
|
82
|
+
|
83
|
+
assert_raise Errno::EBADF, Errno::ECONNREFUSED do
|
84
|
+
res = Net::HTTP.get(URI.parse("http://localhost:#{@port}/"))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Copyright (c) 2005 Zed A. Shaw
|
2
|
+
# You can redistribute it and/or modify it under the same terms as Ruby.
|
3
|
+
#
|
4
|
+
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
5
|
+
# for more information.
|
6
|
+
|
7
|
+
require 'test/test_helper'
|
8
|
+
require 'mongrel/debug'
|
9
|
+
|
10
|
+
class MongrelDbgTest < Test::Unit::TestCase
|
11
|
+
|
12
|
+
def test_tracing_to_log
|
13
|
+
FileUtils.rm_rf "log/mongrel_debug"
|
14
|
+
|
15
|
+
MongrelDbg::configure
|
16
|
+
out = StringIO.new
|
17
|
+
|
18
|
+
MongrelDbg::begin_trace(:rails)
|
19
|
+
MongrelDbg::trace(:rails, "Good stuff")
|
20
|
+
MongrelDbg::end_trace(:rails)
|
21
|
+
|
22
|
+
assert File.exist?("log/mongrel_debug"), "Didn't make logging directory"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# Copyright (c) 2005 Zed A. Shaw
|
2
|
+
# You can redistribute it and/or modify it under the same terms as Ruby.
|
3
|
+
#
|
4
|
+
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
5
|
+
# for more information.
|
6
|
+
|
7
|
+
require 'test/test_helper'
|
8
|
+
|
9
|
+
class SimpleHandler < Mongrel::HttpHandler
|
10
|
+
def process(request, response)
|
11
|
+
response.start do |head,out|
|
12
|
+
head["Content-Type"] = "text/html"
|
13
|
+
results = "<html><body>Your request:<br /><pre>#{request.params.to_yaml}</pre><a href=\"/files\">View the files.</a></body></html>"
|
14
|
+
out << results
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class DumbHandler < Mongrel::HttpHandler
|
20
|
+
def process(request, response)
|
21
|
+
response.start do |head,out|
|
22
|
+
head["Content-Type"] = "text/html"
|
23
|
+
out.write("test")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def check_status(results, expecting)
|
29
|
+
results.each do |res|
|
30
|
+
assert(res.kind_of?(expecting), "Didn't get #{expecting}, got: #{res.class}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class HandlersTest < Test::Unit::TestCase
|
35
|
+
|
36
|
+
def setup
|
37
|
+
@port = process_based_port
|
38
|
+
stats = Mongrel::StatisticsFilter.new(:sample_rate => 1)
|
39
|
+
|
40
|
+
@config = Mongrel::Configurator.new :host => '127.0.0.1' do
|
41
|
+
listener :port => process_based_port do
|
42
|
+
uri "/", :handler => SimpleHandler.new
|
43
|
+
uri "/", :handler => stats
|
44
|
+
uri "/404", :handler => Mongrel::Error404Handler.new("Not found")
|
45
|
+
uri "/dumb", :handler => Mongrel::DeflateFilter.new
|
46
|
+
uri "/dumb", :handler => DumbHandler.new, :in_front => true
|
47
|
+
uri "/files", :handler => Mongrel::DirHandler.new("doc")
|
48
|
+
uri "/files_nodir", :handler => Mongrel::DirHandler.new("doc", listing_allowed=false, index_html="none")
|
49
|
+
uri "/status", :handler => Mongrel::StatusHandler.new(:stats_filter => stats)
|
50
|
+
uri "/relative", :handler => Mongrel::DirHandler.new(nil, listing_allowed=false, index_html="none")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
unless windows?
|
55
|
+
File.open('/tmp/testfile', 'w') do
|
56
|
+
# Do nothing
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
@config.run
|
61
|
+
end
|
62
|
+
|
63
|
+
def teardown
|
64
|
+
@config.stop(false, true)
|
65
|
+
File.delete '/tmp/testfile' unless windows?
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_registration_exception_is_not_lost
|
69
|
+
assert_raises(Mongrel::URIClassifier::RegistrationError) do
|
70
|
+
@config = Mongrel::Configurator.new do
|
71
|
+
listener do
|
72
|
+
uri "bogus", :handler => SimpleHandler.new
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_more_web_server
|
79
|
+
res = hit([ "http://localhost:#{@port}/test",
|
80
|
+
"http://localhost:#{@port}/dumb",
|
81
|
+
"http://localhost:#{@port}/404",
|
82
|
+
"http://localhost:#{@port}/files/rdoc/index.html",
|
83
|
+
"http://localhost:#{@port}/files/rdoc/nothere.html",
|
84
|
+
"http://localhost:#{@port}/files/rdoc/",
|
85
|
+
"http://localhost:#{@port}/files_nodir/rdoc/",
|
86
|
+
"http://localhost:#{@port}/status",
|
87
|
+
])
|
88
|
+
check_status res, String
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_nil_dirhandler
|
92
|
+
return if windows?
|
93
|
+
# Camping uses this internally
|
94
|
+
handler = Mongrel::DirHandler.new(nil, false)
|
95
|
+
assert handler.can_serve("/tmp/testfile")
|
96
|
+
# Not a bug! A nil @file parameter is the only circumstance under which
|
97
|
+
# we are allowed to serve any existing file
|
98
|
+
assert handler.can_serve("../../../../../../../../../../tmp/testfile")
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_non_nil_dirhandler_is_not_vulnerable_to_path_traversal
|
102
|
+
# The famous security bug of Mongrel 1.1.2
|
103
|
+
handler = Mongrel::DirHandler.new("/doc", false)
|
104
|
+
assert_nil handler.can_serve("/tmp/testfile")
|
105
|
+
assert_nil handler.can_serve("../../../../../../../../../../tmp/testfile")
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_deflate
|
109
|
+
Net::HTTP.start("localhost", @port) do |h|
|
110
|
+
# Test that no accept-encoding returns a non-deflated response
|
111
|
+
req = h.get("/dumb")
|
112
|
+
assert(
|
113
|
+
!req['Content-Encoding'] ||
|
114
|
+
!req['Content-Encoding'].include?('deflate'))
|
115
|
+
assert_equal "test", req.body
|
116
|
+
|
117
|
+
req = h.get("/dumb", {"Accept-Encoding" => "deflate"})
|
118
|
+
# -MAX_WBITS stops zlib from looking for a zlib header
|
119
|
+
inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
120
|
+
assert req['Content-Encoding'].include?('deflate')
|
121
|
+
assert_equal "test", inflater.inflate(req.body)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# TODO: find out why this fails on win32 but nowhere else
|
126
|
+
#def test_posting_fails_dirhandler
|
127
|
+
# req = Net::HTTP::Post.new("http://localhost:#{@port}/files/rdoc/")
|
128
|
+
# req.set_form_data({'from'=>'2005-01-01', 'to'=>'2005-03-31'}, ';')
|
129
|
+
# res = hit [["http://localhost:#{@port}/files/rdoc/",req]]
|
130
|
+
# check_status res, Net::HTTPNotFound
|
131
|
+
#end
|
132
|
+
|
133
|
+
def test_unregister
|
134
|
+
@config.listeners["127.0.0.1:#{@port}"].unregister("/")
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# Copyright (c) 2005 Zed A. Shaw
|
2
|
+
# You can redistribute it and/or modify it under the same terms as Ruby.
|
3
|
+
#
|
4
|
+
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
5
|
+
# for more information.
|
6
|
+
|
7
|
+
require 'test/test_helper'
|
8
|
+
|
9
|
+
include Mongrel
|
10
|
+
|
11
|
+
class HttpParserTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def test_parse_simple
|
14
|
+
parser = HttpParser.new
|
15
|
+
req = {}
|
16
|
+
http = "GET / HTTP/1.1\r\n\r\n"
|
17
|
+
nread = parser.execute(req, http, 0)
|
18
|
+
|
19
|
+
assert nread == http.length, "Failed to parse the full HTTP request"
|
20
|
+
assert parser.finished?, "Parser didn't finish"
|
21
|
+
assert !parser.error?, "Parser had error"
|
22
|
+
assert nread == parser.nread, "Number read returned from execute does not match"
|
23
|
+
|
24
|
+
assert_equal 'HTTP/1.1', req['SERVER_PROTOCOL']
|
25
|
+
assert_equal '/', req['REQUEST_PATH']
|
26
|
+
assert_equal 'HTTP/1.1', req['HTTP_VERSION']
|
27
|
+
assert_equal '/', req['REQUEST_URI']
|
28
|
+
assert_equal 'CGI/1.2', req['GATEWAY_INTERFACE']
|
29
|
+
assert_equal 'GET', req['REQUEST_METHOD']
|
30
|
+
assert_nil req['FRAGMENT']
|
31
|
+
assert_nil req['QUERY_STRING']
|
32
|
+
|
33
|
+
parser.reset
|
34
|
+
assert parser.nread == 0, "Number read after reset should be 0"
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_parse_strange_headers
|
38
|
+
parser = HttpParser.new
|
39
|
+
req = {}
|
40
|
+
should_be_good = "GET / HTTP/1.1\r\naaaaaaaaaaaaa:++++++++++\r\n\r\n"
|
41
|
+
nread = parser.execute(req, should_be_good, 0)
|
42
|
+
assert_equal should_be_good.length, nread
|
43
|
+
assert parser.finished?
|
44
|
+
assert !parser.error?
|
45
|
+
|
46
|
+
nasty_pound_header = "GET / HTTP/1.1\r\nX-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgEBBAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n\tRA==\r\n\t-----END CERTIFICATE-----\r\n\r\n"
|
47
|
+
parser = HttpParser.new
|
48
|
+
req = {}
|
49
|
+
nread = parser.execute(req, nasty_pound_header, 0)
|
50
|
+
assert_equal nasty_pound_header.length, nread
|
51
|
+
assert parser.finished?
|
52
|
+
assert !parser.error?
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_parse_error
|
56
|
+
parser = HttpParser.new
|
57
|
+
req = {}
|
58
|
+
bad_http = "GET / SsUTF/1.1"
|
59
|
+
|
60
|
+
error = false
|
61
|
+
begin
|
62
|
+
nread = parser.execute(req, bad_http, 0)
|
63
|
+
rescue => details
|
64
|
+
error = true
|
65
|
+
end
|
66
|
+
|
67
|
+
assert error, "failed to throw exception"
|
68
|
+
assert !parser.finished?, "Parser shouldn't be finished"
|
69
|
+
assert parser.error?, "Parser SHOULD have error"
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_fragment_in_uri
|
73
|
+
parser = HttpParser.new
|
74
|
+
req = {}
|
75
|
+
get = "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n\r\n"
|
76
|
+
assert_nothing_raised do
|
77
|
+
parser.execute(req, get, 0)
|
78
|
+
end
|
79
|
+
assert parser.finished?
|
80
|
+
assert_equal '/forums/1/topics/2375?page=1', req['REQUEST_URI']
|
81
|
+
assert_equal 'posts-17408', req['FRAGMENT']
|
82
|
+
end
|
83
|
+
|
84
|
+
# lame random garbage maker
|
85
|
+
def rand_data(min, max, readable=true)
|
86
|
+
count = min + ((rand(max)+1) *10).to_i
|
87
|
+
res = count.to_s + "/"
|
88
|
+
|
89
|
+
if readable
|
90
|
+
res << Digest::SHA1.hexdigest(rand(count * 100).to_s) * (count / 40)
|
91
|
+
else
|
92
|
+
res << Digest::SHA1.digest(rand(count * 100).to_s) * (count / 20)
|
93
|
+
end
|
94
|
+
|
95
|
+
return res
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def test_horrible_queries
|
100
|
+
parser = HttpParser.new
|
101
|
+
|
102
|
+
# then that large header names are caught
|
103
|
+
10.times do |c|
|
104
|
+
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-#{rand_data(1024, 1024+(c*1024))}: Test\r\n\r\n"
|
105
|
+
assert_raises Mongrel::HttpParserError do
|
106
|
+
parser.execute({}, get, 0)
|
107
|
+
parser.reset
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# then that large mangled field values are caught
|
112
|
+
10.times do |c|
|
113
|
+
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-Test: #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
|
114
|
+
assert_raises Mongrel::HttpParserError do
|
115
|
+
parser.execute({}, get, 0)
|
116
|
+
parser.reset
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# then large headers are rejected too
|
121
|
+
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\n"
|
122
|
+
get << "X-Test: test\r\n" * (80 * 1024)
|
123
|
+
assert_raises Mongrel::HttpParserError do
|
124
|
+
parser.execute({}, get, 0)
|
125
|
+
parser.reset
|
126
|
+
end
|
127
|
+
|
128
|
+
# finally just that random garbage gets blocked all the time
|
129
|
+
10.times do |c|
|
130
|
+
get = "GET #{rand_data(1024, 1024+(c*1024), false)} #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
|
131
|
+
assert_raises Mongrel::HttpParserError do
|
132
|
+
parser.execute({}, get, 0)
|
133
|
+
parser.reset
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
def test_query_parse
|
142
|
+
res = HttpRequest.query_parse("zed=1&frank=#{HttpRequest.escape('&&& ')}")
|
143
|
+
assert res["zed"], "didn't get the request right"
|
144
|
+
assert res["frank"], "no frank"
|
145
|
+
assert_equal "1", res["zed"], "wrong result"
|
146
|
+
assert_equal "&&& ", HttpRequest.unescape(res["frank"]), "wrong result"
|
147
|
+
|
148
|
+
res = HttpRequest.query_parse("zed=1&zed=2&zed=3&frank=11;zed=45")
|
149
|
+
assert res["zed"], "didn't get the request right"
|
150
|
+
assert res["frank"], "no frank"
|
151
|
+
assert_equal 4,res["zed"].length, "wrong number for zed"
|
152
|
+
assert_equal "11",res["frank"], "wrong number for frank"
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Copyright (c) 2005 Zed A. Shaw
|
2
|
+
# You can redistribute it and/or modify it under the same terms as Ruby.
|
3
|
+
#
|
4
|
+
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
5
|
+
# for more information.
|
6
|
+
|
7
|
+
require 'test/test_helper'
|
8
|
+
|
9
|
+
class RedirectHandlerTest < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@port = process_based_port
|
13
|
+
redirect_test_io do
|
14
|
+
@server = Mongrel::HttpServer.new('127.0.0.1', @port)
|
15
|
+
end
|
16
|
+
@server.run
|
17
|
+
@client = Net::HTTP.new('127.0.0.1', @port)
|
18
|
+
end
|
19
|
+
|
20
|
+
def teardown
|
21
|
+
@server.stop(true)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_simple_redirect
|
25
|
+
tester = Mongrel::RedirectHandler.new('/yo')
|
26
|
+
@server.register("/test", tester)
|
27
|
+
|
28
|
+
sleep(1)
|
29
|
+
res = @client.request_get('/test')
|
30
|
+
assert res != nil, "Didn't get a response"
|
31
|
+
assert_equal ['/yo'], res.get_fields('Location')
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_rewrite
|
35
|
+
tester = Mongrel::RedirectHandler.new(/(\w+)/, '+\1+')
|
36
|
+
@server.register("/test", tester)
|
37
|
+
|
38
|
+
sleep(1)
|
39
|
+
res = @client.request_get('/test/something')
|
40
|
+
assert_equal ['/+test+/+something+'], res.get_fields('Location')
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
|