sho-mongrel 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/CHANGELOG +18 -0
  2. data/COPYING +55 -0
  3. data/LICENSE +55 -0
  4. data/Manifest +69 -0
  5. data/README +74 -0
  6. data/Rakefile +202 -0
  7. data/TODO +5 -0
  8. data/bin/mongrel_rails +283 -0
  9. data/examples/builder.rb +29 -0
  10. data/examples/camping/README +3 -0
  11. data/examples/camping/blog.rb +294 -0
  12. data/examples/camping/tepee.rb +149 -0
  13. data/examples/httpd.conf +474 -0
  14. data/examples/mime.yaml +3 -0
  15. data/examples/mongrel.conf +9 -0
  16. data/examples/mongrel_simple_ctrl.rb +92 -0
  17. data/examples/mongrel_simple_service.rb +116 -0
  18. data/examples/monitrc +57 -0
  19. data/examples/random_thrash.rb +19 -0
  20. data/examples/simpletest.rb +52 -0
  21. data/examples/webrick_compare.rb +20 -0
  22. data/ext/http11/ext_help.h +22 -0
  23. data/ext/http11/extconf.rb +6 -0
  24. data/ext/http11/http11.c +402 -0
  25. data/ext/http11/http11_parser.c +1221 -0
  26. data/ext/http11/http11_parser.h +49 -0
  27. data/ext/http11/http11_parser.java.rl +170 -0
  28. data/ext/http11/http11_parser.rl +152 -0
  29. data/ext/http11/http11_parser_common.rl +54 -0
  30. data/ext/http11_java/Http11Service.java +13 -0
  31. data/ext/http11_java/org/jruby/mongrel/Http11.java +266 -0
  32. data/ext/http11_java/org/jruby/mongrel/Http11Parser.java +572 -0
  33. data/lib/mongrel.rb +355 -0
  34. data/lib/mongrel/camping.rb +107 -0
  35. data/lib/mongrel/cgi.rb +181 -0
  36. data/lib/mongrel/command.rb +222 -0
  37. data/lib/mongrel/configurator.rb +392 -0
  38. data/lib/mongrel/const.rb +110 -0
  39. data/lib/mongrel/debug.rb +203 -0
  40. data/lib/mongrel/gems.rb +22 -0
  41. data/lib/mongrel/handlers.rb +468 -0
  42. data/lib/mongrel/header_out.rb +28 -0
  43. data/lib/mongrel/http_request.rb +155 -0
  44. data/lib/mongrel/http_response.rb +163 -0
  45. data/lib/mongrel/init.rb +10 -0
  46. data/lib/mongrel/mime_types.yml +616 -0
  47. data/lib/mongrel/rails.rb +195 -0
  48. data/lib/mongrel/stats.rb +89 -0
  49. data/lib/mongrel/tcphack.rb +18 -0
  50. data/lib/mongrel/uri_classifier.rb +76 -0
  51. data/mongrel-public_cert.pem +20 -0
  52. data/setup.rb +1585 -0
  53. data/sho-mongrel.gemspec +47 -0
  54. data/test/mime.yaml +3 -0
  55. data/test/mongrel.conf +1 -0
  56. data/test/test_cgi_wrapper.rb +26 -0
  57. data/test/test_command.rb +86 -0
  58. data/test/test_conditional.rb +107 -0
  59. data/test/test_configurator.rb +87 -0
  60. data/test/test_debug.rb +25 -0
  61. data/test/test_handlers.rb +123 -0
  62. data/test/test_http11.rb +156 -0
  63. data/test/test_redirect_handler.rb +44 -0
  64. data/test/test_request_progress.rb +99 -0
  65. data/test/test_response.rb +127 -0
  66. data/test/test_stats.rb +35 -0
  67. data/test/test_uriclassifier.rb +261 -0
  68. data/test/test_ws.rb +115 -0
  69. data/test/testhelp.rb +66 -0
  70. data/tools/trickletest.rb +45 -0
  71. metadata +201 -0
