engineyard-mongrel 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|