1 #define SQUID_UNIT_TEST 1
4 #include <cppunit/TestAssert.h>
7 #define protected public
9 #include "testHttp1Parser.h"
10 #include "http/Http1Parser.h"
11 #include "http/RequestMethod.h"
14 #include "SquidConfig.h"
15 #include "testHttp1Parser.h"
17 CPPUNIT_TEST_SUITE_REGISTRATION( testHttp1Parser
);
20 testHttp1Parser::globalSetup()
22 static bool setup_done
= false;
29 // default to strict parser. set for loose parsing specifically where behaviour differs.
30 Config
.onoff
.relaxed_header_parser
= 0;
32 Config
.maxRequestHeaderSize
= 1024; // XXX: unit test the RequestParser handling of this limit
36 testHttp1Parser::testParseRequestLineProtocols()
38 // ensure MemPools etc exist
42 Http1::RequestParser output
;
45 // TEST: Do we comply with RFC 1945 section 5.1 ?
46 // TEST: Do we comply with RFC 2616 section 5.1 ?
48 // RFC 1945 : HTTP/0.9 simple-request
50 input
.append("GET /\r\n", 7);
51 output
.reset(input
.content(), input
.contentSize());
52 CPPUNIT_ASSERT_EQUAL(true, output
.parse());
53 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
54 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
55 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
56 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
57 CPPUNIT_ASSERT_EQUAL(0,memcmp("GET /\r\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
58 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
59 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
60 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
], (output
.req
.m_end
-output
.req
.m_start
+1)));
61 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
62 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
63 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
64 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
], (output
.req
.u_end
-output
.req
.u_start
+1)));
65 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
66 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
67 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,0,9), output
.msgProtocol_
);
71 // RFC 1945 : invalid HTTP/0.9 simple-request (only GET is valid)
74 input
.append("POST /\r\n", 7);
75 output
.reset(input
.content(), input
.contentSize());
76 CPPUNIT_ASSERT_EQUAL(true, output
.parse());
77 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
78 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
79 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
80 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
81 CPPUNIT_ASSERT_EQUAL(0,memcmp("POST /\r\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
82 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
83 CPPUNIT_ASSERT_EQUAL(3, output
.req
.m_end
);
84 CPPUNIT_ASSERT_EQUAL(0, memcmp("POST", &output
.buf
[output
.req
.m_start
], (output
.req
.m_end
-output
.req
.m_start
+1)));
85 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_POST
), output
.method_
);
86 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_start
);
87 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_end
);
88 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
], (output
.req
.u_end
-output
.req
.u_start
+1)));
89 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
90 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
91 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
96 // RFC 1945 and 2616 : HTTP/1.0 request
98 input
.append("GET / HTTP/1.0\r\n", 16);
99 output
.reset(input
.content(), input
.contentSize());
100 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
101 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
102 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
103 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
104 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
105 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
106 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.0\r\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
107 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
108 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
109 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
110 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
111 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
112 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
113 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
114 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
115 CPPUNIT_ASSERT_EQUAL(13, output
.req
.v_end
);
116 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.0", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
117 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,0), output
.msgProtocol_
);
121 // RFC 2616 : HTTP/1.1 request
123 input
.append("GET / HTTP/1.1\r\n", 16);
124 output
.reset(input
.content(), input
.contentSize());
125 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
126 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
127 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
128 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
129 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
130 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
131 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\r\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
132 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
133 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
134 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
135 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
136 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
137 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
138 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
139 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
140 CPPUNIT_ASSERT_EQUAL(13, output
.req
.v_end
);
141 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
142 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
146 // RFC 2616 : future version full-request
148 input
.append("GET / HTTP/1.2\r\n", 16);
149 //printf("TEST: '%s'\n",input.content());
150 output
.reset(input
.content(), input
.contentSize());
151 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
152 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
153 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
154 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
155 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
156 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
157 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.2\r\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
158 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
159 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
160 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
161 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
162 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
163 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
164 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
165 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
166 CPPUNIT_ASSERT_EQUAL(13, output
.req
.v_end
);
167 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.2", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
168 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,2), output
.msgProtocol_
);
172 // RFC 2616 : future version full-request
174 // IETF HTTPbis WG has made this two-digits format invalid.
175 // it gets treated same as HTTP/0.9 for now
176 input
.append("GET / HTTP/10.12\r\n", 18);
177 //printf("TEST: '%s'\n",input.content());
178 output
.reset(input
.content(), input
.contentSize());
179 CPPUNIT_ASSERT_EQUAL(true, output
.parse()); // BUG: declares true
180 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
181 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
182 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
183 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
184 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/10.12\r\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
185 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
186 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
187 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
188 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
189 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
190 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
191 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
192 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
193 CPPUNIT_ASSERT_EQUAL(15, output
.req
.v_end
);
194 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/10.12", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
195 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,10,12), output
.msgProtocol_
);
199 // This stage of the parser does not yet accept non-HTTP protocol names.
201 // violations mode treats them as HTTP/0.9 requests!
202 input
.append("GET / FOO/1.0\n", 14);
203 //printf("TEST: '%s'\n",input.content());
204 output
.reset(input
.content(), input
.contentSize());
205 #if USE_HTTP_VIOLATIONS
206 CPPUNIT_ASSERT_EQUAL(true, output
.parse());
207 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
208 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
209 CPPUNIT_ASSERT_EQUAL(12, output
.req
.u_end
);
210 CPPUNIT_ASSERT_EQUAL(0, memcmp("/ FOO/1.0", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
211 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,0,9), output
.msgProtocol_
);
213 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
214 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
215 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported
, output
.request_parse_status
);
216 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
217 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
218 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
220 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
221 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
222 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / FOO/1.0\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
223 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
224 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
225 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
226 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
227 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
228 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
229 CPPUNIT_ASSERT_EQUAL(12, output
.req
.v_end
);
230 CPPUNIT_ASSERT_EQUAL(0, memcmp("FOO/1.0", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
236 input
.append("GET / HTTP/\n", 12);
237 //printf("TEST: '%s'\n",input.content());
238 output
.reset(input
.content(), input
.contentSize());
239 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
240 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
241 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported
, output
.request_parse_status
);
242 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
243 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
244 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
245 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
246 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
247 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
248 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
249 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
250 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
251 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
252 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
253 CPPUNIT_ASSERT_EQUAL(10, output
.req
.v_end
);
254 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
255 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,0,0), output
.msgProtocol_
);
261 input
.append("GET / HTTP/.1\n", 14);
262 //printf("TEST: '%s'\n",input.content());
263 output
.reset(input
.content(), input
.contentSize());
264 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
265 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
266 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported
, output
.request_parse_status
);
267 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
268 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
269 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
270 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
271 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
272 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
273 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
274 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
275 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
276 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
277 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
278 CPPUNIT_ASSERT_EQUAL(12, output
.req
.v_end
);
279 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
280 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,0,0), output
.msgProtocol_
);
286 input
.append("GET / HTTP/11\n", 14);
287 //printf("TEST: '%s'\n",input.content());
288 output
.reset(input
.content(), input
.contentSize());
289 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
290 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
291 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported
, output
.request_parse_status
);
292 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
293 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
294 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/11\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
295 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
296 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
297 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
298 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
299 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
300 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
301 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
302 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
303 CPPUNIT_ASSERT_EQUAL(12, output
.req
.v_end
);
304 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/11", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
305 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,0,0), output
.msgProtocol_
);
309 // negative major version (bug 3062)
311 input
.append("GET / HTTP/-999999.1\n", 21);
312 //printf("TEST: '%s'\n",input.content());
313 output
.reset(input
.content(), input
.contentSize());
314 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
315 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
316 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported
, output
.request_parse_status
);
317 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
318 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
319 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/-999999.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
320 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
321 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
322 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
323 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
324 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
325 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
326 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
327 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
328 CPPUNIT_ASSERT_EQUAL(19, output
.req
.v_end
);
329 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/-999999.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
330 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,0,0), output
.msgProtocol_
);
336 input
.append("GET / HTTP/1.\n", 14);
337 //printf("TEST: '%s'\n",input.content());
338 output
.reset(input
.content(), input
.contentSize());
339 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
340 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
341 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported
, output
.request_parse_status
);
342 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
343 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
344 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
345 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
346 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
347 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
348 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
349 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
350 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
351 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
352 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
353 CPPUNIT_ASSERT_EQUAL(12, output
.req
.v_end
);
354 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
355 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,0), output
.msgProtocol_
);
359 // negative major version (bug 3062 corollary)
361 input
.append("GET / HTTP/1.-999999\n", 21);
362 //printf("TEST: '%s'\n",input.content());
363 output
.reset(input
.content(), input
.contentSize());
364 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
365 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
366 CPPUNIT_ASSERT_EQUAL(Http::scHttpVersionNotSupported
, output
.request_parse_status
);
367 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
368 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
369 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.-999999\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
370 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
371 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
372 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
373 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
374 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
375 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
376 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
377 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
378 CPPUNIT_ASSERT_EQUAL(19, output
.req
.v_end
);
379 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.-999999", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
380 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,0), output
.msgProtocol_
);
386 testHttp1Parser::testParseRequestLineStrange()
388 // ensure MemPools etc exist
392 Http1::RequestParser output
;
397 input
.append("GET / HTTP/1.1\r\n", 21);
398 //printf("TEST: '%s'\n",input.content());
399 output
.reset(input
.content(), input
.contentSize());
400 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
401 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
402 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
403 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
404 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
405 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
406 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\r\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
407 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
408 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
409 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
410 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
411 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_start
);
412 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_end
);
413 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
414 CPPUNIT_ASSERT_EQUAL(11, output
.req
.v_start
);
415 CPPUNIT_ASSERT_EQUAL(18, output
.req
.v_end
);
416 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
417 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
421 // whitespace inside URI. (nasty but happens)
423 input
.append("GET /fo o/ HTTP/1.1\n", 20);
424 //printf("TEST: '%s'\n",input.content());
425 output
.reset(input
.content(), input
.contentSize());
426 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
427 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
428 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
429 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
430 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
431 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
432 CPPUNIT_ASSERT_EQUAL(0,memcmp("GET /fo o/ HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
433 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
434 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
435 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
436 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
437 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
438 CPPUNIT_ASSERT_EQUAL(9, output
.req
.u_end
);
439 CPPUNIT_ASSERT_EQUAL(0, memcmp("/fo o/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
440 CPPUNIT_ASSERT_EQUAL(11, output
.req
.v_start
);
441 CPPUNIT_ASSERT_EQUAL(18, output
.req
.v_end
);
442 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
443 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
447 // additional data in buffer
449 input
.append("GET / HTTP/1.1\nboo!", 23);
450 //printf("TEST: '%s'\n",input.content());
451 output
.reset(input
.content(), input
.contentSize());
452 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
453 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
454 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
455 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
456 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
457 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-5, output
.req
.end
);
458 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
459 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
460 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
461 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
462 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
463 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
464 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
); // strangeness generated by following RFC
465 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
466 CPPUNIT_ASSERT_EQUAL(10, output
.req
.v_start
);
467 CPPUNIT_ASSERT_EQUAL(17, output
.req
.v_end
);
468 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
469 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
475 testHttp1Parser::testParseRequestLineTerminators()
477 // ensure MemPools etc exist
481 Http1::RequestParser output
;
484 // alternative EOL sequence: NL-only
486 input
.append("GET / HTTP/1.1\n", 15);
487 //printf("TEST: '%s'\n",input.content());
488 output
.reset(input
.content(), input
.contentSize());
489 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
490 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
491 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
492 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
493 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
494 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
495 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
496 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
497 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
498 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
499 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
500 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
501 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
502 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
503 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
504 CPPUNIT_ASSERT_EQUAL(13, output
.req
.v_end
);
505 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
506 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
510 // alternative EOL sequence: double-NL-only
512 input
.append("GET / HTTP/1.1\n\n", 16);
513 //printf("TEST: '%s'\n",input.content());
514 output
.reset(input
.content(), input
.contentSize());
515 CPPUNIT_ASSERT_EQUAL(true, output
.parse());
516 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
517 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
518 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
519 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-2, output
.req
.end
);
520 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
521 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
522 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
523 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
524 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
525 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
526 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
527 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
528 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
529 CPPUNIT_ASSERT_EQUAL(13, output
.req
.v_end
);
530 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
531 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
535 // RELAXED alternative EOL sequence: multi-CR-NL
537 input
.append("GET / HTTP/1.1\r\r\r\n", 18);
538 //printf("TEST: '%s'\n",input.content());
539 output
.reset(input
.content(), input
.contentSize());
540 Config
.onoff
.relaxed_header_parser
= 1;
541 // Being tolerant we can ignore and elide these apparently benign CR
542 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
543 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
544 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
545 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
546 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
547 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
548 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)));
549 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
550 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
551 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
552 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
553 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
554 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_end
);
555 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
556 CPPUNIT_ASSERT_EQUAL(6, output
.req
.v_start
);
557 CPPUNIT_ASSERT_EQUAL(13, output
.req
.v_end
);
558 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
559 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
561 Config
.onoff
.relaxed_header_parser
= 0;
564 // STRICT alternative EOL sequence: multi-CR-NL
566 input
.append("GET / HTTP/1.1\r\r\r\n", 18);
567 //printf("TEST: '%s'\n",input.content());
568 output
.reset(input
.content(), input
.contentSize());
569 // strict mode treats these as several bare-CR in the request line which is explicitly invalid.
570 Config
.onoff
.relaxed_header_parser
= 0;
571 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
572 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
573 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest
, output
.request_parse_status
);
574 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
575 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.end
);
576 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_start
);
577 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_end
);
578 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
579 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
580 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
581 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
582 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
586 // space padded version
588 // RFC 1945 and 2616 specify version is followed by CRLF. No intermediary bytes.
589 // NP: the terminal whitespace is a special case: invalid for even HTTP/0.9 with no version tag
590 input
.append("GET / HTTP/1.1 \n", 16);
591 //printf("TEST: '%s'\n",input.content());
592 output
.reset(input
.content(), input
.contentSize());
593 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
594 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
595 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest
, output
.request_parse_status
);
596 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
597 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
598 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1 \n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
599 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
600 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
601 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
602 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
603 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
604 CPPUNIT_ASSERT_EQUAL(13, output
.req
.u_end
);
605 CPPUNIT_ASSERT_EQUAL(0, memcmp("/ HTTP/1.1", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
606 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
607 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
608 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
612 // incomplete line at various positions
614 input
.append("GET", 3);
615 //printf("TEST: '%s'\n",input.content());
616 output
.reset(input
.content(), input
.contentSize());
617 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
618 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
619 CPPUNIT_ASSERT_EQUAL(Http::scNone
, output
.request_parse_status
);
620 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
621 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.end
);
622 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_start
);
623 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_end
);
624 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(), output
.method_
);
625 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
626 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
627 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
628 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
629 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
632 input
.append("GET ", 4);
633 //printf("TEST: '%s'\n",input.content());
634 output
.reset(input
.content(), input
.contentSize());
635 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
636 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
637 CPPUNIT_ASSERT_EQUAL(Http::scNone
, output
.request_parse_status
);
638 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
639 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.end
);
640 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_start
);
641 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_end
);
642 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(), output
.method_
);
643 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
644 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
645 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
646 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
647 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
650 input
.append("GET / HT", 8);
651 //printf("TEST: '%s'\n",input.content());
652 output
.reset(input
.content(), input
.contentSize());
653 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
654 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
655 CPPUNIT_ASSERT_EQUAL(Http::scNone
, output
.request_parse_status
);
656 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
657 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.end
);
658 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_start
);
659 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_end
);
660 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(), output
.method_
);
661 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
662 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
663 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
664 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
665 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
668 input
.append("GET / HTTP/1.1", 14);
669 //printf("TEST: '%s'\n",input.content());
670 output
.reset(input
.content(), input
.contentSize());
671 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
672 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
673 CPPUNIT_ASSERT_EQUAL(Http::scNone
, output
.request_parse_status
);
674 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
675 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.end
);
676 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_start
);
677 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_end
);
678 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(), output
.method_
);
679 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
680 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
681 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
682 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
683 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
689 testHttp1Parser::testParseRequestLineMethods()
691 // ensure MemPools etc exist
695 Http1::RequestParser output
;
698 // RFC 2616 : . method
700 input
.append(". / HTTP/1.1\n", 13);
701 //printf("TEST: '%s'\n",input.content());
702 output
.reset(input
.content(), input
.contentSize());
703 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
704 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
705 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
706 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
707 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
708 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
709 CPPUNIT_ASSERT_EQUAL(0, memcmp(". / HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
710 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
711 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_end
);
712 CPPUNIT_ASSERT_EQUAL(0, memcmp(".", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
713 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(".", NULL
), output
.method_
);
714 CPPUNIT_ASSERT_EQUAL(2, output
.req
.u_start
);
715 CPPUNIT_ASSERT_EQUAL(2, output
.req
.u_end
);
716 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
717 CPPUNIT_ASSERT_EQUAL(4, output
.req
.v_start
);
718 CPPUNIT_ASSERT_EQUAL(11, output
.req
.v_end
);
719 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
720 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
724 // OPTIONS with * URL
726 input
.append("OPTIONS * HTTP/1.1\n", 19);
727 //printf("TEST: '%s'\n",input.content());
728 output
.reset(input
.content(), input
.contentSize());
729 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
730 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
731 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
732 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
733 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
734 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
735 CPPUNIT_ASSERT_EQUAL(0, memcmp("OPTIONS * HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
736 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
737 CPPUNIT_ASSERT_EQUAL(6, output
.req
.m_end
);
738 CPPUNIT_ASSERT_EQUAL(0, memcmp("OPTIONS", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
739 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_OPTIONS
), output
.method_
);
740 CPPUNIT_ASSERT_EQUAL(8, output
.req
.u_start
);
741 CPPUNIT_ASSERT_EQUAL(8, output
.req
.u_end
);
742 CPPUNIT_ASSERT_EQUAL(0, memcmp("*", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
743 CPPUNIT_ASSERT_EQUAL(10, output
.req
.v_start
);
744 CPPUNIT_ASSERT_EQUAL(17, output
.req
.v_end
);
745 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
746 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
752 input
.append("HELLOWORLD / HTTP/1.1\n", 22);
753 //printf("TEST: '%s'\n",input.content());
754 output
.reset(input
.content(), input
.contentSize());
755 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
756 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
757 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
758 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
759 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
760 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
761 CPPUNIT_ASSERT_EQUAL(0, memcmp("HELLOWORLD / HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
762 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
763 CPPUNIT_ASSERT_EQUAL(9, output
.req
.m_end
);
764 CPPUNIT_ASSERT_EQUAL(0, memcmp("HELLOWORLD", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
765 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod("HELLOWORLD",NULL
), output
.method_
);
766 CPPUNIT_ASSERT_EQUAL(11, output
.req
.u_start
);
767 CPPUNIT_ASSERT_EQUAL(11, output
.req
.u_end
);
768 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
769 CPPUNIT_ASSERT_EQUAL(13, output
.req
.v_start
);
770 CPPUNIT_ASSERT_EQUAL(20, output
.req
.v_end
);
771 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
772 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
778 input
.append("A\n", 2);
779 //printf("TEST: '%s'\n",input.content());
780 output
.reset(input
.content(), input
.contentSize());
781 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
782 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
783 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest
, output
.request_parse_status
);
784 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
785 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
786 CPPUNIT_ASSERT_EQUAL(0, memcmp("A\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
787 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
788 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_end
);
789 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(), output
.method_
);
790 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
791 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
792 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
793 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
794 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
798 input
.append("GET\n", 4);
800 //printf("TEST: '%s'\n",input.content());
801 output
.reset(input
.content(), input
.contentSize());
802 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
803 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
804 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest
, output
.request_parse_status
);
805 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
806 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
807 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
808 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
809 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_end
);
810 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(), output
.method_
);
811 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
812 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
813 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
814 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
815 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
819 // RELAXED space padded method (in strict mode SP is reserved so invalid as a method byte)
821 input
.append(" GET / HTTP/1.1\n", 16);
822 //printf("TEST: '%s'\n",input.content());
823 output
.reset(input
.content(), input
.contentSize());
824 Config
.onoff
.relaxed_header_parser
= 1;
825 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
826 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
827 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
828 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
829 CPPUNIT_ASSERT_EQUAL(1, output
.req
.start
);
830 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
831 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET / HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
832 CPPUNIT_ASSERT_EQUAL(1, output
.req
.m_start
);
833 CPPUNIT_ASSERT_EQUAL(3, output
.req
.m_end
);
834 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
835 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
836 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_start
);
837 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_end
);
838 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
839 CPPUNIT_ASSERT_EQUAL(7, output
.req
.v_start
);
840 CPPUNIT_ASSERT_EQUAL(14, output
.req
.v_end
);
841 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
842 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
844 Config
.onoff
.relaxed_header_parser
= 0;
847 // STRICT space padded method (in strict mode SP is reserved so invalid as a method byte)
849 input
.append(" GET / HTTP/1.1\n", 16);
850 //printf("TEST: '%s'\n",input.content());
851 output
.reset(input
.content(), input
.contentSize());
852 Config
.onoff
.relaxed_header_parser
= 0;
853 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
854 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
855 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest
, output
.request_parse_status
);
856 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
857 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
858 CPPUNIT_ASSERT_EQUAL(0, memcmp(" GET / HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
859 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
860 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_end
);
861 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(), output
.method_
);
862 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
863 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
864 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
865 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
866 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_NONE
,0,0), output
.msgProtocol_
);
870 // tab padded method (NP: tab is not SP so treated as any other binary)
872 input
.append("\tGET / HTTP/1.1\n", 16);
873 //printf("TEST: '%s'\n",input.content());
874 output
.reset(input
.content(), input
.contentSize());
875 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
876 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
877 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
878 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
879 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
880 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
881 CPPUNIT_ASSERT_EQUAL(0, memcmp("\tGET / HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
882 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
883 CPPUNIT_ASSERT_EQUAL(3, output
.req
.m_end
);
884 CPPUNIT_ASSERT_EQUAL(0, memcmp("\tGET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
885 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(&output
.buf
[output
.req
.m_start
],&output
.buf
[output
.req
.m_end
+1]), output
.method_
);
886 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_start
);
887 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_end
);
888 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
889 CPPUNIT_ASSERT_EQUAL(7, output
.req
.v_start
);
890 CPPUNIT_ASSERT_EQUAL(14, output
.req
.v_end
);
891 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
892 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
898 testHttp1Parser::testParseRequestLineInvalid()
900 // ensure MemPools etc exist
904 Http1::RequestParser output
;
907 // no method (but in a form which is ambiguous with HTTP/0.9 simple-request)
909 // XXX: Bug: HTTP/0.9 requires method to be "GET"
910 input
.append("/ HTTP/1.0\n", 11);
911 //printf("TEST: '%s'\n",input.content());
912 output
.reset(input
.content(), input
.contentSize());
913 CPPUNIT_ASSERT_EQUAL(true, output
.parse());
914 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
915 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
916 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
917 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
918 CPPUNIT_ASSERT_EQUAL(0, memcmp("/ HTTP/1.0\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
919 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
920 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_end
);
921 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
922 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod("/",NULL
), output
.method_
);
923 CPPUNIT_ASSERT_EQUAL(2, output
.req
.u_start
);
924 CPPUNIT_ASSERT_EQUAL(9, output
.req
.u_end
);
925 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.0", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
926 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
927 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
928 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,0,9), output
.msgProtocol_
);
932 // RELAXED no method (an invalid format)
934 input
.append(" / HTTP/1.0\n", 12);
935 //printf("TEST: '%s'\n",input.content());
936 output
.reset(input
.content(), input
.contentSize());
937 // BUG: When tolerantly ignoring SP prefix this case becomes ambiguous with HTTP/0.9 simple-request)
938 Config
.onoff
.relaxed_header_parser
= 1;
939 CPPUNIT_ASSERT_EQUAL(true, output
.parse());
940 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
941 // CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_NEW, output.completedState_);
942 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
943 CPPUNIT_ASSERT_EQUAL(1, output
.req
.start
);
944 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
945 CPPUNIT_ASSERT_EQUAL(0, memcmp("/ HTTP/1.0\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
946 CPPUNIT_ASSERT_EQUAL(1, output
.req
.m_start
);
947 CPPUNIT_ASSERT_EQUAL(1, output
.req
.m_end
);
948 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
949 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod("/",NULL
), output
.method_
);
950 CPPUNIT_ASSERT_EQUAL(3, output
.req
.u_start
);
951 CPPUNIT_ASSERT_EQUAL(10, output
.req
.u_end
);
952 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.0", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
953 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
954 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
955 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,0,9), output
.msgProtocol_
);
957 Config
.onoff
.relaxed_header_parser
= 0;
960 // STRICT no method (an invalid format)
962 input
.append(" / HTTP/1.0\n", 12);
963 //printf("TEST: '%s'\n",input.content());
964 output
.reset(input
.content(), input
.contentSize());
965 // When tolerantly ignoring SP prefix this case becomes ambiguous with HTTP/0.9 simple-request)
966 Config
.onoff
.relaxed_header_parser
= 0;
967 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
968 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
969 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest
, output
.request_parse_status
);
970 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
971 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
972 CPPUNIT_ASSERT_EQUAL(0, memcmp(" / HTTP/1.0\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
973 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
974 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_end
);
975 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(), output
.method_
);
976 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
977 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
978 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
979 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
980 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_NONE
,0,0), output
.msgProtocol_
);
984 // binary code in method (strange but ...)
986 input
.append("GET\x0B / HTTP/1.1\n", 16);
987 //printf("TEST: %d-%d/%d '%.*s'\n", output.req.start, output.req.end, input.contentSize(), 16, input.content());
988 output
.reset(input
.content(), input
.contentSize());
989 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
990 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
991 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
992 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
993 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
994 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
995 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\x0B / HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
996 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
997 CPPUNIT_ASSERT_EQUAL(3, output
.req
.m_end
);
998 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\x0B", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
999 // CPPUNIT_ASSERT_EQUAL(HttpRequestMethod("GET\0x0B",NULL), output.method_);
1000 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_start
);
1001 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_end
);
1002 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
1003 CPPUNIT_ASSERT_EQUAL(7, output
.req
.v_start
);
1004 CPPUNIT_ASSERT_EQUAL(14, output
.req
.v_end
);
1005 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
1006 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
1012 // RFC 2616 sec 5.1 prohibits CR other than in terminator.
1013 input
.append("GET\r / HTTP/1.1\r\n", 16);
1014 //printf("TEST: '%s'\n",input.content());
1015 output
.reset(input
.content(), input
.contentSize());
1016 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
1017 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
1018 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest
, output
.request_parse_status
);
1019 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
1020 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.end
);
1021 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_start
);
1022 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_end
);
1023 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(), output
.method_
);
1024 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
1025 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
1026 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
1027 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
1028 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
1032 // binary code NUL! in method (strange but ...)
1034 input
.append("GET\0 / HTTP/1.1\n", 16);
1035 //printf("TEST: %d-%d/%d '%.*s'\n", output.req.start, output.req.end, input.contentSize(), 16, input.content());
1036 output
.reset(input
.content(), input
.contentSize());
1037 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
1038 CPPUNIT_ASSERT_EQUAL(false, output
.isDone());
1039 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, output
.completedState_
);
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
);
1043 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\0 / HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
1044 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
1045 CPPUNIT_ASSERT_EQUAL(3, output
.req
.m_end
);
1046 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\0", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
1047 // CPPUNIT_ASSERT_EQUAL(HttpRequestMethod("GET\0",NULL), output.method_);
1048 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_start
);
1049 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_end
);
1050 CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
1051 CPPUNIT_ASSERT_EQUAL(7, output
.req
.v_start
);
1052 CPPUNIT_ASSERT_EQUAL(14, output
.req
.v_end
);
1053 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.v_start
],(output
.req
.v_end
-output
.req
.v_start
+1)));
1054 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,1,1), output
.msgProtocol_
);
1058 // no URL (grammer otherwise correct)
1060 input
.append("GET HTTP/1.1\n", 14);
1061 //printf("TEST: '%s'\n",input.content());
1062 output
.reset(input
.content(), input
.contentSize());
1063 CPPUNIT_ASSERT_EQUAL(true, output
.parse());
1064 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
1065 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
1066 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
1067 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
1068 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
1069 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
1070 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
1071 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
1072 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
1073 CPPUNIT_ASSERT_EQUAL(5, output
.req
.u_start
);
1074 CPPUNIT_ASSERT_EQUAL(12, output
.req
.u_end
);
1075 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
1076 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
1077 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
1078 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,0,9), output
.msgProtocol_
);
1082 // no URL (grammer invalid, ambiguous with RFC 1945 HTTP/0.9 simple-request)
1084 input
.append("GET HTTP/1.1\n", 13);
1085 //printf("TEST: '%s'\n",input.content());
1086 output
.reset(input
.content(), input
.contentSize());
1087 CPPUNIT_ASSERT_EQUAL(true, output
.parse());
1088 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
1089 CPPUNIT_ASSERT_EQUAL(Http::scOkay
, output
.request_parse_status
);
1090 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
1091 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
1092 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET HTTP/1.1\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
1093 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
1094 CPPUNIT_ASSERT_EQUAL(2, output
.req
.m_end
);
1095 CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
1096 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_GET
), output
.method_
);
1097 CPPUNIT_ASSERT_EQUAL(4, output
.req
.u_start
);
1098 CPPUNIT_ASSERT_EQUAL(11, output
.req
.u_end
);
1099 CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output
.buf
[output
.req
.u_start
],(output
.req
.u_end
-output
.req
.u_start
+1)));
1100 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
1101 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
1102 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(AnyP::PROTO_HTTP
,0,9), output
.msgProtocol_
);
1108 input
.append("\xB\xC\xE\xF\n", 5);
1109 //printf("TEST: binary-line\n");
1110 output
.reset(input
.content(), input
.contentSize());
1111 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
1112 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
1113 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest
, output
.request_parse_status
);
1114 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
1115 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
1116 CPPUNIT_ASSERT_EQUAL(0, memcmp("\xB\xC\xE\xF\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
1117 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
1118 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_end
);
1119 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(), output
.method_
);
1120 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
1121 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
1122 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
1123 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
1124 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
1128 // mixed whitespace line
1130 // We accept non-space binary bytes for method so first \t shows up as that
1131 // but remaining space and tabs are skipped searching for URI-start
1132 input
.append("\t \t \t\n", 6);
1133 //printf("TEST: mixed whitespace\n");
1134 output
.reset(input
.content(), input
.contentSize());
1135 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
1136 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
1137 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest
, output
.request_parse_status
);
1138 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
1139 CPPUNIT_ASSERT_EQUAL((int)input
.contentSize()-1, output
.req
.end
);
1140 CPPUNIT_ASSERT_EQUAL(0, memcmp("\t \t \t\n", &output
.buf
[output
.req
.start
],(output
.req
.end
-output
.req
.start
+1)));
1141 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_start
);
1142 CPPUNIT_ASSERT_EQUAL(0, output
.req
.m_end
);
1143 CPPUNIT_ASSERT_EQUAL(0, memcmp("\t", &output
.buf
[output
.req
.m_start
],(output
.req
.m_end
-output
.req
.m_start
+1)));
1144 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(&output
.buf
[output
.req
.m_start
],&output
.buf
[output
.req
.m_end
+1]), output
.method_
);
1145 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
1146 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
1147 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
1148 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
1149 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
1153 // mixed whitespace line with CR middle
1155 // CR aborts on sight, so even initial \t method is not marked as above
1156 // (not when parsing clean with whole line available anyway)
1157 input
.append("\t \r \n", 6);
1158 //printf("TEST: mixed whitespace with CR\n");
1159 output
.reset(input
.content(), input
.contentSize());
1160 CPPUNIT_ASSERT_EQUAL(false, output
.parse());
1161 CPPUNIT_ASSERT_EQUAL(true, output
.isDone());
1162 CPPUNIT_ASSERT_EQUAL(Http::scBadRequest
, output
.request_parse_status
);
1163 CPPUNIT_ASSERT_EQUAL(0, output
.req
.start
);
1164 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.end
);
1165 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_start
);
1166 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.m_end
);
1167 CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(), output
.method_
);
1168 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_start
);
1169 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.u_end
);
1170 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_start
);
1171 CPPUNIT_ASSERT_EQUAL(-1, output
.req
.v_end
);
1172 CPPUNIT_ASSERT_EQUAL(AnyP::ProtocolVersion(), output
.msgProtocol_
);
1178 testHttp1Parser::testDripFeed()
1180 // Simulate a client drip-feeding Squid a few bytes at a time.
1181 // extend the size of the buffer from 0 bytes to full request length
1182 // calling the parser repeatedly as visible data grows.
1185 mb
.init(1024, 1024);
1187 int garbageEnd
= mb
.contentSize();
1188 mb
.append("GET http://example.com/ HTTP/1.1\r\n", 34);
1189 int reqLineEnd
= mb
.contentSize();
1190 mb
.append("Host: example.com\r\n\r\n.", 22);
1192 Http1::RequestParser
hp(mb
.content(), 0);
1194 // only relaxed parser accepts the garbage whitespace
1195 Config
.onoff
.relaxed_header_parser
= 1;
1197 for (; hp
.bufsiz
<= mb
.contentSize(); ++hp
.bufsiz
) {
1198 bool parseResult
= hp
.parse();
1200 #if WHEN_TEST_DEBUG_IS_NEEDED
1201 printf("%d/%d :: %d, %d, %d '%c'\n", hp
.bufsiz
, mb
.contentSize(),
1202 garbageEnd
, reqLineEnd
, parseResult
,
1203 mb
.content()[hp
.bufsiz
]);
1206 // before end of garbage found its a moving offset.
1207 if (hp
.bufsiz
< garbageEnd
) {
1208 CPPUNIT_ASSERT_EQUAL(hp
.bufsiz
, (int)hp
.parseOffset_
);
1209 CPPUNIT_ASSERT_EQUAL(false, hp
.isDone());
1213 // before request line found, parse announces incomplete
1214 if (hp
.bufsiz
< reqLineEnd
) {
1215 CPPUNIT_ASSERT_EQUAL(garbageEnd
, (int)hp
.parseOffset_
);
1216 CPPUNIT_ASSERT_EQUAL(false, parseResult
);
1217 CPPUNIT_ASSERT_EQUAL(false, hp
.isDone());
1218 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_NEW
, hp
.completedState_
);
1222 // before request headers entirely found, parse announces incomplete
1223 if (hp
.bufsiz
< mb
.contentSize()-1) {
1224 CPPUNIT_ASSERT_EQUAL(reqLineEnd
, (int)hp
.parseOffset_
);
1225 CPPUNIT_ASSERT_EQUAL(false, parseResult
);
1226 CPPUNIT_ASSERT_EQUAL(false, hp
.isDone());
1227 // TODO: add all the other usual tests for request-line details
1228 CPPUNIT_ASSERT_EQUAL((uint8_t)HTTP_PARSE_FIRST
, hp
.completedState_
);
1232 // once request line is found (AND the following \n) current parser announces success
1233 CPPUNIT_ASSERT_EQUAL(reqLineEnd
, (int)hp
.parseOffset_
);
1234 CPPUNIT_ASSERT_EQUAL(true, parseResult
);
1235 CPPUNIT_ASSERT_EQUAL(true, hp
.isDone());