@@ -0,0 +1,47 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{sho-mongrel}
5
+ s.version = "1.1.5"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Zed A. Shaw"]
9
+ s.date = %q{2009-10-25}
10
+ s.default_executable = %q{mongrel_rails}
11
+ s.description = %q{Mongrel patched to run on Ruby 1.9 and respect Rails cache directives. Nothing more, nothing less.}
12
+ s.email = %q{}
13
+ s.executables = ["mongrel_rails"]
14
+ s.extensions = ["ext/http11/extconf.rb"]
15
+ s.extra_rdoc_files = ["CHANGELOG", "COPYING", "lib/mongrel/camping.rb", "lib/mongrel/cgi.rb", "lib/mongrel/command.rb", "lib/mongrel/configurator.rb", "lib/mongrel/const.rb", "lib/mongrel/debug.rb", "lib/mongrel/gems.rb", "lib/mongrel/handlers.rb", "lib/mongrel/header_out.rb", "lib/mongrel/http_request.rb", "lib/mongrel/http_response.rb", "lib/mongrel/init.rb", "lib/mongrel/rails.rb", "lib/mongrel/stats.rb", "lib/mongrel/tcphack.rb", "lib/mongrel/uri_classifier.rb", "lib/mongrel.rb", "LICENSE", "README"]
16
+ s.files = ["bin/mongrel_rails", "CHANGELOG", "COPYING", "examples/builder.rb", "examples/camping/blog.rb", "examples/camping/README", "examples/camping/tepee.rb", "examples/httpd.conf", "examples/mime.yaml", "examples/mongrel.conf", "examples/mongrel_simple_ctrl.rb", "examples/mongrel_simple_service.rb", "examples/monitrc", "examples/random_thrash.rb", "examples/simpletest.rb", "examples/webrick_compare.rb", "ext/http11/ext_help.h", "ext/http11/extconf.rb", "ext/http11/http11.c", "ext/http11/http11_parser.c", "ext/http11/http11_parser.h", "ext/http11/http11_parser.java.rl", "ext/http11/http11_parser.rl", "ext/http11/http11_parser_common.rl", "ext/http11_java/Http11Service.java", "ext/http11_java/org/jruby/mongrel/Http11.java", "ext/http11_java/org/jruby/mongrel/Http11Parser.java", "lib/mongrel/camping.rb", "lib/mongrel/cgi.rb", "lib/mongrel/command.rb", "lib/mongrel/configurator.rb", "lib/mongrel/const.rb", "lib/mongrel/debug.rb", "lib/mongrel/gems.rb", "lib/mongrel/handlers.rb", "lib/mongrel/header_out.rb", "lib/mongrel/http_request.rb", "lib/mongrel/http_response.rb", "lib/mongrel/init.rb", "lib/mongrel/mime_types.yml", "lib/mongrel/rails.rb", "lib/mongrel/stats.rb", "lib/mongrel/tcphack.rb", "lib/mongrel/uri_classifier.rb", "lib/mongrel.rb", "LICENSE", "Manifest", "mongrel-public_cert.pem", "sho-mongrel.gemspec", "README", "setup.rb", "test/mime.yaml", "test/mongrel.conf", "test/test_cgi_wrapper.rb", "test/test_command.rb", "test/test_conditional.rb", "test/test_configurator.rb", "test/test_debug.rb", "test/test_handlers.rb", "test/test_http11.rb", "test/test_redirect_handler.rb", "test/test_request_progress.rb", "test/test_response.rb", "test/test_stats.rb", "test/test_uriclassifier.rb", "test/test_ws.rb", "test/testhelp.rb", "TODO", "tools/trickletest.rb", "Rakefile"]
17
+ s.homepage = %q{http://mongrel.rubyforge.org}
18
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Mongrel", "--main", "README"]
19
+ s.require_paths = ["lib", "ext"]
20
+ s.required_ruby_version = Gem::Requirement.new(">= 1.8.4")
21
+ s.rubyforge_project = %q{mongrel}
22
+ s.rubygems_version = %q{1.3.5}
23
+ s.summary = %q{A small fast HTTP library and server that runs Rails, Camping, Nitro and Iowa apps.}
24
+ s.test_files = ["test/test_cgi_wrapper.rb", "test/test_command.rb", "test/test_conditional.rb", "test/test_configurator.rb", "test/test_debug.rb", "test/test_handlers.rb", "test/test_http11.rb", "test/test_redirect_handler.rb", "test/test_request_progress.rb", "test/test_response.rb", "test/test_stats.rb", "test/test_uriclassifier.rb", "test/test_ws.rb"]
25
+
26
+ if s.respond_to? :specification_version then
27
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
28
+ s.specification_version = 3
29
+
30
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
31
+ s.add_runtime_dependency(%q<gem_plugin>, [">= 0.2.3"])
32
+ s.add_runtime_dependency(%q<daemons>, [">= 1.0.3"])
33
+ s.add_runtime_dependency(%q<fastthread>, [">= 1.0.1"])
34
+ s.add_runtime_dependency(%q<cgi_multipart_eof_fix>, [">= 2.4"])
35
+ else
36
+ s.add_dependency(%q<gem_plugin>, [">= 0.2.3"])
37
+ s.add_dependency(%q<daemons>, [">= 1.0.3"])
38
+ s.add_dependency(%q<fastthread>, [">= 1.0.1"])
39
+ s.add_dependency(%q<cgi_multipart_eof_fix>, [">= 2.4"])
40
+ end
41
+ else
42
+ s.add_dependency(%q<gem_plugin>, [">= 0.2.3"])
43
+ s.add_dependency(%q<daemons>, [">= 1.0.3"])
44
+ s.add_dependency(%q<fastthread>, [">= 1.0.1"])
45
+ s.add_dependency(%q<cgi_multipart_eof_fix>, [">= 2.4"])
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ ---
2
+ .jpeg: image/jpeg
3
+ .png: image/test
@@ -0,0 +1 @@
1
+ uri "/fromconf", :handler => Mongrel::Error404Handler.new("test")
@@ -0,0 +1,26 @@
1
+
2
+ require 'test/testhelp'
3
+
4
+ class MockHttpRequest
5
+ attr_reader :body
6
+
7
+ def params
8
+ return { 'REQUEST_METHOD' => 'GET'}
9
+ end
10
+ end
11
+
12
+ class CGIWrapperTest < Test::Unit::TestCase
13
+
14
+ def test_set_cookies_output_cookies
15
+ request = MockHttpRequest.new
16
+ response = nil # not needed for this test
17
+ output_headers = {}
18
+
19
+ cgi = Mongrel::CGIWrapper.new(request, response)
20
+ session = CGI::Session.new(cgi, 'database_manager' => CGI::Session::MemoryStore)
21
+ cgi.send_cookies(output_headers)
22
+
23
+ assert(output_headers.has_key?("Set-Cookie"))
24
+ assert_equal("_session_id="+session.session_id+"; path=", output_headers["Set-Cookie"])
25
+ end
26
+ end
@@ -0,0 +1,86 @@
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/testhelp'
8
+
9
+ class TestCommand < GemPlugin::Plugin "/commands"
10
+ include Mongrel::Command::Base
11
+
12
+ def configure
13
+ options [
14
+ ["-e", "--environment ENV", "Rails environment to run as", :@environment, ENV['RAILS_ENV'] || "development"],
15
+ ['', '--user USER', "User to run as", :@user, nil],
16
+ ["-d", "--daemonize", "Whether to run in the background or not", :@daemon, false],
17
+ ["-x", "--test", "Used to let the test run failures", :@test, false],
18
+ ]
19
+ end
20
+
21
+ def validate
22
+ valid_dir? ".", "Can't validate current directory."
23
+ valid_exists? "Rakefile", "Rakefile not there, test is invalid."
24
+ if @test
25
+ valid_exist? "BADFILE", "Yeah, badfile"
26
+ valid_file? "BADFILE", "Not even a file"
27
+ valid_dir? "BADDIR", "No dir here"
28
+ valid? false, "Total failure"
29
+ end
30
+
31
+ return @valid
32
+ end
33
+
34
+
35
+ def run
36
+ $test_command_ran = true
37
+ end
38
+ end
39
+
40
+ class CommandTest < Test::Unit::TestCase
41
+
42
+ def setup
43
+ $test_command_ran = false
44
+ end
45
+
46
+ def teardown
47
+ end
48
+
49
+ def run_cmd(args)
50
+ Mongrel::Command::Registry.instance.run args
51
+ end
52
+
53
+ def test_run_command
54
+ redirect_test_io do
55
+ run_cmd ["testcommand"]
56
+ assert $test_command_ran, "command didn't run"
57
+ end
58
+ end
59
+
60
+ def test_command_error
61
+ redirect_test_io do
62
+ run_cmd ["crapcommand"]
63
+ end
64
+ end
65
+
66
+ def test_command_listing
67
+ redirect_test_io do
68
+ run_cmd ["help"]
69
+ end
70
+ end
71
+
72
+ def test_options
73
+ redirect_test_io do
74
+ run_cmd ["testcommand","-h"]
75
+ run_cmd ["testcommand","--help"]
76
+ run_cmd ["testcommand","-e","test","-d","--user"]
77
+ end
78
+ end
79
+
80
+ def test_version
81
+ redirect_test_io do
82
+ run_cmd ["testcommand", "--version"]
83
+ end
84
+ end
85
+
86
+ end
@@ -0,0 +1,107 @@
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/testhelp'
8
+
9
+ include Mongrel
10
+
11
+ class ConditionalResponseTest < Test::Unit::TestCase
12
+ def setup
13
+ @server = HttpServer.new('127.0.0.1', 3501)
14
+ @server.register('/', Mongrel::DirHandler.new('.'))
15
+ @server.run
16
+
17
+ @http = Net::HTTP.new(@server.host, @server.port)
18
+
19
+ # get the ETag and Last-Modified headers
20
+ @path = '/README'
21
+ res = @http.start { |http| http.get(@path) }
22
+ assert_not_nil @etag = res['ETag']
23
+ assert_not_nil @last_modified = res['Last-Modified']
24
+ assert_not_nil @content_length = res['Content-Length']
25
+ end
26
+
27
+ def teardown
28
+ @server.stop(true)
29
+ end
30
+
31
+ # status should be 304 Not Modified when If-None-Match is the matching ETag
32
+ def test_not_modified_via_if_none_match
33
+ assert_status_for_get_and_head Net::HTTPNotModified, 'If-None-Match' => @etag
34
+ end
35
+
36
+ # status should be 304 Not Modified when If-Modified-Since is the matching Last-Modified date
37
+ def test_not_modified_via_if_modified_since
38
+ assert_status_for_get_and_head Net::HTTPNotModified, 'If-Modified-Since' => @last_modified
39
+ end
40
+
41
+ # status should be 304 Not Modified when If-None-Match is the matching ETag
42
+ # and If-Modified-Since is the matching Last-Modified date
43
+ def test_not_modified_via_if_none_match_and_if_modified_since
44
+ assert_status_for_get_and_head Net::HTTPNotModified, 'If-None-Match' => @etag, 'If-Modified-Since' => @last_modified
45
+ end
46
+
47
+ # status should be 200 OK when If-None-Match is invalid
48
+ def test_invalid_if_none_match
49
+ assert_status_for_get_and_head Net::HTTPOK, 'If-None-Match' => 'invalid'
50
+ assert_status_for_get_and_head Net::HTTPOK, 'If-None-Match' => 'invalid', 'If-Modified-Since' => @last_modified
51
+ end
52
+
53
+ # status should be 200 OK when If-Modified-Since is invalid
54
+ def test_invalid_if_modified_since
55
+ assert_status_for_get_and_head Net::HTTPOK, 'If-Modified-Since' => 'invalid'
56
+ assert_status_for_get_and_head Net::HTTPOK, 'If-None-Match' => @etag, 'If-Modified-Since' => 'invalid'
57
+ end
58
+
59
+ # status should be 304 Not Modified when If-Modified-Since is greater than the Last-Modified header, but less than the system time
60
+ def test_if_modified_since_greater_than_last_modified
61
+ sleep 2
62
+ last_modified_plus_1 = (Time.httpdate(@last_modified) + 1).httpdate
63
+ assert_status_for_get_and_head Net::HTTPNotModified, 'If-Modified-Since' => last_modified_plus_1
64
+ assert_status_for_get_and_head Net::HTTPNotModified, 'If-None-Match' => @etag, 'If-Modified-Since' => last_modified_plus_1
65
+ end
66
+
67
+ # status should be 200 OK when If-Modified-Since is less than the Last-Modified header
68
+ def test_if_modified_since_less_than_last_modified
69
+ last_modified_minus_1 = (Time.httpdate(@last_modified) - 1).httpdate
70
+ assert_status_for_get_and_head Net::HTTPOK, 'If-Modified-Since' => last_modified_minus_1
71
+ assert_status_for_get_and_head Net::HTTPOK, 'If-None-Match' => @etag, 'If-Modified-Since' => last_modified_minus_1
72
+ end
73
+
74
+ # status should be 200 OK when If-Modified-Since is a date in the future
75
+ def test_future_if_modified_since
76
+ the_future = Time.at(2**31-1).httpdate
77
+ assert_status_for_get_and_head Net::HTTPOK, 'If-Modified-Since' => the_future
78
+ assert_status_for_get_and_head Net::HTTPOK, 'If-None-Match' => @etag, 'If-Modified-Since' => the_future
79
+ end
80
+
81
+ # status should be 200 OK when If-None-Match is a wildcard
82
+ def test_wildcard_match
83
+ assert_status_for_get_and_head Net::HTTPOK, 'If-None-Match' => '*'
84
+ assert_status_for_get_and_head Net::HTTPOK, 'If-None-Match' => '*', 'If-Modified-Since' => @last_modified
85
+ end
86
+
87
+ private
88
+
89
+ # assert the response status is correct for GET and HEAD
90
+ def assert_status_for_get_and_head(response_class, headers = {})
91
+ %w{ get head }.each do |method|
92
+ res = @http.send(method, @path, headers)
93
+ assert_kind_of response_class, res
94
+ assert_equal @etag, res['ETag']
95
+ case response_class.to_s
96
+ when 'Net::HTTPNotModified' then
97
+ assert_nil res['Last-Modified']
98
+ assert_nil res['Content-Length']
99
+ when 'Net::HTTPOK' then
100
+ assert_equal @last_modified, res['Last-Modified']
101
+ assert_equal @content_length, res['Content-Length']
102
+ else
103
+ fail "Incorrect response class: #{response_class}"
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,87 @@
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/testhelp'
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
+ @config = nil
33
+
34
+ redirect_test_io do
35
+ @config = Mongrel::Configurator.new :host => "localhost" do
36
+ listener :port => 4501 do
37
+ # 2 in front should run, but the sentinel shouldn't since dirhandler processes the request
38
+ uri "/", :handler => plugin("/handlers/testplugin")
39
+ uri "/", :handler => plugin("/handlers/testplugin")
40
+ uri "/", :handler => Mongrel::DirHandler.new(".")
41
+ uri "/", :handler => plugin("/handlers/testplugin")
42
+
43
+ uri "/test", :handler => plugin("/handlers/testplugin")
44
+ uri "/test", :handler => plugin("/handlers/testplugin")
45
+ uri "/test", :handler => Mongrel::DirHandler.new(".")
46
+ uri "/test", :handler => plugin("/handlers/testplugin")
47
+
48
+ debug "/"
49
+ setup_signals
50
+
51
+ run_config(File.dirname(__FILE__) + "/../test/mongrel.conf")
52
+ load_mime_map(File.dirname(__FILE__) + "/../test/mime.yaml")
53
+
54
+ run
55
+ end
56
+ end
57
+ end
58
+
59
+ # pp @config.listeners.values.first.classifier.routes
60
+
61
+ @config.listeners.each do |host,listener|
62
+ assert listener.classifier.uris.length == 3, "Wrong number of registered URIs"
63
+ assert listener.classifier.uris.include?("/"), "/ not registered"
64
+ assert listener.classifier.uris.include?("/test"), "/test not registered"
65
+ end
66
+
67
+ res = Net::HTTP.get(URI.parse('http://localhost:4501/test'))
68
+ assert res != nil, "Didn't get a response"
69
+ assert $test_plugin_fired == 3, "Test filter plugin didn't run 3 times."
70
+
71
+ redirect_test_io do
72
+ res = Net::HTTP.get(URI.parse('http://localhost:4501/'))
73
+
74
+ assert res != nil, "Didn't get a response"
75
+ assert $test_plugin_fired == 6, "Test filter plugin didn't run 6 times."
76
+ end
77
+
78
+ redirect_test_io do
79
+ @config.stop(false, true)
80
+ end
81
+
82
+ assert_raise Errno::EBADF, Errno::ECONNREFUSED do
83
+ res = Net::HTTP.get(URI.parse("http://localhost:4501/"))
84
+ end
85
+ end
86
+
87
+ 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/testhelp'
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,123 @@
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/testhelp'
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
+ stats = Mongrel::StatisticsFilter.new(:sample_rate => 1)
38
+
39
+ @config = Mongrel::Configurator.new :host => '127.0.0.1', :port => 9998 do
40
+ listener do
41
+ uri "/", :handler => SimpleHandler.new
42
+ uri "/", :handler => stats
43
+ uri "/404", :handler => Mongrel::Error404Handler.new("Not found")
44
+ uri "/dumb", :handler => Mongrel::DeflateFilter.new
45
+ uri "/dumb", :handler => DumbHandler.new, :in_front => true
46
+ uri "/files", :handler => Mongrel::DirHandler.new("doc")
47
+ uri "/files_nodir", :handler => Mongrel::DirHandler.new("doc", listing_allowed=false, index_html="none")
48
+ uri "/status", :handler => Mongrel::StatusHandler.new(:stats_filter => stats)
49
+ uri "/relative", :handler => Mongrel::DirHandler.new(nil, listing_allowed=false, index_html="none")
50
+ end
51
+ end
52
+
53
+ File.open("/tmp/testfile", 'w') do
54
+ # Do nothing
55
+ end
56
+
57
+ @config.run
58
+ end
59
+
60
+ def teardown
61
+ @config.stop(false, true)
62
+ File.delete "/tmp/testfile"
63
+ end
64
+
65
+ def test_more_web_server
66
+ res = hit([ "http://localhost:9998/test",
67
+ "http://localhost:9998/dumb",
68
+ "http://localhost:9998/404",
69
+ "http://localhost:9998/files/rdoc/index.html",
70
+ "http://localhost:9998/files/rdoc/nothere.html",
71
+ "http://localhost:9998/files/rdoc/",
72
+ "http://localhost:9998/files_nodir/rdoc/",
73
+ "http://localhost:9998/status",
74
+ ])
75
+ check_status res, String
76
+ end
77
+
78
+ def test_nil_dirhandler
79
+ # Camping uses this internally
80
+ handler = Mongrel::DirHandler.new(nil, false)
81
+ assert handler.can_serve("/tmp/testfile")
82
+ # Not a bug! A nil @file parameter is the only circumstance under which
83
+ # we are allowed to serve any existing file
84
+ assert handler.can_serve("../../../../../../../../../../tmp/testfile")
85
+ end
86
+
87
+ def test_non_nil_dirhandler_is_not_vulnerable_to_path_traversal
88
+ # The famous security bug of Mongrel 1.1.2
89
+ handler = Mongrel::DirHandler.new("/doc", false)
90
+ assert_nil handler.can_serve("/tmp/testfile")
91
+ assert_nil handler.can_serve("../../../../../../../../../../tmp/testfile")
92
+ end
93
+
94
+ def test_deflate
95
+ Net::HTTP.start("localhost", 9998) do |h|
96
+ # Test that no accept-encoding returns a non-deflated response
97
+ req = h.get("/dumb", {"Accept-Encoding" => "plain"})
98
+ assert(
99
+ !req['Content-Encoding'] ||
100
+ !req['Content-Encoding'].include?('deflate'))
101
+ assert_equal "test", req.body
102
+
103
+ req = h.get("/dumb", {"Accept-Encoding" => "deflate"})
104
+ # -MAX_WBITS stops zlib from looking for a zlib header
105
+ inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
106
+ assert req['Content-Encoding'].include?('deflate')
107
+ assert_equal "test", inflater.inflate(req.body)
108
+ end
109
+ end
110
+
111
+ # TODO: find out why this fails on win32 but nowhere else
112
+ #def test_posting_fails_dirhandler
113
+ # req = Net::HTTP::Post.new("http://localhost:9998/files/rdoc/")
114
+ # req.set_form_data({'from'=>'2005-01-01', 'to'=>'2005-03-31'}, ';')
115
+ # res = hit [["http://localhost:9998/files/rdoc/",req]]
116
+ # check_status res, Net::HTTPNotFound
117
+ #end
118
+
119
+ def test_unregister
120
+ @config.listeners["127.0.0.1:9998"].unregister("/")
121
+ end
122
+ end
123
+