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