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.
Files changed (72) hide show
  1. data/CHANGELOG +16 -0
  2. data/CONTRIBUTORS +17 -0
  3. data/COPYING +55 -0
  4. data/LICENSE +55 -0
  5. data/Manifest +71 -0
  6. data/README +74 -0
  7. data/bin/mongrel_rails +285 -0
  8. data/examples/builder.rb +29 -0
  9. data/examples/camping/README +3 -0
  10. data/examples/camping/blog.rb +294 -0
  11. data/examples/camping/tepee.rb +149 -0
  12. data/examples/httpd.conf +474 -0
  13. data/examples/mime.yaml +3 -0
  14. data/examples/mongrel.conf +9 -0
  15. data/examples/mongrel_simple_ctrl.rb +92 -0
  16. data/examples/mongrel_simple_service.rb +116 -0
  17. data/examples/monitrc +57 -0
  18. data/examples/random_thrash.rb +19 -0
  19. data/examples/simpletest.rb +52 -0
  20. data/examples/webrick_compare.rb +20 -0
  21. data/ext/http11/ext_help.h +15 -0
  22. data/ext/http11/extconf.rb +6 -0
  23. data/ext/http11/http11.c +527 -0
  24. data/ext/http11/http11_parser.c +1243 -0
  25. data/ext/http11/http11_parser.h +49 -0
  26. data/ext/http11/http11_parser.java.rl +171 -0
  27. data/ext/http11/http11_parser.rl +152 -0
  28. data/ext/http11/http11_parser_common.rl +54 -0
  29. data/ext/http11_java/Http11Service.java +13 -0
  30. data/ext/http11_java/org/jruby/mongrel/Http11.java +266 -0
  31. data/ext/http11_java/org/jruby/mongrel/Http11Parser.java +474 -0
  32. data/lib/mongrel.rb +360 -0
  33. data/lib/mongrel/camping.rb +107 -0
  34. data/lib/mongrel/cgi.rb +181 -0
  35. data/lib/mongrel/command.rb +222 -0
  36. data/lib/mongrel/configurator.rb +389 -0
  37. data/lib/mongrel/const.rb +110 -0
  38. data/lib/mongrel/debug.rb +203 -0
  39. data/lib/mongrel/gems.rb +22 -0
  40. data/lib/mongrel/handlers.rb +468 -0
  41. data/lib/mongrel/header_out.rb +28 -0
  42. data/lib/mongrel/http_request.rb +155 -0
  43. data/lib/mongrel/http_response.rb +166 -0
  44. data/lib/mongrel/init.rb +10 -0
  45. data/lib/mongrel/mime_types.yml +616 -0
  46. data/lib/mongrel/rails.rb +214 -0
  47. data/lib/mongrel/stats.rb +89 -0
  48. data/lib/mongrel/tcphack.rb +18 -0
  49. data/lib/mongrel/uri_classifier.rb +76 -0
  50. data/mongrel-public_cert.pem +20 -0
  51. data/setup.rb +1585 -0
  52. data/test/benchmark/previous.rb +11 -0
  53. data/test/benchmark/simple.rb +11 -0
  54. data/test/benchmark/utils.rb +82 -0
  55. data/test/mime.yaml +3 -0
  56. data/test/mongrel.conf +1 -0
  57. data/test/test_helper.rb +79 -0
  58. data/test/tools/trickletest.rb +45 -0
  59. data/test/unit/test_cgi_wrapper.rb +26 -0
  60. data/test/unit/test_command.rb +86 -0
  61. data/test/unit/test_conditional.rb +107 -0
  62. data/test/unit/test_configurator.rb +88 -0
  63. data/test/unit/test_debug.rb +25 -0
  64. data/test/unit/test_handlers.rb +136 -0
  65. data/test/unit/test_http_parser.rb +156 -0
  66. data/test/unit/test_redirect_handler.rb +45 -0
  67. data/test/unit/test_request_progress.rb +100 -0
  68. data/test/unit/test_response.rb +127 -0
  69. data/test/unit/test_stats.rb +35 -0
  70. data/test/unit/test_uriclassifier.rb +261 -0
  71. data/test/unit/test_ws.rb +116 -0
  72. 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
+