mongrel 1.1.2-java
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of mongrel might be problematic. Click here for more details.
- data.tar.gz.sig +1 -0
- data/CHANGELOG +12 -0
- data/COPYING +55 -0
- data/LICENSE +55 -0
- data/Manifest +69 -0
- data/README +74 -0
- data/TODO +5 -0
- data/bin/mongrel_rails +283 -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 +14 -0
- data/ext/http11/extconf.rb +6 -0
- data/ext/http11/http11.c +402 -0
- data/ext/http11/http11_parser.c +1221 -0
- data/ext/http11/http11_parser.h +49 -0
- data/ext/http11/http11_parser.java.rl +170 -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 +572 -0
- data/lib/http11.jar +0 -0
- data/lib/mongrel.rb +355 -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 +388 -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 +163 -0
- data/lib/mongrel/init.rb +10 -0
- data/lib/mongrel/mime_types.yml +616 -0
- data/lib/mongrel/rails.rb +185 -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/mongrel.gemspec +263 -0
- data/setup.rb +1585 -0
- data/test/mime.yaml +3 -0
- data/test/mongrel.conf +1 -0
- data/test/test_cgi_wrapper.rb +26 -0
- data/test/test_command.rb +86 -0
- data/test/test_conditional.rb +107 -0
- data/test/test_configurator.rb +87 -0
- data/test/test_debug.rb +25 -0
- data/test/test_handlers.rb +103 -0
- data/test/test_http11.rb +156 -0
- data/test/test_redirect_handler.rb +44 -0
- data/test/test_request_progress.rb +99 -0
- data/test/test_response.rb +127 -0
- data/test/test_stats.rb +35 -0
- data/test/test_uriclassifier.rb +261 -0
- data/test/test_ws.rb +115 -0
- data/test/testhelp.rb +66 -0
- data/tools/trickletest.rb +45 -0
- metadata +186 -0
- metadata.gz.sig +4 -0
data/test/test_http11.rb
ADDED
@@ -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/testhelp'
|
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_dumbfuck_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,44 @@
|
|
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 RedirectHandlerTest < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def setup
|
12
|
+
redirect_test_io do
|
13
|
+
@server = Mongrel::HttpServer.new('127.0.0.1', 9998)
|
14
|
+
end
|
15
|
+
@server.run
|
16
|
+
@client = Net::HTTP.new('127.0.0.1', 9998)
|
17
|
+
end
|
18
|
+
|
19
|
+
def teardown
|
20
|
+
@server.stop(true)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_simple_redirect
|
24
|
+
tester = Mongrel::RedirectHandler.new('/yo')
|
25
|
+
@server.register("/test", tester)
|
26
|
+
|
27
|
+
sleep(1)
|
28
|
+
res = @client.request_get('/test')
|
29
|
+
assert res != nil, "Didn't get a response"
|
30
|
+
assert_equal ['/yo'], res.get_fields('Location')
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_rewrite
|
34
|
+
tester = Mongrel::RedirectHandler.new(/(\w+)/, '+\1+')
|
35
|
+
@server.register("/test", tester)
|
36
|
+
|
37
|
+
sleep(1)
|
38
|
+
res = @client.request_get('/test/something')
|
39
|
+
assert_equal ['/+test+/+something+'], res.get_fields('Location')
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
@@ -0,0 +1,99 @@
|
|
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 UploadBeginHandler < Mongrel::HttpHandler
|
10
|
+
attr_reader :request_began, :request_progressed, :request_processed
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@request_notify = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset
|
17
|
+
@request_began = false
|
18
|
+
@request_progressed = false
|
19
|
+
@request_processed = false
|
20
|
+
end
|
21
|
+
|
22
|
+
def request_begins(params)
|
23
|
+
@request_began = true
|
24
|
+
end
|
25
|
+
|
26
|
+
def request_progress(params,len,total)
|
27
|
+
@request_progressed = true
|
28
|
+
end
|
29
|
+
|
30
|
+
def process(request, response)
|
31
|
+
@request_processed = true
|
32
|
+
response.start do |head,body|
|
33
|
+
body.write("test")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
class RequestProgressTest < Test::Unit::TestCase
|
40
|
+
def setup
|
41
|
+
redirect_test_io do
|
42
|
+
@server = Mongrel::HttpServer.new("127.0.0.1", 9998)
|
43
|
+
end
|
44
|
+
@handler = UploadBeginHandler.new
|
45
|
+
@server.register("/upload", @handler)
|
46
|
+
@server.run
|
47
|
+
end
|
48
|
+
|
49
|
+
def teardown
|
50
|
+
@server.stop(true)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_begin_end_progress
|
54
|
+
Net::HTTP.get("localhost", "/upload", 9998)
|
55
|
+
assert @handler.request_began
|
56
|
+
assert @handler.request_progressed
|
57
|
+
assert @handler.request_processed
|
58
|
+
end
|
59
|
+
|
60
|
+
def call_and_assert_handlers_in_turn(handlers)
|
61
|
+
# reset all handlers
|
62
|
+
handlers.each { |h| h.reset }
|
63
|
+
|
64
|
+
# make the call
|
65
|
+
Net::HTTP.get("localhost", "/upload", 9998)
|
66
|
+
|
67
|
+
# assert that each one was fired
|
68
|
+
handlers.each { |h|
|
69
|
+
assert h.request_began && h.request_progressed && h.request_processed,
|
70
|
+
"Callbacks NOT fired for #{h}"
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_more_than_one_begin_end_progress
|
75
|
+
handlers = [@handler]
|
76
|
+
|
77
|
+
second = UploadBeginHandler.new
|
78
|
+
@server.register("/upload", second)
|
79
|
+
handlers << second
|
80
|
+
call_and_assert_handlers_in_turn(handlers)
|
81
|
+
|
82
|
+
# check three handlers
|
83
|
+
third = UploadBeginHandler.new
|
84
|
+
@server.register("/upload", third)
|
85
|
+
handlers << third
|
86
|
+
call_and_assert_handlers_in_turn(handlers)
|
87
|
+
|
88
|
+
# remove handlers to make sure they've all gone away
|
89
|
+
@server.unregister("/upload")
|
90
|
+
handlers.each { |h| h.reset }
|
91
|
+
Net::HTTP.get("localhost", "/upload", 9998)
|
92
|
+
handlers.each { |h|
|
93
|
+
assert !h.request_began && !h.request_progressed && !h.request_processed
|
94
|
+
}
|
95
|
+
|
96
|
+
# re-register upload to the state before this test
|
97
|
+
@server.register("/upload", @handler)
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,127 @@
|
|
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 ResponseTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def test_response_headers
|
14
|
+
out = StringIO.new
|
15
|
+
resp = HttpResponse.new(out)
|
16
|
+
resp.status = 200
|
17
|
+
resp.header["Accept"] = "text/plain"
|
18
|
+
resp.header["X-Whatever"] = "stuff"
|
19
|
+
resp.body.write("test")
|
20
|
+
resp.finished
|
21
|
+
|
22
|
+
assert out.length > 0, "output didn't have data"
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_response_200
|
26
|
+
io = StringIO.new
|
27
|
+
resp = HttpResponse.new(io)
|
28
|
+
resp.start do |head,out|
|
29
|
+
head["Accept"] = "text/plain"
|
30
|
+
out.write("tested")
|
31
|
+
out.write("hello!")
|
32
|
+
end
|
33
|
+
|
34
|
+
resp.finished
|
35
|
+
assert io.length > 0, "output didn't have data"
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_response_duplicate_header_squash
|
39
|
+
io = StringIO.new
|
40
|
+
resp = HttpResponse.new(io)
|
41
|
+
resp.start do |head,out|
|
42
|
+
head["Content-Length"] = 30
|
43
|
+
head["Content-Length"] = 0
|
44
|
+
end
|
45
|
+
|
46
|
+
resp.finished
|
47
|
+
|
48
|
+
assert_equal io.length, 95, "too much output"
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def test_response_some_duplicates_allowed
|
53
|
+
allowed_duplicates = ["Set-Cookie", "Set-Cookie2", "Warning", "WWW-Authenticate"]
|
54
|
+
io = StringIO.new
|
55
|
+
resp = HttpResponse.new(io)
|
56
|
+
resp.start do |head,out|
|
57
|
+
allowed_duplicates.each do |dup|
|
58
|
+
10.times do |i|
|
59
|
+
head[dup] = i
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
resp.finished
|
65
|
+
|
66
|
+
assert_equal io.length, 734, "wrong amount of output"
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_response_404
|
70
|
+
io = StringIO.new
|
71
|
+
|
72
|
+
resp = HttpResponse.new(io)
|
73
|
+
resp.start(404) do |head,out|
|
74
|
+
head['Accept'] = "text/plain"
|
75
|
+
out.write("NOT FOUND")
|
76
|
+
end
|
77
|
+
|
78
|
+
resp.finished
|
79
|
+
assert io.length > 0, "output didn't have data"
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_response_file
|
83
|
+
contents = "PLAIN TEXT\r\nCONTENTS\r\n"
|
84
|
+
require 'tempfile'
|
85
|
+
tmpf = Tempfile.new("test_response_file")
|
86
|
+
tmpf.binmode
|
87
|
+
tmpf.write(contents)
|
88
|
+
tmpf.rewind
|
89
|
+
|
90
|
+
io = StringIO.new
|
91
|
+
resp = HttpResponse.new(io)
|
92
|
+
resp.start(200) do |head,out|
|
93
|
+
head['Content-Type'] = 'text/plain'
|
94
|
+
resp.send_header
|
95
|
+
resp.send_file(tmpf.path)
|
96
|
+
end
|
97
|
+
io.rewind
|
98
|
+
tmpf.close
|
99
|
+
|
100
|
+
assert io.length > 0, "output didn't have data"
|
101
|
+
assert io.read[-contents.length..-1] == contents, "output doesn't end with file payload"
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_response_with_custom_reason
|
105
|
+
reason = "You made a bad request"
|
106
|
+
io = StringIO.new
|
107
|
+
resp = HttpResponse.new(io)
|
108
|
+
resp.start(400, false, reason) { |head,out| }
|
109
|
+
resp.finished
|
110
|
+
|
111
|
+
io.rewind
|
112
|
+
assert_match(/.* #{reason}$/, io.readline.chomp, "wrong custom reason phrase")
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_response_with_default_reason
|
116
|
+
code = 400
|
117
|
+
io = StringIO.new
|
118
|
+
resp = HttpResponse.new(io)
|
119
|
+
resp.start(code) { |head,out| }
|
120
|
+
resp.finished
|
121
|
+
|
122
|
+
io.rewind
|
123
|
+
assert_match(/.* #{HTTP_STATUS_CODES[code]}$/, io.readline.chomp, "wrong default reason phrase")
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
data/test/test_stats.rb
ADDED
@@ -0,0 +1,35 @@
|
|
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 StatsTest < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def test_sampling_speed
|
12
|
+
out = StringIO.new
|
13
|
+
|
14
|
+
s = Mongrel::Stats.new("test")
|
15
|
+
t = Mongrel::Stats.new("time")
|
16
|
+
|
17
|
+
100.times { s.sample(rand(20)); t.tick }
|
18
|
+
|
19
|
+
s.dump("FIRST", out)
|
20
|
+
t.dump("FIRST", out)
|
21
|
+
|
22
|
+
old_mean = s.mean
|
23
|
+
old_sd = s.sd
|
24
|
+
|
25
|
+
s.reset
|
26
|
+
t.reset
|
27
|
+
100.times { s.sample(rand(30)); t.tick }
|
28
|
+
|
29
|
+
s.dump("SECOND", out)
|
30
|
+
t.dump("SECOND", out)
|
31
|
+
assert_not_equal old_mean, s.mean
|
32
|
+
assert_not_equal old_mean, s.sd
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|