]> git.ipfire.org Git - thirdparty/squid.git/blame - src/tests/testHttpParser.cc
Drop HttpParser::Pointer::getRaw() uses
[thirdparty/squid.git] / src / tests / testHttpParser.cc
CommitLineData
4c14658e 1#define SQUID_UNIT_TEST 1
f7f3304a 2#include "squid.h"
4c14658e
AJ
3
4#include <cppunit/TestAssert.h>
5
b6a7fc85
AJ
6#define private public
7#define protected public
8
4c14658e
AJ
9#include "testHttpParser.h"
10#include "HttpParser.h"
11#include "Mem.h"
12#include "MemBuf.h"
4d5904f7 13#include "SquidConfig.h"
602d9612 14#include "testHttpParser.h"
4c14658e 15
4c14658e
AJ
16CPPUNIT_TEST_SUITE_REGISTRATION( testHttpParser );
17
18void
19testHttpParser::globalSetup()
20{
21 static bool setup_done = false;
22 if (setup_done)
23 return;
26c66627 24
4c14658e
AJ
25 Mem::Init();
26 setup_done = true;
27}
28
29void
8c730cae 30testHttpParser::testParseRequestLineProtocols()
4c14658e
AJ
31{
32 // ensure MemPools etc exist
33 globalSetup();
34
35 MemBuf input;
36 HttpParser output;
37 input.init();
38
39 // TEST: Do we comply with RFC 1945 section 5.1 ?
40 // TEST: Do we comply with RFC 2616 section 5.1 ?
41
42 // RFC 1945 : HTTP/0.9 simple-request
4245f3b9
AJ
43 {
44 input.append("GET /\r\n", 7);
45 output.reset(input.content(), input.contentSize());
87abd755
AJ
46 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
47 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
48 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
49 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
50 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 51 CPPUNIT_ASSERT_EQUAL(0,memcmp("GET /\r\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
52 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
53 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 54 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start], (output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
55 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
56 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 57 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start], (output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
58 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
59 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
60 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
61 CPPUNIT_ASSERT_EQUAL(9, output.req.v_min);
62 input.reset();
63 }
4c14658e 64
8c730cae
AJ
65 // RFC 1945 : invalid HTTP/0.9 simple-request (only GET is valid)
66#if 0
4245f3b9
AJ
67 {
68 input.append("POST /\r\n", 7);
69 output.reset(input.content(), input.contentSize());
87abd755
AJ
70 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
71 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
72 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
73 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
74 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 75 CPPUNIT_ASSERT_EQUAL(0,memcmp("GET /\r\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
76 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
77 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 78 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start], (output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
79 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
80 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 81 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start], (output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
82 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
83 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
84 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
85 CPPUNIT_ASSERT_EQUAL(9, output.req.v_min);
86 input.reset();
87 }
8c730cae
AJ
88#endif
89
90 // RFC 1945 and 2616 : HTTP/1.0 request
4245f3b9
AJ
91 {
92 input.append("GET / HTTP/1.0\r\n", 16);
93 output.reset(input.content(), input.contentSize());
87abd755
AJ
94 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
95 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
96 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
97 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
98 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 99 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.0\r\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
100 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
101 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 102 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
103 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
104 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 105 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
106 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
107 CPPUNIT_ASSERT_EQUAL(13, output.req.v_end);
5d1dff27 108 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.0", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
109 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
110 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
111 input.reset();
112 }
4c14658e 113
8c730cae 114 // RFC 2616 : HTTP/1.1 request
4245f3b9
AJ
115 {
116 input.append("GET / HTTP/1.1\r\n", 16);
117 output.reset(input.content(), input.contentSize());
87abd755
AJ
118 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
119 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
120 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
121 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
122 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 123 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\r\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
124 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
125 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 126 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
127 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
128 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 129 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
130 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
131 CPPUNIT_ASSERT_EQUAL(13, output.req.v_end);
5d1dff27 132 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
133 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
134 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
135 input.reset();
136 }
4c14658e
AJ
137
138 // RFC 2616 : future version full-request
4245f3b9
AJ
139 { input.append("GET / HTTP/1.2\r\n", 16);
140 //printf("TEST: '%s'\n",input.content());
141 output.reset(input.content(), input.contentSize());
87abd755
AJ
142 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
143 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
144 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
145 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
146 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 147 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.2\r\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
148 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
149 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 150 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
151 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
152 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 153 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
154 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
155 CPPUNIT_ASSERT_EQUAL(13, output.req.v_end);
5d1dff27 156 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.2", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
157 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
158 CPPUNIT_ASSERT_EQUAL(2, output.req.v_min);
159 input.reset();
160 }
8c730cae
AJ
161
162 // RFC 2616 : future version full-request
4245f3b9
AJ
163 {
164 // XXX: IETF HTTPbis WG has made this two-digits format invalid.
165 input.append("GET / HTTP/10.12\r\n", 18);
166 //printf("TEST: '%s'\n",input.content());
167 output.reset(input.content(), input.contentSize());
87abd755
AJ
168 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
169 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
170 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
171 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
172 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 173 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/10.12\r\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
174 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
175 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 176 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
177 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
178 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 179 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
180 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
181 CPPUNIT_ASSERT_EQUAL(15, output.req.v_end);
5d1dff27 182 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/10.12", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
183 CPPUNIT_ASSERT_EQUAL(10, output.req.v_maj);
184 CPPUNIT_ASSERT_EQUAL(12, output.req.v_min);
185 input.reset();
186 }
4c14658e 187
8c730cae 188 // This stage of the parser does not yet accept non-HTTP protocol names.
4245f3b9
AJ
189 {
190 // violations mode treats them as HTTP/0.9 requests!
191 input.append("GET / FOO/1.0\n", 14);
192 //printf("TEST: '%s'\n",input.content());
193 output.reset(input.content(), input.contentSize());
8c730cae 194#if USE_HTTP_VIOLATIONS
87abd755
AJ
195 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
196 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
197 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
198 CPPUNIT_ASSERT_EQUAL(12, output.req.u_end);
5d1dff27 199 CPPUNIT_ASSERT_EQUAL(0, memcmp("/ FOO/1.0", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
200 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
201 CPPUNIT_ASSERT_EQUAL(9, output.req.v_min);
8c730cae 202#else
87abd755
AJ
203 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
204 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
205 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported, output.request_parse_status);
206 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 207 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
208 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
209 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
8c730cae 210#endif
4245f3b9
AJ
211 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
212 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 213 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / FOO/1.0\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
214 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
215 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 216 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
217 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
218 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
219 CPPUNIT_ASSERT_EQUAL(12, output.req.v_end);
5d1dff27 220 CPPUNIT_ASSERT_EQUAL(0, memcmp("FOO/1.0", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
221 input.reset();
222 }
8c730cae
AJ
223
224 // no version
4245f3b9
AJ
225 {
226 input.append("GET / HTTP/\n", 12);
227 //printf("TEST: '%s'\n",input.content());
228 output.reset(input.content(), input.contentSize());
87abd755
AJ
229 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
230 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
231 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported, output.request_parse_status);
232 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
233 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 234 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
235 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
236 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 237 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
238 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
239 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 240 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
241 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
242 CPPUNIT_ASSERT_EQUAL(10, output.req.v_end);
5d1dff27 243 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
244 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
245 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
246 input.reset();
247 }
4c14658e 248
8c730cae 249 // no major version
4245f3b9
AJ
250 {
251 input.append("GET / HTTP/.1\n", 14);
252 //printf("TEST: '%s'\n",input.content());
253 output.reset(input.content(), input.contentSize());
87abd755
AJ
254 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
255 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
256 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported, output.request_parse_status);
257 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
258 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 259 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
260 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
261 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 262 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
263 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
264 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 265 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
266 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
267 CPPUNIT_ASSERT_EQUAL(12, output.req.v_end);
5d1dff27 268 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
269 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
270 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
271 input.reset();
272 }
8c730cae
AJ
273
274 // no version dot
4245f3b9
AJ
275 {
276 input.append("GET / HTTP/11\n", 14);
277 //printf("TEST: '%s'\n",input.content());
278 output.reset(input.content(), input.contentSize());
87abd755
AJ
279 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
280 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
281 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported, output.request_parse_status);
282 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
283 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 284 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/11\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
285 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
286 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 287 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
288 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
289 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 290 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
291 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
292 CPPUNIT_ASSERT_EQUAL(12, output.req.v_end);
5d1dff27 293 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/11", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
294 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
295 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
296 input.reset();
297 }
8c730cae
AJ
298
299 // negative major version (bug 3062)
4245f3b9
AJ
300 {
301 input.append("GET / HTTP/-999999.1\n", 21);
302 //printf("TEST: '%s'\n",input.content());
303 output.reset(input.content(), input.contentSize());
87abd755
AJ
304 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
305 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
306 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported, output.request_parse_status);
307 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
308 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 309 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/-999999.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
310 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
311 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 312 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
313 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
314 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 315 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
316 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
317 CPPUNIT_ASSERT_EQUAL(19, output.req.v_end);
5d1dff27 318 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/-999999.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
319 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
320 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
321 input.reset();
322 }
4c14658e 323
8c730cae 324 // no minor version
4245f3b9
AJ
325 {
326 input.append("GET / HTTP/1.\n", 14);
327 //printf("TEST: '%s'\n",input.content());
328 output.reset(input.content(), input.contentSize());
87abd755
AJ
329 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
330 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
331 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported, output.request_parse_status);
332 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
333 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 334 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
335 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
336 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 337 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
338 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
339 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 340 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
341 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
342 CPPUNIT_ASSERT_EQUAL(12, output.req.v_end);
5d1dff27 343 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
344 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
345 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
346 input.reset();
347 }
8c730cae
AJ
348
349 // negative major version (bug 3062 corollary)
4245f3b9
AJ
350 {
351 input.append("GET / HTTP/1.-999999\n", 21);
352 //printf("TEST: '%s'\n",input.content());
353 output.reset(input.content(), input.contentSize());
87abd755
AJ
354 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
355 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
356 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported, output.request_parse_status);
357 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
358 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 359 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.-999999\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
360 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
361 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 362 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
363 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
364 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 365 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
366 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
367 CPPUNIT_ASSERT_EQUAL(19, output.req.v_end);
5d1dff27 368 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.-999999", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
369 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
370 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
371 input.reset();
372 }
8c730cae
AJ
373}
374
375void
376testHttpParser::testParseRequestLineStrange()
377{
378 // ensure MemPools etc exist
379 globalSetup();
380
381 MemBuf input;
382 HttpParser output;
383 input.init();
384
385 // space padded URL
4245f3b9
AJ
386 {
387 input.append("GET / HTTP/1.1\r\n", 21);
388 //printf("TEST: '%s'\n",input.content());
389 output.reset(input.content(), input.contentSize());
87abd755
AJ
390 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
391 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
392 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
393 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
394 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 395 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\r\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
396 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
397 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 398 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
399 CPPUNIT_ASSERT_EQUAL(5, output.req.u_start);
400 CPPUNIT_ASSERT_EQUAL(5, output.req.u_end);
5d1dff27 401 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
402 CPPUNIT_ASSERT_EQUAL(11, output.req.v_start);
403 CPPUNIT_ASSERT_EQUAL(18, output.req.v_end);
5d1dff27 404 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
405 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
406 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
407 input.reset();
408 }
8c730cae 409
4c14658e 410 // whitespace inside URI. (nasty but happens)
4245f3b9
AJ
411 {
412 input.append("GET /fo o/ HTTP/1.1\n", 20);
413 //printf("TEST: '%s'\n",input.content());
414 output.reset(input.content(), input.contentSize());
87abd755
AJ
415 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
416 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
417 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
418 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
419 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 420 CPPUNIT_ASSERT_EQUAL(0,memcmp("GET /fo o/ HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
421 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
422 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 423 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
424 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
425 CPPUNIT_ASSERT_EQUAL(9, output.req.u_end);
5d1dff27 426 CPPUNIT_ASSERT_EQUAL(0, memcmp("/fo o/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
427 CPPUNIT_ASSERT_EQUAL(11, output.req.v_start);
428 CPPUNIT_ASSERT_EQUAL(18, output.req.v_end);
5d1dff27 429 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
430 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
431 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
432 input.reset();
433 }
4c14658e
AJ
434
435 // additional data in buffer
4245f3b9
AJ
436 {
437 input.append("GET / HTTP/1.1\nboo!", 23);
438 //printf("TEST: '%s'\n",input.content());
439 output.reset(input.content(), input.contentSize());
87abd755
AJ
440 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
441 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
442 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
443 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
444 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-5, output.req.end);
5d1dff27 445 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
446 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
447 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 448 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
449 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
450 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end); // strangeness generated by following RFC
5d1dff27 451 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
452 CPPUNIT_ASSERT_EQUAL(10, output.req.v_start);
453 CPPUNIT_ASSERT_EQUAL(17, output.req.v_end);
5d1dff27 454 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
455 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
456 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
457 input.reset();
458 }
8c730cae
AJ
459}
460
461void
462testHttpParser::testParseRequestLineTerminators()
463{
464 // ensure MemPools etc exist
465 globalSetup();
466
467 MemBuf input;
468 HttpParser output;
469 input.init();
4c14658e
AJ
470
471 // alternative EOL sequence: NL-only
4245f3b9
AJ
472 {
473 input.append("GET / HTTP/1.1\n", 15);
474 //printf("TEST: '%s'\n",input.content());
475 output.reset(input.content(), input.contentSize());
87abd755
AJ
476 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
477 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
478 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
479 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
480 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 481 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
482 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
483 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 484 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
485 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
486 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 487 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
488 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
489 CPPUNIT_ASSERT_EQUAL(13, output.req.v_end);
5d1dff27 490 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
491 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
492 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
493 input.reset();
494 }
4c14658e
AJ
495
496 // alternative EOL sequence: double-NL-only
4245f3b9
AJ
497 {
498 input.append("GET / HTTP/1.1\n\n", 16);
499 //printf("TEST: '%s'\n",input.content());
500 output.reset(input.content(), input.contentSize());
87abd755
AJ
501 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
502 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
503 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
504 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
505 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-2, output.req.end);
5d1dff27 506 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
507 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
508 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 509 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
510 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
511 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 512 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
513 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
514 CPPUNIT_ASSERT_EQUAL(13, output.req.v_end);
5d1dff27 515 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
516 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
517 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
518 input.reset();
519 }
4c14658e
AJ
520
521 // RELAXED alternative EOL sequence: multi-CR-NL
4245f3b9
AJ
522 {
523 input.append("GET / HTTP/1.1\r\r\r\n", 18);
524 //printf("TEST: '%s'\n",input.content());
525 output.reset(input.content(), input.contentSize());
526 Config.onoff.relaxed_header_parser = 1;
527 // Being tolerant we can ignore and elide these apparently benign CR
87abd755
AJ
528 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
529 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
530 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
531 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
532 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 533 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\r\r\r\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
534 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
535 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 536 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
537 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
538 CPPUNIT_ASSERT_EQUAL(4, output.req.u_end);
5d1dff27 539 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
540 CPPUNIT_ASSERT_EQUAL(6, output.req.v_start);
541 CPPUNIT_ASSERT_EQUAL(13, output.req.v_end);
5d1dff27 542 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
543 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
544 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
545 input.reset();
546 }
4c14658e
AJ
547
548 // STRICT alternative EOL sequence: multi-CR-NL
4245f3b9
AJ
549 {
550 input.append("GET / HTTP/1.1\r\r\r\n", 18);
551 //printf("TEST: '%s'\n",input.content());
552 output.reset(input.content(), input.contentSize());
553 // strict mode treats these as several bare-CR in the request line which is explicitly invalid.
554 Config.onoff.relaxed_header_parser = 0;
87abd755
AJ
555 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
556 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
557 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status);
558 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
559 CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
560 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
561 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
562 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
563 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
564 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
565 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
566 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
567 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
568 input.reset();
569 }
4c14658e 570
8c730cae 571 // space padded version
4245f3b9
AJ
572 {
573 // RFC 1945 and 2616 specify version is followed by CRLF. No intermediary bytes.
574 // NP: the terminal whitespace is a special case: invalid for even HTTP/0.9 with no version tag
575 input.append("GET / HTTP/1.1 \n", 16);
576 //printf("TEST: '%s'\n",input.content());
577 output.reset(input.content(), input.contentSize());
87abd755
AJ
578 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
579 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
580 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status);
581 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
582 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 583 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1 \n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
584 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
585 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 586 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
587 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
588 CPPUNIT_ASSERT_EQUAL(13, output.req.u_end);
5d1dff27 589 CPPUNIT_ASSERT_EQUAL(0, memcmp("/ HTTP/1.1", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
590 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
591 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
592 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
593 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
594 input.reset();
595 }
8c730cae
AJ
596
597 // incomplete line at various positions
4245f3b9
AJ
598 {
599 input.append("GET", 3);
600 //printf("TEST: '%s'\n",input.content());
601 output.reset(input.content(), input.contentSize());
87abd755
AJ
602 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
603 CPPUNIT_ASSERT_EQUAL(false, output.isDone());
4245f3b9
AJ
604 CPPUNIT_ASSERT_EQUAL(Http::scNone, output.request_parse_status);
605 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
606 CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
607 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
608 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
609 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
610 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
611 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
612 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
613 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
614 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
615 input.reset();
8c730cae 616
4245f3b9
AJ
617 input.append("GET ", 4);
618 //printf("TEST: '%s'\n",input.content());
619 output.reset(input.content(), input.contentSize());
87abd755
AJ
620 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
621 CPPUNIT_ASSERT_EQUAL(false, output.isDone());
4245f3b9
AJ
622 CPPUNIT_ASSERT_EQUAL(Http::scNone, output.request_parse_status);
623 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
624 CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
625 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
626 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
627 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
628 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
629 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
630 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
631 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
632 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
633 input.reset();
634
635 input.append("GET / HT", 8);
636 //printf("TEST: '%s'\n",input.content());
637 output.reset(input.content(), input.contentSize());
87abd755
AJ
638 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
639 CPPUNIT_ASSERT_EQUAL(false, output.isDone());
4245f3b9
AJ
640 CPPUNIT_ASSERT_EQUAL(Http::scNone, output.request_parse_status);
641 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
642 CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
643 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
644 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
645 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
646 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
647 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
648 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
649 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
650 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
651 input.reset();
652
653 input.append("GET / HTTP/1.1", 14);
654 //printf("TEST: '%s'\n",input.content());
655 output.reset(input.content(), input.contentSize());
87abd755
AJ
656 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
657 CPPUNIT_ASSERT_EQUAL(false, output.isDone());
4245f3b9
AJ
658 CPPUNIT_ASSERT_EQUAL(Http::scNone, output.request_parse_status);
659 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
660 CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
661 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
662 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
663 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
664 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
665 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
666 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
667 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
668 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
669 input.reset();
670 }
8c730cae
AJ
671}
672
673void
674testHttpParser::testParseRequestLineMethods()
675{
676 // ensure MemPools etc exist
677 globalSetup();
678
679 MemBuf input;
680 HttpParser output;
681 input.init();
682
4c14658e 683 // RFC 2616 : . method
4245f3b9
AJ
684 {
685 input.append(". / HTTP/1.1\n", 13);
686 //printf("TEST: '%s'\n",input.content());
687 output.reset(input.content(), input.contentSize());
87abd755
AJ
688 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
689 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
690 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
691 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
692 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 693 CPPUNIT_ASSERT_EQUAL(0, memcmp(". / HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
694 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
695 CPPUNIT_ASSERT_EQUAL(0, output.req.m_end);
5d1dff27 696 CPPUNIT_ASSERT_EQUAL(0, memcmp(".", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
697 CPPUNIT_ASSERT_EQUAL(2, output.req.u_start);
698 CPPUNIT_ASSERT_EQUAL(2, output.req.u_end);
5d1dff27 699 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
700 CPPUNIT_ASSERT_EQUAL(4, output.req.v_start);
701 CPPUNIT_ASSERT_EQUAL(11, output.req.v_end);
5d1dff27 702 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
703 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
704 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
705 input.reset();
706 }
4c14658e
AJ
707
708 // OPTIONS with * URL
4245f3b9
AJ
709 {
710 input.append("OPTIONS * HTTP/1.1\n", 19);
711 //printf("TEST: '%s'\n",input.content());
712 output.reset(input.content(), input.contentSize());
87abd755
AJ
713 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
714 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
715 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
716 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
717 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 718 CPPUNIT_ASSERT_EQUAL(0, memcmp("OPTIONS * HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
719 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
720 CPPUNIT_ASSERT_EQUAL(6, output.req.m_end);
5d1dff27 721 CPPUNIT_ASSERT_EQUAL(0, memcmp("OPTIONS", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
722 CPPUNIT_ASSERT_EQUAL(8, output.req.u_start);
723 CPPUNIT_ASSERT_EQUAL(8, output.req.u_end);
5d1dff27 724 CPPUNIT_ASSERT_EQUAL(0, memcmp("*", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
725 CPPUNIT_ASSERT_EQUAL(10, output.req.v_start);
726 CPPUNIT_ASSERT_EQUAL(17, output.req.v_end);
5d1dff27 727 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
728 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
729 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
730 input.reset();
731 }
4c14658e
AJ
732
733 // unknown method
4245f3b9
AJ
734 {
735 input.append("HELLOWORLD / HTTP/1.1\n", 22);
736 //printf("TEST: '%s'\n",input.content());
737 output.reset(input.content(), input.contentSize());
87abd755
AJ
738 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
739 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
740 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
741 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
742 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 743 CPPUNIT_ASSERT_EQUAL(0, memcmp("HELLOWORLD / HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
744 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
745 CPPUNIT_ASSERT_EQUAL(9, output.req.m_end);
5d1dff27 746 CPPUNIT_ASSERT_EQUAL(0, memcmp("HELLOWORLD", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
747 CPPUNIT_ASSERT_EQUAL(11, output.req.u_start);
748 CPPUNIT_ASSERT_EQUAL(11, output.req.u_end);
5d1dff27 749 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
750 CPPUNIT_ASSERT_EQUAL(13, output.req.v_start);
751 CPPUNIT_ASSERT_EQUAL(20, output.req.v_end);
5d1dff27 752 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
753 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
754 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
755 input.reset();
756 }
4c14658e 757
8c730cae 758 // method-only
4245f3b9
AJ
759 {
760 input.append("A\n", 2);
761 //printf("TEST: '%s'\n",input.content());
762 output.reset(input.content(), input.contentSize());
87abd755
AJ
763 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
764 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
765 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status);
766 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
767 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 768 CPPUNIT_ASSERT_EQUAL(0, memcmp("A\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
769 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
770 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
771 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
772 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
773 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
774 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
775 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
776 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
777 input.reset();
778 }
8c730cae
AJ
779
780 input.append("GET\n", 4);
4245f3b9
AJ
781 {
782 //printf("TEST: '%s'\n",input.content());
783 output.reset(input.content(), input.contentSize());
87abd755
AJ
784 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
785 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
786 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status);
787 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
788 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 789 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
790 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
791 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
792 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
793 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
794 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
795 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
796 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
797 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
798 input.reset();
799 }
4c14658e
AJ
800
801 // RELAXED space padded method (in strict mode SP is reserved so invalid as a method byte)
4245f3b9
AJ
802 {
803 input.append(" GET / HTTP/1.1\n", 16);
804 //printf("TEST: '%s'\n",input.content());
805 output.reset(input.content(), input.contentSize());
806 Config.onoff.relaxed_header_parser = 1;
87abd755
AJ
807 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
808 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
809 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
810 CPPUNIT_ASSERT_EQUAL(1, output.req.start);
811 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 812 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
813 CPPUNIT_ASSERT_EQUAL(1, output.req.m_start);
814 CPPUNIT_ASSERT_EQUAL(3, output.req.m_end);
5d1dff27 815 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
816 CPPUNIT_ASSERT_EQUAL(5, output.req.u_start);
817 CPPUNIT_ASSERT_EQUAL(5, output.req.u_end);
5d1dff27 818 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
819 CPPUNIT_ASSERT_EQUAL(7, output.req.v_start);
820 CPPUNIT_ASSERT_EQUAL(14, output.req.v_end);
5d1dff27 821 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
822 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
823 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
824 input.reset();
825 }
4c14658e
AJ
826
827 // STRICT space padded method (in strict mode SP is reserved so invalid as a method byte)
4245f3b9
AJ
828 {
829 input.append(" GET / HTTP/1.1\n", 16);
830 //printf("TEST: '%s'\n",input.content());
831 output.reset(input.content(), input.contentSize());
832 Config.onoff.relaxed_header_parser = 0;
87abd755
AJ
833 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
834 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
835 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status);
836 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
837 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 838 CPPUNIT_ASSERT_EQUAL(0, memcmp(" GET / HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
839 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
840 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
841 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
842 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
843 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
844 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
845 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
846 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
847 input.reset();
848 }
4c14658e
AJ
849
850 // tab padded method (NP: tab is not SP so treated as any other binary)
4245f3b9
AJ
851 {
852 input.append("\tGET / HTTP/1.1\n", 16);
853 //printf("TEST: '%s'\n",input.content());
854 output.reset(input.content(), input.contentSize());
87abd755
AJ
855 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
856 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
857 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
858 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
859 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 860 CPPUNIT_ASSERT_EQUAL(0, memcmp("\tGET / HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
861 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
862 CPPUNIT_ASSERT_EQUAL(3, output.req.m_end);
5d1dff27 863 CPPUNIT_ASSERT_EQUAL(0, memcmp("\tGET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
864 CPPUNIT_ASSERT_EQUAL(5, output.req.u_start);
865 CPPUNIT_ASSERT_EQUAL(5, output.req.u_end);
5d1dff27 866 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
867 CPPUNIT_ASSERT_EQUAL(7, output.req.v_start);
868 CPPUNIT_ASSERT_EQUAL(14, output.req.v_end);
5d1dff27 869 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
870 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
871 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
872 input.reset();
873 }
8c730cae 874}
4c14658e 875
8c730cae
AJ
876void
877testHttpParser::testParseRequestLineInvalid()
878{
879 // ensure MemPools etc exist
880 globalSetup();
4c14658e 881
8c730cae
AJ
882 MemBuf input;
883 HttpParser output;
884 input.init();
4c14658e
AJ
885
886 // no method (but in a form which is ambiguous with HTTP/0.9 simple-request)
4245f3b9
AJ
887 {
888 // XXX: Bug: HTTP/0.9 requires method to be "GET"
889 input.append("/ HTTP/1.0\n", 11);
890 //printf("TEST: '%s'\n",input.content());
891 output.reset(input.content(), input.contentSize());
87abd755
AJ
892 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
893 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
894 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
895 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
896 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 897 CPPUNIT_ASSERT_EQUAL(0, memcmp("/ HTTP/1.0\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
898 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
899 CPPUNIT_ASSERT_EQUAL(0, output.req.m_end);
5d1dff27 900 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
901 CPPUNIT_ASSERT_EQUAL(2, output.req.u_start);
902 CPPUNIT_ASSERT_EQUAL(9, output.req.u_end);
5d1dff27 903 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.0", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
904 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
905 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
906 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
907 CPPUNIT_ASSERT_EQUAL(9, output.req.v_min);
908 input.reset();
909 }
4c14658e
AJ
910
911 // RELAXED no method (an invalid format)
4245f3b9
AJ
912 {
913 input.append(" / HTTP/1.0\n", 12);
914 //printf("TEST: '%s'\n",input.content());
915 output.reset(input.content(), input.contentSize());
916 // When tolerantly ignoring SP prefix this case becomes ambiguous with HTTP/0.9 simple-request)
917 Config.onoff.relaxed_header_parser = 1;
87abd755
AJ
918 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
919 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
920 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
921 CPPUNIT_ASSERT_EQUAL(1, output.req.start);
922 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 923 CPPUNIT_ASSERT_EQUAL(0, memcmp("/ HTTP/1.0\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
924 CPPUNIT_ASSERT_EQUAL(1, output.req.m_start);
925 CPPUNIT_ASSERT_EQUAL(1, output.req.m_end);
5d1dff27 926 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
927 CPPUNIT_ASSERT_EQUAL(3, output.req.u_start);
928 CPPUNIT_ASSERT_EQUAL(10, output.req.u_end);
5d1dff27 929 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.0", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
930 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
931 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
932 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
933 CPPUNIT_ASSERT_EQUAL(9, output.req.v_min);
934 input.reset();
935 }
4c14658e
AJ
936
937 // STRICT no method (an invalid format)
4245f3b9
AJ
938 {
939 input.append(" / HTTP/1.0\n", 12);
940 //printf("TEST: '%s'\n",input.content());
941 output.reset(input.content(), input.contentSize());
942 // When tolerantly ignoring SP prefix this case becomes ambiguous with HTTP/0.9 simple-request)
943 Config.onoff.relaxed_header_parser = 0;
87abd755
AJ
944 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
945 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
946 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status);
947 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
948 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 949 CPPUNIT_ASSERT_EQUAL(0, memcmp(" / HTTP/1.0\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
950 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
951 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
952 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
953 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
954 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
955 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
956 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
957 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
958 input.reset();
959 }
4c14658e
AJ
960
961 // binary code in method (strange but ...)
4245f3b9
AJ
962 {
963 input.append("GET\x0B / HTTP/1.1\n", 16);
964 //printf("TEST: %d-%d/%d '%.*s'\n", output.req.start, output.req.end, input.contentSize(), 16, input.content());
965 output.reset(input.content(), input.contentSize());
87abd755
AJ
966 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
967 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
968 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
969 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
970 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 971 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\x0B / HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
972 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
973 CPPUNIT_ASSERT_EQUAL(3, output.req.m_end);
5d1dff27 974 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\x0B", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
975 CPPUNIT_ASSERT_EQUAL(5, output.req.u_start);
976 CPPUNIT_ASSERT_EQUAL(5, output.req.u_end);
5d1dff27 977 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
978 CPPUNIT_ASSERT_EQUAL(7, output.req.v_start);
979 CPPUNIT_ASSERT_EQUAL(14, output.req.v_end);
5d1dff27 980 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
981 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
982 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
983 input.reset();
984 }
4c14658e
AJ
985
986 // CR in method
4245f3b9
AJ
987 {
988 // RFC 2616 sec 5.1 prohibits CR other than in terminator.
989 input.append("GET\r / HTTP/1.1\r\n", 16);
990 //printf("TEST: '%s'\n",input.content());
991 output.reset(input.content(), input.contentSize());
87abd755
AJ
992 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
993 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
994 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status);
995 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
996 CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
997 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
998 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
999 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
1000 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
1001 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
1002 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
1003 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
1004 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
1005 input.reset();
1006 }
4c14658e
AJ
1007
1008 // binary code NUL! in method (strange but ...)
4245f3b9
AJ
1009 {
1010 input.append("GET\0 / HTTP/1.1\n", 16);
1011 //printf("TEST: %d-%d/%d '%.*s'\n", output.req.start, output.req.end, input.contentSize(), 16, input.content());
1012 output.reset(input.content(), input.contentSize());
87abd755
AJ
1013 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
1014 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
1015 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
1016 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
1017 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 1018 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\0 / HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
1019 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
1020 CPPUNIT_ASSERT_EQUAL(3, output.req.m_end);
5d1dff27 1021 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\0", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
1022 CPPUNIT_ASSERT_EQUAL(5, output.req.u_start);
1023 CPPUNIT_ASSERT_EQUAL(5, output.req.u_end);
5d1dff27 1024 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
1025 CPPUNIT_ASSERT_EQUAL(7, output.req.v_start);
1026 CPPUNIT_ASSERT_EQUAL(14, output.req.v_end);
5d1dff27 1027 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)));
4245f3b9
AJ
1028 CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj);
1029 CPPUNIT_ASSERT_EQUAL(1, output.req.v_min);
1030 input.reset();
1031 }
4c14658e
AJ
1032
1033 // no URL (grammer otherwise correct)
4245f3b9
AJ
1034 {
1035 input.append("GET HTTP/1.1\n", 14);
1036 //printf("TEST: '%s'\n",input.content());
1037 output.reset(input.content(), input.contentSize());
87abd755
AJ
1038 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
1039 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
1040 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
1041 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
1042 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 1043 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
1044 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
1045 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 1046 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
1047 CPPUNIT_ASSERT_EQUAL(5, output.req.u_start);
1048 CPPUNIT_ASSERT_EQUAL(12, output.req.u_end);
1049 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
5d1dff27 1050 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
1051 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
1052 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
1053 CPPUNIT_ASSERT_EQUAL(9, output.req.v_min);
1054 input.reset();
1055 }
4c14658e
AJ
1056
1057 // no URL (grammer invalid, ambiguous with RFC 1945 HTTP/0.9 simple-request)
4245f3b9
AJ
1058 {
1059 input.append("GET HTTP/1.1\n", 13);
1060 //printf("TEST: '%s'\n",input.content());
1061 output.reset(input.content(), input.contentSize());
87abd755
AJ
1062 CPPUNIT_ASSERT_EQUAL(true, output.parseRequest());
1063 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
1064 CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status);
1065 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
1066 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 1067 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
1068 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
1069 CPPUNIT_ASSERT_EQUAL(2, output.req.m_end);
5d1dff27 1070 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
1071 CPPUNIT_ASSERT_EQUAL(4, output.req.u_start);
1072 CPPUNIT_ASSERT_EQUAL(11, output.req.u_end);
5d1dff27 1073 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)));
4245f3b9
AJ
1074 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
1075 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
1076 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
1077 CPPUNIT_ASSERT_EQUAL(9, output.req.v_min);
1078 input.reset();
1079 }
4c14658e 1080
4c14658e 1081 // binary line
4245f3b9
AJ
1082 {
1083 input.append("\xB\xC\xE\xF\n", 5);
1084 //printf("TEST: binary-line\n");
1085 output.reset(input.content(), input.contentSize());
87abd755
AJ
1086 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
1087 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
1088 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status);
1089 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
1090 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 1091 CPPUNIT_ASSERT_EQUAL(0, memcmp("\xB\xC\xE\xF\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
1092 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
1093 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
1094 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
1095 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
1096 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
1097 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
1098 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
1099 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
1100 input.reset();
1101 }
4c14658e
AJ
1102
1103 // mixed whitespace line
4245f3b9
AJ
1104 {
1105 // We accept non-space binary bytes for method so first \t shows up as that
1106 // but remaining space and tabs are skipped searching for URI-start
1107 input.append("\t \t \t\n", 6);
1108 //printf("TEST: mixed whitespace\n");
1109 output.reset(input.content(), input.contentSize());
87abd755
AJ
1110 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
1111 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
1112 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status);
1113 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
1114 CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end);
5d1dff27 1115 CPPUNIT_ASSERT_EQUAL(0, memcmp("\t \t \t\n", &output.buf[output.req.start],(output.req.end-output.req.start+1)));
4245f3b9
AJ
1116 CPPUNIT_ASSERT_EQUAL(0, output.req.m_start);
1117 CPPUNIT_ASSERT_EQUAL(0, output.req.m_end);
5d1dff27 1118 CPPUNIT_ASSERT_EQUAL(0, memcmp("\t", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)));
4245f3b9
AJ
1119 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
1120 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
1121 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
1122 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
1123 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
1124 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
1125 input.reset();
1126 }
4c14658e
AJ
1127
1128 // mixed whitespace line with CR middle
4245f3b9
AJ
1129 {
1130 // CR aborts on sight, so even initial \t method is not marked as above
1131 // (not when parsing clean with whole line available anyway)
1132 input.append("\t \r \n", 6);
1133 //printf("TEST: mixed whitespace with CR\n");
1134 output.reset(input.content(), input.contentSize());
87abd755
AJ
1135 CPPUNIT_ASSERT_EQUAL(false, output.parseRequest());
1136 CPPUNIT_ASSERT_EQUAL(true, output.isDone());
4245f3b9
AJ
1137 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status);
1138 CPPUNIT_ASSERT_EQUAL(0, output.req.start);
1139 CPPUNIT_ASSERT_EQUAL(-1, output.req.end);
1140 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start);
1141 CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end);
1142 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start);
1143 CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end);
1144 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start);
1145 CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end);
1146 CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj);
1147 CPPUNIT_ASSERT_EQUAL(0, output.req.v_min);
1148 input.reset();
1149 }
4c14658e 1150}
b6a7fc85
AJ
1151
1152void
1153testHttpParser::testDripFeed()
1154{
1155 // Simulate a client drip-feeding Squid a few bytes at a time.
1156 // extend the size of the buffer from 0 bytes to full request length
1157 // calling the parser repeatedly as visible data grows.
1158
1159 MemBuf mb;
1160 mb.init(1024, 1024);
1161 mb.append(" ", 12);
1162 int garbageEnd = mb.contentSize();
1163 mb.append("GET http://example.com/ HTTP/1.1\r\n", 34);
1164 int reqLineEnd = mb.contentSize();
1165 mb.append("\n", 1);
1166
1167 HttpParser hp(mb.content(), 0);
1168
1169 // only relaxed parser accepts the garbage whitespace
1170 Config.onoff.relaxed_header_parser = 1;
1171
1172 for (; hp.bufsiz < mb.contentSize(); ++hp.bufsiz) {
87abd755 1173 bool parseResult = hp.parseRequest();
b6a7fc85
AJ
1174
1175#if WHEN_TEST_DEBUG_IS_NEEDED
1176 printf("%d/%d :: %d, %d, %d '%c'\n", hp.bufsiz, mb.contentSize(),
1177 garbageEnd, reqLineEnd, parseResult,
1178 mb.content()[hp.bufsiz]);
1179#endif
1180
1181 // before end of garbage found its a moving offset.
1182 if (hp.bufsiz < garbageEnd) {
1183 CPPUNIT_ASSERT_EQUAL(hp.bufsiz, (int)hp.parseOffset_);
87abd755 1184 CPPUNIT_ASSERT_EQUAL(false, hp.isDone());
b6a7fc85
AJ
1185 continue;
1186 }
1187
1188 // before request line found, parse announces incomplete
1189 if (hp.bufsiz < reqLineEnd) {
1190 CPPUNIT_ASSERT_EQUAL(garbageEnd, (int)hp.parseOffset_);
87abd755
AJ
1191 CPPUNIT_ASSERT_EQUAL(false, parseResult);
1192 CPPUNIT_ASSERT_EQUAL(false, hp.isDone());
b6a7fc85
AJ
1193 continue;
1194 }
1195
1196 // once request line is found (AND the following \n) current parser announces success
1197 CPPUNIT_ASSERT_EQUAL(reqLineEnd, (int)hp.parseOffset_);
87abd755
AJ
1198 CPPUNIT_ASSERT_EQUAL(true, parseResult);
1199 CPPUNIT_ASSERT_EQUAL(true, hp.isDone());
b6a7fc85
AJ
1200 }
1201}