unicorn 3.3.1 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.wrongdoc.yml +2 -2
- data/GIT-VERSION-GEN +1 -1
- data/KNOWN_ISSUES +17 -7
- data/README +2 -2
- data/Rakefile +3 -2
- data/examples/nginx.conf +12 -8
- data/ext/unicorn_http/unicorn_http.rl +12 -1
- data/ext/unicorn_http/unicorn_http_common.rl +1 -1
- data/lib/unicorn/app/exec_cgi.rb +25 -22
- data/lib/unicorn/configurator.rb +17 -11
- data/lib/unicorn/const.rb +2 -2
- data/lib/unicorn/http_response.rb +1 -1
- data/lib/unicorn/http_server.rb +0 -1
- data/lib/unicorn/socket_helper.rb +33 -19
- data/lib/unicorn/tee_input.rb +1 -1
- data/script/isolate_for_tests +1 -1
- data/t/bin/unused_listen +2 -15
- data/test/exec/test_exec.rb +1 -2
- data/test/rails/test_rails.rb +1 -1
- data/test/test_helper.rb +3 -16
- data/test/unit/test_configurator.rb +8 -0
- data/test/unit/test_http_parser.rb +294 -130
- data/test/unit/test_http_parser_ng.rb +147 -126
- data/test/unit/test_request.rb +3 -3
- data/test/unit/test_response.rb +0 -12
- data/test/unit/test_server.rb +4 -7
- data/test/unit/test_tee_input.rb +25 -21
- data/test/unit/test_upload.rb +10 -2
- data/unicorn.gemspec +2 -2
- metadata +12 -12
data/t/bin/unused_listen
CHANGED
@@ -7,24 +7,11 @@ require 'tmpdir'
|
|
7
7
|
|
8
8
|
default_port = 8080
|
9
9
|
addr = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
|
10
|
-
retries = 100
|
11
|
-
base = 5000
|
12
10
|
port = sock = lock_path = nil
|
13
11
|
|
14
12
|
begin
|
15
|
-
|
16
|
-
|
17
|
-
while port == default_port
|
18
|
-
port = base + rand(32768 - base)
|
19
|
-
end
|
20
|
-
|
21
|
-
sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
22
|
-
sock.bind(Socket.pack_sockaddr_in(port, addr))
|
23
|
-
sock.listen(5)
|
24
|
-
rescue Errno::EADDRINUSE, Errno::EACCES
|
25
|
-
sock.close rescue nil
|
26
|
-
retry if (retries -= 1) >= 0
|
27
|
-
end
|
13
|
+
sock = TCPServer.new(addr, 0)
|
14
|
+
port = sock.addr[1]
|
28
15
|
|
29
16
|
# since we'll end up closing the random port we just got, there's a race
|
30
17
|
# condition could allow the random port we just chose to reselect itself
|
data/test/exec/test_exec.rb
CHANGED
@@ -797,7 +797,6 @@ EOF
|
|
797
797
|
|
798
798
|
def test_daemonize_redirect_fail
|
799
799
|
pid_file = "#{@tmpdir}/test.pid"
|
800
|
-
log = Tempfile.new('unicorn_test_log')
|
801
800
|
ucfg = Tempfile.new('unicorn_test_config')
|
802
801
|
ucfg.syswrite("pid #{pid_file}\"\n")
|
803
802
|
err = Tempfile.new('stderr')
|
@@ -1040,7 +1039,7 @@ EOF
|
|
1040
1039
|
lock_path = "#{Dir::tmpdir}/unicorn_test." \
|
1041
1040
|
"#{Unicorn::Const::DEFAULT_LISTEN}.lock"
|
1042
1041
|
begin
|
1043
|
-
|
1042
|
+
File.open(lock_path, File::WRONLY|File::CREAT|File::EXCL, 0600)
|
1044
1043
|
yield
|
1045
1044
|
rescue Errno::EEXIST
|
1046
1045
|
lock_path = nil
|
data/test/rails/test_rails.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -100,30 +100,17 @@ end
|
|
100
100
|
# for a race condition is very small). You may also set UNICORN_TEST_ADDR
|
101
101
|
# to override the default test address (127.0.0.1).
|
102
102
|
def unused_port(addr = '127.0.0.1')
|
103
|
-
retries = 100
|
104
|
-
base = 5000
|
105
103
|
port = sock = nil
|
106
104
|
begin
|
107
|
-
|
108
|
-
|
109
|
-
while port == Unicorn::Const::DEFAULT_PORT
|
110
|
-
port = base + rand(32768 - base)
|
111
|
-
end
|
112
|
-
|
113
|
-
sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
114
|
-
sock.bind(Socket.pack_sockaddr_in(port, addr))
|
115
|
-
sock.listen(5)
|
116
|
-
rescue Errno::EADDRINUSE, Errno::EACCES
|
117
|
-
sock.close rescue nil
|
118
|
-
retry if (retries -= 1) >= 0
|
119
|
-
end
|
105
|
+
sock = TCPServer.new(addr, 0)
|
106
|
+
port = sock.addr[1]
|
120
107
|
|
121
108
|
# since we'll end up closing the random port we just got, there's a race
|
122
109
|
# condition could allow the random port we just chose to reselect itself
|
123
110
|
# when running tests in parallel with gmake. Create a lock file while
|
124
111
|
# we have the port here to ensure that does not happen .
|
125
112
|
lock_path = "#{Dir::tmpdir}/unicorn_test.#{addr}:#{port}.lock"
|
126
|
-
|
113
|
+
File.open(lock_path, File::WRONLY|File::CREAT|File::EXCL, 0600)
|
127
114
|
at_exit { File.unlink(lock_path) rescue nil }
|
128
115
|
rescue Errno::EEXIST
|
129
116
|
sock.close rescue nil
|
@@ -33,6 +33,14 @@ class TestConfigurator < Test::Unit::TestCase
|
|
33
33
|
assert_equal "0.0.0.0:2007", meth.call('2007')
|
34
34
|
assert_equal "0.0.0.0:2007", meth.call(2007)
|
35
35
|
|
36
|
+
%w([::1]:2007 [::]:2007).each do |addr|
|
37
|
+
assert_equal addr, meth.call(addr.dup)
|
38
|
+
end
|
39
|
+
|
40
|
+
# for Rainbows! users only
|
41
|
+
assert_equal "[::]:80", meth.call("[::]")
|
42
|
+
assert_equal "127.6.6.6:80", meth.call("127.6.6.6")
|
43
|
+
|
36
44
|
# the next two aren't portable, consider them unsupported for now
|
37
45
|
# assert_match %r{\A\d+\.\d+\.\d+\.\d+:2007\z}, meth.call('1:2007')
|
38
46
|
# assert_match %r{\A\d+\.\d+\.\d+\.\d+:2007\z}, meth.call('2:2007')
|
@@ -14,9 +14,10 @@ class HttpParserTest < Test::Unit::TestCase
|
|
14
14
|
|
15
15
|
def test_parse_simple
|
16
16
|
parser = HttpParser.new
|
17
|
-
req =
|
18
|
-
http =
|
19
|
-
|
17
|
+
req = parser.env
|
18
|
+
http = parser.buf
|
19
|
+
http << "GET / HTTP/1.1\r\n\r\n"
|
20
|
+
assert_equal req, parser.parse
|
20
21
|
assert_equal '', http
|
21
22
|
|
22
23
|
assert_equal 'HTTP/1.1', req['SERVER_PROTOCOL']
|
@@ -31,14 +32,14 @@ class HttpParserTest < Test::Unit::TestCase
|
|
31
32
|
parser.clear
|
32
33
|
req.clear
|
33
34
|
|
34
|
-
http
|
35
|
-
assert_nil parser.
|
35
|
+
http << "G"
|
36
|
+
assert_nil parser.parse
|
36
37
|
assert_equal "G", http
|
37
38
|
assert req.empty?
|
38
39
|
|
39
40
|
# try parsing again to ensure we were reset correctly
|
40
|
-
http
|
41
|
-
assert parser.
|
41
|
+
http << "ET /hello-world HTTP/1.1\r\n\r\n"
|
42
|
+
assert parser.parse
|
42
43
|
|
43
44
|
assert_equal 'HTTP/1.1', req['SERVER_PROTOCOL']
|
44
45
|
assert_equal '/hello-world', req['REQUEST_PATH']
|
@@ -53,161 +54,161 @@ class HttpParserTest < Test::Unit::TestCase
|
|
53
54
|
|
54
55
|
def test_tab_lws
|
55
56
|
parser = HttpParser.new
|
56
|
-
req =
|
57
|
-
|
58
|
-
assert_equal req.object_id, parser.
|
57
|
+
req = parser.env
|
58
|
+
parser.buf << "GET / HTTP/1.1\r\nHost:\tfoo.bar\r\n\r\n"
|
59
|
+
assert_equal req.object_id, parser.parse.object_id
|
59
60
|
assert_equal "foo.bar", req['HTTP_HOST']
|
60
61
|
end
|
61
62
|
|
62
63
|
def test_connection_close_no_ka
|
63
64
|
parser = HttpParser.new
|
64
|
-
req =
|
65
|
-
|
66
|
-
assert_equal req.object_id, parser.
|
65
|
+
req = parser.env
|
66
|
+
parser.buf << "GET / HTTP/1.1\r\nConnection: close\r\n\r\n"
|
67
|
+
assert_equal req.object_id, parser.parse.object_id
|
67
68
|
assert_equal "GET", req['REQUEST_METHOD']
|
68
69
|
assert ! parser.keepalive?
|
69
70
|
end
|
70
71
|
|
71
72
|
def test_connection_keep_alive_ka
|
72
73
|
parser = HttpParser.new
|
73
|
-
req =
|
74
|
-
|
75
|
-
assert_equal req.object_id, parser.
|
74
|
+
req = parser.env
|
75
|
+
parser.buf << "HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n"
|
76
|
+
assert_equal req.object_id, parser.parse.object_id
|
76
77
|
assert parser.keepalive?
|
77
78
|
end
|
78
79
|
|
79
80
|
def test_connection_keep_alive_no_body
|
80
81
|
parser = HttpParser.new
|
81
|
-
req =
|
82
|
-
|
83
|
-
assert_equal req.object_id, parser.
|
82
|
+
req = parser.env
|
83
|
+
parser.buf << "POST / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n"
|
84
|
+
assert_equal req.object_id, parser.parse.object_id
|
84
85
|
assert parser.keepalive?
|
85
86
|
end
|
86
87
|
|
87
88
|
def test_connection_keep_alive_no_body_empty
|
88
89
|
parser = HttpParser.new
|
89
|
-
req =
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
assert_equal req.object_id, parser.
|
90
|
+
req = parser.env
|
91
|
+
parser.buf << "POST / HTTP/1.1\r\n" \
|
92
|
+
"Content-Length: 0\r\n" \
|
93
|
+
"Connection: keep-alive\r\n\r\n"
|
94
|
+
assert_equal req.object_id, parser.parse.object_id
|
94
95
|
assert parser.keepalive?
|
95
96
|
end
|
96
97
|
|
97
98
|
def test_connection_keep_alive_ka_bad_version
|
98
99
|
parser = HttpParser.new
|
99
|
-
req =
|
100
|
-
|
101
|
-
assert_equal req.object_id, parser.
|
100
|
+
req = parser.env
|
101
|
+
parser.buf << "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n"
|
102
|
+
assert_equal req.object_id, parser.parse.object_id
|
102
103
|
assert parser.keepalive?
|
103
104
|
end
|
104
105
|
|
105
106
|
def test_parse_server_host_default_port
|
106
107
|
parser = HttpParser.new
|
107
|
-
req =
|
108
|
-
|
109
|
-
assert_equal req, parser.
|
108
|
+
req = parser.env
|
109
|
+
parser.buf << "GET / HTTP/1.1\r\nHost: foo\r\n\r\n"
|
110
|
+
assert_equal req, parser.parse
|
110
111
|
assert_equal 'foo', req['SERVER_NAME']
|
111
112
|
assert_equal '80', req['SERVER_PORT']
|
112
|
-
assert_equal '',
|
113
|
+
assert_equal '', parser.buf
|
113
114
|
assert parser.keepalive?
|
114
115
|
end
|
115
116
|
|
116
117
|
def test_parse_server_host_alt_port
|
117
118
|
parser = HttpParser.new
|
118
|
-
req =
|
119
|
-
|
120
|
-
assert_equal req, parser.
|
119
|
+
req = parser.env
|
120
|
+
parser.buf << "GET / HTTP/1.1\r\nHost: foo:999\r\n\r\n"
|
121
|
+
assert_equal req, parser.parse
|
121
122
|
assert_equal 'foo', req['SERVER_NAME']
|
122
123
|
assert_equal '999', req['SERVER_PORT']
|
123
|
-
assert_equal '',
|
124
|
+
assert_equal '', parser.buf
|
124
125
|
assert parser.keepalive?
|
125
126
|
end
|
126
127
|
|
127
128
|
def test_parse_server_host_empty_port
|
128
129
|
parser = HttpParser.new
|
129
|
-
req =
|
130
|
-
|
131
|
-
assert_equal req, parser.
|
130
|
+
req = parser.env
|
131
|
+
parser.buf << "GET / HTTP/1.1\r\nHost: foo:\r\n\r\n"
|
132
|
+
assert_equal req, parser.parse
|
132
133
|
assert_equal 'foo', req['SERVER_NAME']
|
133
134
|
assert_equal '80', req['SERVER_PORT']
|
134
|
-
assert_equal '',
|
135
|
+
assert_equal '', parser.buf
|
135
136
|
assert parser.keepalive?
|
136
137
|
end
|
137
138
|
|
138
139
|
def test_parse_server_host_xfp_https
|
139
140
|
parser = HttpParser.new
|
140
|
-
req =
|
141
|
-
|
142
|
-
|
143
|
-
assert_equal req, parser.
|
141
|
+
req = parser.env
|
142
|
+
parser.buf << "GET / HTTP/1.1\r\nHost: foo:\r\n" \
|
143
|
+
"X-Forwarded-Proto: https\r\n\r\n"
|
144
|
+
assert_equal req, parser.parse
|
144
145
|
assert_equal 'foo', req['SERVER_NAME']
|
145
146
|
assert_equal '443', req['SERVER_PORT']
|
146
|
-
assert_equal '',
|
147
|
+
assert_equal '', parser.buf
|
147
148
|
assert parser.keepalive?
|
148
149
|
end
|
149
150
|
|
150
151
|
def test_parse_xfp_https_chained
|
151
152
|
parser = HttpParser.new
|
152
|
-
req =
|
153
|
-
|
154
|
-
|
155
|
-
assert_equal req, parser.
|
153
|
+
req = parser.env
|
154
|
+
parser.buf << "GET / HTTP/1.0\r\n" \
|
155
|
+
"X-Forwarded-Proto: https,http\r\n\r\n"
|
156
|
+
assert_equal req, parser.parse
|
156
157
|
assert_equal '443', req['SERVER_PORT'], req.inspect
|
157
158
|
assert_equal 'https', req['rack.url_scheme'], req.inspect
|
158
|
-
assert_equal '',
|
159
|
+
assert_equal '', parser.buf
|
159
160
|
end
|
160
161
|
|
161
162
|
def test_parse_xfp_https_chained_backwards
|
162
163
|
parser = HttpParser.new
|
163
|
-
req =
|
164
|
-
|
164
|
+
req = parser.env
|
165
|
+
parser.buf << "GET / HTTP/1.0\r\n" \
|
165
166
|
"X-Forwarded-Proto: http,https\r\n\r\n"
|
166
|
-
assert_equal req, parser.
|
167
|
+
assert_equal req, parser.parse
|
167
168
|
assert_equal '80', req['SERVER_PORT'], req.inspect
|
168
169
|
assert_equal 'http', req['rack.url_scheme'], req.inspect
|
169
|
-
assert_equal '',
|
170
|
+
assert_equal '', parser.buf
|
170
171
|
end
|
171
172
|
|
172
173
|
def test_parse_xfp_gopher_is_ignored
|
173
174
|
parser = HttpParser.new
|
174
|
-
req =
|
175
|
-
|
176
|
-
|
177
|
-
assert_equal req, parser.
|
175
|
+
req = parser.env
|
176
|
+
parser.buf << "GET / HTTP/1.0\r\n" \
|
177
|
+
"X-Forwarded-Proto: gopher\r\n\r\n"
|
178
|
+
assert_equal req, parser.parse
|
178
179
|
assert_equal '80', req['SERVER_PORT'], req.inspect
|
179
180
|
assert_equal 'http', req['rack.url_scheme'], req.inspect
|
180
|
-
assert_equal '',
|
181
|
+
assert_equal '', parser.buf
|
181
182
|
end
|
182
183
|
|
183
184
|
def test_parse_x_forwarded_ssl_on
|
184
185
|
parser = HttpParser.new
|
185
|
-
req =
|
186
|
-
|
187
|
-
|
188
|
-
assert_equal req, parser.
|
186
|
+
req = parser.env
|
187
|
+
parser.buf << "GET / HTTP/1.0\r\n" \
|
188
|
+
"X-Forwarded-Ssl: on\r\n\r\n"
|
189
|
+
assert_equal req, parser.parse
|
189
190
|
assert_equal '443', req['SERVER_PORT'], req.inspect
|
190
191
|
assert_equal 'https', req['rack.url_scheme'], req.inspect
|
191
|
-
assert_equal '',
|
192
|
+
assert_equal '', parser.buf
|
192
193
|
end
|
193
194
|
|
194
195
|
def test_parse_x_forwarded_ssl_off
|
195
196
|
parser = HttpParser.new
|
196
|
-
req =
|
197
|
-
|
198
|
-
|
199
|
-
assert_equal req, parser.headers(req, tmp)
|
197
|
+
req = parser.env
|
198
|
+
parser.buf << "GET / HTTP/1.0\r\nX-Forwarded-Ssl: off\r\n\r\n"
|
199
|
+
assert_equal req, parser.parse
|
200
200
|
assert_equal '80', req['SERVER_PORT'], req.inspect
|
201
201
|
assert_equal 'http', req['rack.url_scheme'], req.inspect
|
202
|
-
assert_equal '',
|
202
|
+
assert_equal '', parser.buf
|
203
203
|
end
|
204
204
|
|
205
205
|
def test_parse_strange_headers
|
206
206
|
parser = HttpParser.new
|
207
|
-
req =
|
207
|
+
req = parser.env
|
208
208
|
should_be_good = "GET / HTTP/1.1\r\naaaaaaaaaaaaa:++++++++++\r\n\r\n"
|
209
|
-
|
210
|
-
assert_equal
|
209
|
+
parser.buf << should_be_good
|
210
|
+
assert_equal req, parser.parse
|
211
|
+
assert_equal '', parser.buf
|
211
212
|
assert parser.keepalive?
|
212
213
|
end
|
213
214
|
|
@@ -217,14 +218,14 @@ class HttpParserTest < Test::Unit::TestCase
|
|
217
218
|
def test_nasty_pound_header
|
218
219
|
parser = HttpParser.new
|
219
220
|
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"
|
220
|
-
req =
|
221
|
-
buf
|
221
|
+
req = parser.env
|
222
|
+
parser.buf << nasty_pound_header.dup
|
222
223
|
|
223
224
|
assert nasty_pound_header =~ /(-----BEGIN .*--END CERTIFICATE-----)/m
|
224
225
|
expect = $1.dup
|
225
226
|
expect.gsub!(/\r\n\t/, ' ')
|
226
|
-
assert_equal req, parser.
|
227
|
-
assert_equal '', buf
|
227
|
+
assert_equal req, parser.parse
|
228
|
+
assert_equal '', parser.buf
|
228
229
|
assert_equal expect, req['HTTP_X_SSL_BULLSHIT']
|
229
230
|
end
|
230
231
|
|
@@ -235,9 +236,10 @@ class HttpParserTest < Test::Unit::TestCase
|
|
235
236
|
"\t\r\n" \
|
236
237
|
" \r\n" \
|
237
238
|
" ASDF\r\n\r\n"
|
238
|
-
|
239
|
-
|
240
|
-
assert_equal
|
239
|
+
parser.buf << header
|
240
|
+
req = parser.env
|
241
|
+
assert_equal req, parser.parse
|
242
|
+
assert_equal '', parser.buf
|
241
243
|
assert_equal 'ASDF', req['HTTP_X_ASDF']
|
242
244
|
end
|
243
245
|
|
@@ -249,9 +251,10 @@ class HttpParserTest < Test::Unit::TestCase
|
|
249
251
|
"\t\r\n" \
|
250
252
|
" x\r\n" \
|
251
253
|
" ASDF\r\n\r\n"
|
252
|
-
req =
|
253
|
-
|
254
|
-
assert_equal
|
254
|
+
req = parser.env
|
255
|
+
parser.buf << header
|
256
|
+
assert_equal req, parser.parse
|
257
|
+
assert_equal '', parser.buf
|
255
258
|
assert_equal 'hi y x ASDF', req['HTTP_X_ASDF']
|
256
259
|
end
|
257
260
|
|
@@ -261,8 +264,9 @@ class HttpParserTest < Test::Unit::TestCase
|
|
261
264
|
"Host: \r\n" \
|
262
265
|
" YHBT.net\r\n" \
|
263
266
|
"\r\n"
|
264
|
-
|
265
|
-
|
267
|
+
parser.buf << header
|
268
|
+
req = parser.env
|
269
|
+
assert_equal req, parser.parse
|
266
270
|
assert_equal 'example.com', req['HTTP_HOST']
|
267
271
|
end
|
268
272
|
|
@@ -271,21 +275,22 @@ class HttpParserTest < Test::Unit::TestCase
|
|
271
275
|
# in case we ever go multithreaded/evented...
|
272
276
|
def test_resumable_continuations
|
273
277
|
nr = 1000
|
274
|
-
req = {}
|
275
278
|
header = "GET / HTTP/1.1\r\n" \
|
276
279
|
"X-ASDF: \r\n" \
|
277
280
|
" hello\r\n"
|
278
281
|
tmp = []
|
279
282
|
nr.times { |i|
|
280
283
|
parser = HttpParser.new
|
281
|
-
|
284
|
+
req = parser.env
|
285
|
+
parser.buf << "#{header} #{i}\r\n"
|
286
|
+
assert parser.parse.nil?
|
282
287
|
asdf = req['HTTP_X_ASDF']
|
283
288
|
assert_equal "hello #{i}", asdf
|
284
289
|
tmp << [ parser, asdf ]
|
285
|
-
req.clear
|
286
290
|
}
|
287
291
|
tmp.each_with_index { |(parser, asdf), i|
|
288
|
-
|
292
|
+
parser.buf << " .\r\n\r\n"
|
293
|
+
assert parser.parse
|
289
294
|
assert_equal "hello #{i} .", asdf
|
290
295
|
}
|
291
296
|
end
|
@@ -296,8 +301,9 @@ class HttpParserTest < Test::Unit::TestCase
|
|
296
301
|
" y\r\n" \
|
297
302
|
"Host: hello\r\n" \
|
298
303
|
"\r\n"
|
299
|
-
|
300
|
-
|
304
|
+
parser.buf << header
|
305
|
+
req = parser.env
|
306
|
+
assert_raises(HttpParserError) { parser.parse }
|
301
307
|
end
|
302
308
|
|
303
309
|
def test_parse_ie6_urls
|
@@ -309,7 +315,7 @@ class HttpParserTest < Test::Unit::TestCase
|
|
309
315
|
/mal"formed"?
|
310
316
|
).each do |path|
|
311
317
|
parser = HttpParser.new
|
312
|
-
req =
|
318
|
+
req = parser.env
|
313
319
|
sorta_safe = %(GET #{path} HTTP/1.1\r\n\r\n)
|
314
320
|
assert_equal req, parser.headers(req, sorta_safe)
|
315
321
|
assert_equal path, req['REQUEST_URI']
|
@@ -320,7 +326,7 @@ class HttpParserTest < Test::Unit::TestCase
|
|
320
326
|
|
321
327
|
def test_parse_error
|
322
328
|
parser = HttpParser.new
|
323
|
-
req =
|
329
|
+
req = parser.env
|
324
330
|
bad_http = "GET / SsUTF/1.1"
|
325
331
|
|
326
332
|
assert_raises(HttpParserError) { parser.headers(req, bad_http) }
|
@@ -334,7 +340,7 @@ class HttpParserTest < Test::Unit::TestCase
|
|
334
340
|
|
335
341
|
def test_piecemeal
|
336
342
|
parser = HttpParser.new
|
337
|
-
req =
|
343
|
+
req = parser.env
|
338
344
|
http = "GET"
|
339
345
|
assert_nil parser.headers(req, http)
|
340
346
|
assert_nil parser.headers(req, http)
|
@@ -356,9 +362,10 @@ class HttpParserTest < Test::Unit::TestCase
|
|
356
362
|
# not common, but underscores do appear in practice
|
357
363
|
def test_absolute_uri_underscores
|
358
364
|
parser = HttpParser.new
|
359
|
-
req =
|
365
|
+
req = parser.env
|
360
366
|
http = "GET http://under_score.example.com/foo?q=bar HTTP/1.0\r\n\r\n"
|
361
|
-
|
367
|
+
parser.buf << http
|
368
|
+
assert_equal req, parser.parse
|
362
369
|
assert_equal 'http', req['rack.url_scheme']
|
363
370
|
assert_equal '/foo?q=bar', req['REQUEST_URI']
|
364
371
|
assert_equal '/foo', req['REQUEST_PATH']
|
@@ -367,16 +374,17 @@ class HttpParserTest < Test::Unit::TestCase
|
|
367
374
|
assert_equal 'under_score.example.com', req['HTTP_HOST']
|
368
375
|
assert_equal 'under_score.example.com', req['SERVER_NAME']
|
369
376
|
assert_equal '80', req['SERVER_PORT']
|
370
|
-
assert_equal "",
|
377
|
+
assert_equal "", parser.buf
|
371
378
|
assert ! parser.keepalive?
|
372
379
|
end
|
373
380
|
|
374
381
|
# some dumb clients add users because they're stupid
|
375
382
|
def test_absolute_uri_w_user
|
376
383
|
parser = HttpParser.new
|
377
|
-
req =
|
384
|
+
req = parser.env
|
378
385
|
http = "GET http://user%20space@example.com/foo?q=bar HTTP/1.0\r\n\r\n"
|
379
|
-
|
386
|
+
parser.buf << http
|
387
|
+
assert_equal req, parser.parse
|
380
388
|
assert_equal 'http', req['rack.url_scheme']
|
381
389
|
assert_equal '/foo?q=bar', req['REQUEST_URI']
|
382
390
|
assert_equal '/foo', req['REQUEST_PATH']
|
@@ -385,7 +393,7 @@ class HttpParserTest < Test::Unit::TestCase
|
|
385
393
|
assert_equal 'example.com', req['HTTP_HOST']
|
386
394
|
assert_equal 'example.com', req['SERVER_NAME']
|
387
395
|
assert_equal '80', req['SERVER_PORT']
|
388
|
-
assert_equal "",
|
396
|
+
assert_equal "", parser.buf
|
389
397
|
assert ! parser.keepalive?
|
390
398
|
end
|
391
399
|
|
@@ -394,7 +402,7 @@ class HttpParserTest < Test::Unit::TestCase
|
|
394
402
|
def test_absolute_uri_uri_parse
|
395
403
|
"#{URI::REGEXP::PATTERN::UNRESERVED};:&=+$,".split(//).each do |char|
|
396
404
|
parser = HttpParser.new
|
397
|
-
req =
|
405
|
+
req = parser.env
|
398
406
|
http = "GET http://#{char}@example.com/ HTTP/1.0\r\n\r\n"
|
399
407
|
assert_equal req, parser.headers(req, http)
|
400
408
|
assert_equal 'http', req['rack.url_scheme']
|
@@ -412,9 +420,9 @@ class HttpParserTest < Test::Unit::TestCase
|
|
412
420
|
|
413
421
|
def test_absolute_uri
|
414
422
|
parser = HttpParser.new
|
415
|
-
req =
|
416
|
-
|
417
|
-
assert_equal req, parser.
|
423
|
+
req = parser.env
|
424
|
+
parser.buf << "GET http://example.com/foo?q=bar HTTP/1.0\r\n\r\n"
|
425
|
+
assert_equal req, parser.parse
|
418
426
|
assert_equal 'http', req['rack.url_scheme']
|
419
427
|
assert_equal '/foo?q=bar', req['REQUEST_URI']
|
420
428
|
assert_equal '/foo', req['REQUEST_PATH']
|
@@ -423,17 +431,18 @@ class HttpParserTest < Test::Unit::TestCase
|
|
423
431
|
assert_equal 'example.com', req['HTTP_HOST']
|
424
432
|
assert_equal 'example.com', req['SERVER_NAME']
|
425
433
|
assert_equal '80', req['SERVER_PORT']
|
426
|
-
assert_equal "",
|
434
|
+
assert_equal "", parser.buf
|
427
435
|
assert ! parser.keepalive?
|
428
436
|
end
|
429
437
|
|
430
438
|
# X-Forwarded-Proto is not in rfc2616, absolute URIs are, however...
|
431
439
|
def test_absolute_uri_https
|
432
440
|
parser = HttpParser.new
|
433
|
-
req =
|
441
|
+
req = parser.env
|
434
442
|
http = "GET https://example.com/foo?q=bar HTTP/1.1\r\n" \
|
435
443
|
"X-Forwarded-Proto: http\r\n\r\n"
|
436
|
-
|
444
|
+
parser.buf << http
|
445
|
+
assert_equal req, parser.parse
|
437
446
|
assert_equal 'https', req['rack.url_scheme']
|
438
447
|
assert_equal '/foo?q=bar', req['REQUEST_URI']
|
439
448
|
assert_equal '/foo', req['REQUEST_PATH']
|
@@ -442,17 +451,17 @@ class HttpParserTest < Test::Unit::TestCase
|
|
442
451
|
assert_equal 'example.com', req['HTTP_HOST']
|
443
452
|
assert_equal 'example.com', req['SERVER_NAME']
|
444
453
|
assert_equal '443', req['SERVER_PORT']
|
445
|
-
assert_equal "",
|
454
|
+
assert_equal "", parser.buf
|
446
455
|
assert parser.keepalive?
|
447
456
|
end
|
448
457
|
|
449
458
|
# Host: header should be ignored for absolute URIs
|
450
459
|
def test_absolute_uri_with_port
|
451
460
|
parser = HttpParser.new
|
452
|
-
req =
|
453
|
-
|
461
|
+
req = parser.env
|
462
|
+
parser.buf << "GET http://example.com:8080/foo?q=bar HTTP/1.2\r\n" \
|
454
463
|
"Host: bad.example.com\r\n\r\n"
|
455
|
-
assert_equal req, parser.
|
464
|
+
assert_equal req, parser.parse
|
456
465
|
assert_equal 'http', req['rack.url_scheme']
|
457
466
|
assert_equal '/foo?q=bar', req['REQUEST_URI']
|
458
467
|
assert_equal '/foo', req['REQUEST_PATH']
|
@@ -461,16 +470,16 @@ class HttpParserTest < Test::Unit::TestCase
|
|
461
470
|
assert_equal 'example.com:8080', req['HTTP_HOST']
|
462
471
|
assert_equal 'example.com', req['SERVER_NAME']
|
463
472
|
assert_equal '8080', req['SERVER_PORT']
|
464
|
-
assert_equal "",
|
473
|
+
assert_equal "", parser.buf
|
465
474
|
assert ! parser.keepalive? # TODO: read HTTP/1.2 when it's final
|
466
475
|
end
|
467
476
|
|
468
477
|
def test_absolute_uri_with_empty_port
|
469
478
|
parser = HttpParser.new
|
470
|
-
req =
|
471
|
-
|
479
|
+
req = parser.env
|
480
|
+
parser.buf << "GET https://example.com:/foo?q=bar HTTP/1.1\r\n" \
|
472
481
|
"Host: bad.example.com\r\n\r\n"
|
473
|
-
assert_equal req, parser.
|
482
|
+
assert_equal req, parser.parse
|
474
483
|
assert_equal 'https', req['rack.url_scheme']
|
475
484
|
assert_equal '/foo?q=bar', req['REQUEST_URI']
|
476
485
|
assert_equal '/foo', req['REQUEST_PATH']
|
@@ -479,42 +488,192 @@ class HttpParserTest < Test::Unit::TestCase
|
|
479
488
|
assert_equal 'example.com:', req['HTTP_HOST']
|
480
489
|
assert_equal 'example.com', req['SERVER_NAME']
|
481
490
|
assert_equal '443', req['SERVER_PORT']
|
491
|
+
assert_equal "", parser.buf
|
492
|
+
assert parser.keepalive? # TODO: read HTTP/1.2 when it's final
|
493
|
+
end
|
494
|
+
|
495
|
+
def test_absolute_ipv6_uri
|
496
|
+
parser = HttpParser.new
|
497
|
+
req = parser.env
|
498
|
+
url = "http://[::1]/foo?q=bar"
|
499
|
+
http = "GET #{url} HTTP/1.1\r\n" \
|
500
|
+
"Host: bad.example.com\r\n\r\n"
|
501
|
+
assert_equal req, parser.headers(req, http)
|
502
|
+
assert_equal 'http', req['rack.url_scheme']
|
503
|
+
assert_equal '/foo?q=bar', req['REQUEST_URI']
|
504
|
+
assert_equal '/foo', req['REQUEST_PATH']
|
505
|
+
assert_equal 'q=bar', req['QUERY_STRING']
|
506
|
+
|
507
|
+
uri = URI.parse(url)
|
508
|
+
assert_equal "[::1]", uri.host,
|
509
|
+
"URI.parse changed upstream for #{url}? host=#{uri.host}"
|
510
|
+
assert_equal "[::1]", req['HTTP_HOST']
|
511
|
+
assert_equal "[::1]", req['SERVER_NAME']
|
512
|
+
assert_equal '80', req['SERVER_PORT']
|
482
513
|
assert_equal "", http
|
483
514
|
assert parser.keepalive? # TODO: read HTTP/1.2 when it's final
|
484
515
|
end
|
485
516
|
|
486
|
-
def
|
517
|
+
def test_absolute_ipv6_uri_alpha
|
518
|
+
parser = HttpParser.new
|
519
|
+
req = parser.env
|
520
|
+
url = "http://[::a]/"
|
521
|
+
http = "GET #{url} HTTP/1.1\r\n" \
|
522
|
+
"Host: bad.example.com\r\n\r\n"
|
523
|
+
assert_equal req, parser.headers(req, http)
|
524
|
+
assert_equal 'http', req['rack.url_scheme']
|
525
|
+
|
526
|
+
uri = URI.parse(url)
|
527
|
+
assert_equal "[::a]", uri.host,
|
528
|
+
"URI.parse changed upstream for #{url}? host=#{uri.host}"
|
529
|
+
assert_equal "[::a]", req['HTTP_HOST']
|
530
|
+
assert_equal "[::a]", req['SERVER_NAME']
|
531
|
+
assert_equal '80', req['SERVER_PORT']
|
532
|
+
end
|
533
|
+
|
534
|
+
def test_absolute_ipv6_uri_alpha_2
|
487
535
|
parser = HttpParser.new
|
488
|
-
req =
|
489
|
-
|
536
|
+
req = parser.env
|
537
|
+
url = "http://[::B]/"
|
538
|
+
http = "GET #{url} HTTP/1.1\r\n" \
|
539
|
+
"Host: bad.example.com\r\n\r\n"
|
490
540
|
assert_equal req, parser.headers(req, http)
|
541
|
+
assert_equal 'http', req['rack.url_scheme']
|
542
|
+
|
543
|
+
uri = URI.parse(url)
|
544
|
+
assert_equal "[::B]", uri.host,
|
545
|
+
"URI.parse changed upstream for #{url}? host=#{uri.host}"
|
546
|
+
assert_equal "[::B]", req['HTTP_HOST']
|
547
|
+
assert_equal "[::B]", req['SERVER_NAME']
|
548
|
+
assert_equal '80', req['SERVER_PORT']
|
549
|
+
end
|
550
|
+
|
551
|
+
def test_absolute_ipv6_uri_with_empty_port
|
552
|
+
parser = HttpParser.new
|
553
|
+
req = parser.env
|
554
|
+
url = "https://[::1]:/foo?q=bar"
|
555
|
+
http = "GET #{url} HTTP/1.1\r\n" \
|
556
|
+
"Host: bad.example.com\r\n\r\n"
|
557
|
+
assert_equal req, parser.headers(req, http)
|
558
|
+
assert_equal 'https', req['rack.url_scheme']
|
559
|
+
assert_equal '/foo?q=bar', req['REQUEST_URI']
|
560
|
+
assert_equal '/foo', req['REQUEST_PATH']
|
561
|
+
assert_equal 'q=bar', req['QUERY_STRING']
|
562
|
+
|
563
|
+
uri = URI.parse(url)
|
564
|
+
assert_equal "[::1]", uri.host,
|
565
|
+
"URI.parse changed upstream for #{url}? host=#{uri.host}"
|
566
|
+
assert_equal "[::1]:", req['HTTP_HOST']
|
567
|
+
assert_equal "[::1]", req['SERVER_NAME']
|
568
|
+
assert_equal '443', req['SERVER_PORT']
|
569
|
+
assert_equal "", http
|
570
|
+
assert parser.keepalive? # TODO: read HTTP/1.2 when it's final
|
571
|
+
end
|
572
|
+
|
573
|
+
def test_absolute_ipv6_uri_with_port
|
574
|
+
parser = HttpParser.new
|
575
|
+
req = parser.env
|
576
|
+
url = "https://[::1]:666/foo?q=bar"
|
577
|
+
http = "GET #{url} HTTP/1.1\r\n" \
|
578
|
+
"Host: bad.example.com\r\n\r\n"
|
579
|
+
assert_equal req, parser.headers(req, http)
|
580
|
+
assert_equal 'https', req['rack.url_scheme']
|
581
|
+
assert_equal '/foo?q=bar', req['REQUEST_URI']
|
582
|
+
assert_equal '/foo', req['REQUEST_PATH']
|
583
|
+
assert_equal 'q=bar', req['QUERY_STRING']
|
584
|
+
|
585
|
+
uri = URI.parse(url)
|
586
|
+
assert_equal "[::1]", uri.host,
|
587
|
+
"URI.parse changed upstream for #{url}? host=#{uri.host}"
|
588
|
+
assert_equal "[::1]:666", req['HTTP_HOST']
|
589
|
+
assert_equal "[::1]", req['SERVER_NAME']
|
590
|
+
assert_equal '666', req['SERVER_PORT']
|
591
|
+
assert_equal "", http
|
592
|
+
assert parser.keepalive? # TODO: read HTTP/1.2 when it's final
|
593
|
+
end
|
594
|
+
|
595
|
+
def test_ipv6_host_header
|
596
|
+
parser = HttpParser.new
|
597
|
+
req = parser.env
|
598
|
+
parser.buf << "GET / HTTP/1.1\r\n" \
|
599
|
+
"Host: [::1]\r\n\r\n"
|
600
|
+
assert_equal req, parser.parse
|
601
|
+
assert_equal "[::1]", req['HTTP_HOST']
|
602
|
+
assert_equal "[::1]", req['SERVER_NAME']
|
603
|
+
assert_equal '80', req['SERVER_PORT']
|
604
|
+
assert_equal "", parser.buf
|
605
|
+
assert parser.keepalive? # TODO: read HTTP/1.2 when it's final
|
606
|
+
end
|
607
|
+
|
608
|
+
def test_ipv6_host_header_with_port
|
609
|
+
parser = HttpParser.new
|
610
|
+
req = parser.env
|
611
|
+
parser.buf << "GET / HTTP/1.1\r\n" \
|
612
|
+
"Host: [::1]:666\r\n\r\n"
|
613
|
+
assert_equal req, parser.parse
|
614
|
+
assert_equal "[::1]", req['SERVER_NAME']
|
615
|
+
assert_equal '666', req['SERVER_PORT']
|
616
|
+
assert_equal "[::1]:666", req['HTTP_HOST']
|
617
|
+
assert_equal "", parser.buf
|
618
|
+
assert parser.keepalive? # TODO: read HTTP/1.2 when it's final
|
619
|
+
end
|
620
|
+
|
621
|
+
def test_ipv6_host_header_with_empty_port
|
622
|
+
parser = HttpParser.new
|
623
|
+
req = parser.env
|
624
|
+
parser.buf << "GET / HTTP/1.1\r\nHost: [::1]:\r\n\r\n"
|
625
|
+
assert_equal req, parser.parse
|
626
|
+
assert_equal "[::1]", req['SERVER_NAME']
|
627
|
+
assert_equal '80', req['SERVER_PORT']
|
628
|
+
assert_equal "[::1]:", req['HTTP_HOST']
|
629
|
+
assert_equal "", parser.buf
|
630
|
+
assert parser.keepalive? # TODO: read HTTP/1.2 when it's final
|
631
|
+
end
|
632
|
+
|
633
|
+
# XXX Highly unlikely..., just make sure we don't segfault or assert on it
|
634
|
+
def test_broken_ipv6_host_header
|
635
|
+
parser = HttpParser.new
|
636
|
+
req = parser.env
|
637
|
+
parser.buf << "GET / HTTP/1.1\r\nHost: [::1:\r\n\r\n"
|
638
|
+
assert_equal req, parser.parse
|
639
|
+
assert_equal "[", req['SERVER_NAME']
|
640
|
+
assert_equal ':1:', req['SERVER_PORT']
|
641
|
+
assert_equal "[::1:", req['HTTP_HOST']
|
642
|
+
assert_equal "", parser.buf
|
643
|
+
end
|
644
|
+
|
645
|
+
def test_put_body_oneshot
|
646
|
+
parser = HttpParser.new
|
647
|
+
req = parser.env
|
648
|
+
parser.buf << "PUT / HTTP/1.0\r\nContent-Length: 5\r\n\r\nabcde"
|
649
|
+
assert_equal req, parser.parse
|
491
650
|
assert_equal '/', req['REQUEST_PATH']
|
492
651
|
assert_equal '/', req['REQUEST_URI']
|
493
652
|
assert_equal 'PUT', req['REQUEST_METHOD']
|
494
653
|
assert_equal 'HTTP/1.0', req['HTTP_VERSION']
|
495
654
|
assert_equal 'HTTP/1.0', req['SERVER_PROTOCOL']
|
496
|
-
assert_equal "abcde",
|
655
|
+
assert_equal "abcde", parser.buf
|
497
656
|
assert ! parser.keepalive? # TODO: read HTTP/1.2 when it's final
|
498
657
|
end
|
499
658
|
|
500
659
|
def test_put_body_later
|
501
660
|
parser = HttpParser.new
|
502
|
-
req =
|
503
|
-
|
504
|
-
assert_equal req, parser.
|
661
|
+
req = parser.env
|
662
|
+
parser.buf << "PUT /l HTTP/1.0\r\nContent-Length: 5\r\n\r\n"
|
663
|
+
assert_equal req, parser.parse
|
505
664
|
assert_equal '/l', req['REQUEST_PATH']
|
506
665
|
assert_equal '/l', req['REQUEST_URI']
|
507
666
|
assert_equal 'PUT', req['REQUEST_METHOD']
|
508
667
|
assert_equal 'HTTP/1.0', req['HTTP_VERSION']
|
509
668
|
assert_equal 'HTTP/1.0', req['SERVER_PROTOCOL']
|
510
|
-
assert_equal "",
|
669
|
+
assert_equal "", parser.buf
|
511
670
|
assert ! parser.keepalive? # TODO: read HTTP/1.2 when it's final
|
512
671
|
end
|
513
672
|
|
514
673
|
def test_unknown_methods
|
515
674
|
%w(GETT HEADR XGET XHEAD).each { |m|
|
516
675
|
parser = HttpParser.new
|
517
|
-
req =
|
676
|
+
req = parser.env
|
518
677
|
s = "#{m} /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n\r\n"
|
519
678
|
ok = false
|
520
679
|
assert_nothing_raised do
|
@@ -532,17 +691,18 @@ class HttpParserTest < Test::Unit::TestCase
|
|
532
691
|
|
533
692
|
def test_fragment_in_uri
|
534
693
|
parser = HttpParser.new
|
535
|
-
req =
|
694
|
+
req = parser.env
|
536
695
|
get = "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n\r\n"
|
696
|
+
parser.buf << get
|
537
697
|
ok = false
|
538
698
|
assert_nothing_raised do
|
539
|
-
ok = parser.
|
699
|
+
ok = parser.parse
|
540
700
|
end
|
541
701
|
assert ok
|
542
702
|
assert_equal '/forums/1/topics/2375?page=1', req['REQUEST_URI']
|
543
703
|
assert_equal 'posts-17408', req['FRAGMENT']
|
544
704
|
assert_equal 'page=1', req['QUERY_STRING']
|
545
|
-
assert_equal '',
|
705
|
+
assert_equal '', parser.buf
|
546
706
|
assert parser.keepalive?
|
547
707
|
end
|
548
708
|
|
@@ -568,7 +728,8 @@ class HttpParserTest < Test::Unit::TestCase
|
|
568
728
|
10.times do |c|
|
569
729
|
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-#{rand_data(1024, 1024+(c*1024))}: Test\r\n\r\n"
|
570
730
|
assert_raises Unicorn::HttpParserError do
|
571
|
-
parser.
|
731
|
+
parser.buf << get
|
732
|
+
parser.parse
|
572
733
|
parser.clear
|
573
734
|
end
|
574
735
|
end
|
@@ -577,7 +738,8 @@ class HttpParserTest < Test::Unit::TestCase
|
|
577
738
|
10.times do |c|
|
578
739
|
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-Test: #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
|
579
740
|
assert_raises Unicorn::HttpParserError do
|
580
|
-
parser.
|
741
|
+
parser.buf << get
|
742
|
+
parser.parse
|
581
743
|
parser.clear
|
582
744
|
end
|
583
745
|
end
|
@@ -585,16 +747,18 @@ class HttpParserTest < Test::Unit::TestCase
|
|
585
747
|
# then large headers are rejected too
|
586
748
|
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\n"
|
587
749
|
get << "X-Test: test\r\n" * (80 * 1024)
|
750
|
+
parser.buf << get
|
588
751
|
assert_raises Unicorn::HttpParserError do
|
589
|
-
parser.
|
590
|
-
parser.clear
|
752
|
+
parser.parse
|
591
753
|
end
|
754
|
+
parser.clear
|
592
755
|
|
593
756
|
# finally just that random garbage gets blocked all the time
|
594
757
|
10.times do |c|
|
595
758
|
get = "GET #{rand_data(1024, 1024+(c*1024), false)} #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
|
596
759
|
assert_raises Unicorn::HttpParserError do
|
597
|
-
parser.
|
760
|
+
parser.buf << get
|
761
|
+
parser.parse
|
598
762
|
parser.clear
|
599
763
|
end
|
600
764
|
end
|