Add REQUEST_BODY
[mistral.git] / http11_parser.c
bloba14238e0e0c50603ec9a820ba56d18e5e37de571
2 #line 1 "http11_parser.rl"
3 /**
5 * Copyright (c) 2010, Zed A. Shaw and Mongrel2 Project Contributors.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * * Neither the name of the Mongrel2 Project, Zed A. Shaw, nor the names
20 * of its contributors may be used to endorse or promote products
21 * derived from this software without specific prior written
22 * permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #include "http11_parser.h"
38 #include <stdio.h>
39 #include <assert.h>
40 #include <stdlib.h>
41 #include <ctype.h>
42 #include <string.h>
44 #define LEN(AT, FPC) (FPC - buffer - parser->AT)
45 #define MARK(M,FPC) (parser->M = (FPC) - buffer)
46 #define PTR_TO(F) (buffer + parser->F)
48 /** Machine **/
51 #line 161 "http11_parser.rl"
54 /** Data **/
56 #line 57 "http11_parser.c"
57 static const char _http_parser_actions[] = {
58 0, 1, 0, 1, 1, 1, 2, 1,
59 3, 1, 4, 1, 5, 1, 6, 1,
60 7, 1, 8, 1, 9, 1, 10, 1,
61 12, 2, 0, 5, 2, 3, 4, 2,
62 7, 9, 2, 11, 9, 3, 10, 11,
66 static const short _http_parser_key_offsets[] = {
67 0, 0, 8, 17, 20, 22, 23, 24,
68 25, 26, 27, 28, 29, 31, 33, 50,
69 51, 67, 70, 72, 73, 82, 91, 97,
70 103, 114, 120, 126, 136, 142, 148, 157,
71 166, 172, 178, 179, 180, 181, 182, 191,
72 197, 203, 212, 221, 230, 239, 248, 257,
73 266, 275, 284, 293, 302, 311, 320, 329,
74 338, 347, 356, 365, 366
77 static const char _http_parser_trans_keys[] = {
78 36, 95, 45, 46, 48, 57, 65, 90,
79 32, 36, 95, 45, 46, 48, 57, 65,
80 90, 42, 47, 104, 32, 35, 72, 84,
81 84, 80, 47, 49, 46, 48, 49, 10,
82 13, 10, 13, 33, 124, 126, 35, 39,
83 42, 43, 45, 46, 48, 57, 65, 90,
84 94, 122, 10, 33, 58, 124, 126, 35,
85 39, 42, 43, 45, 46, 48, 57, 65,
86 90, 94, 122, 10, 13, 32, 10, 13,
87 10, 32, 37, 60, 62, 127, 0, 31,
88 34, 35, 32, 37, 60, 62, 127, 0,
89 31, 34, 35, 48, 57, 65, 70, 97,
90 102, 48, 57, 65, 70, 97, 102, 32,
91 34, 35, 37, 59, 60, 62, 63, 127,
92 0, 31, 48, 57, 65, 70, 97, 102,
93 48, 57, 65, 70, 97, 102, 32, 34,
94 35, 37, 60, 62, 63, 127, 0, 31,
95 48, 57, 65, 70, 97, 102, 48, 57,
96 65, 70, 97, 102, 32, 34, 35, 37,
97 60, 62, 127, 0, 31, 32, 34, 35,
98 37, 60, 62, 127, 0, 31, 48, 57,
99 65, 70, 97, 102, 48, 57, 65, 70,
100 97, 102, 116, 116, 112, 58, 32, 34,
101 35, 37, 60, 62, 127, 0, 31, 48,
102 57, 65, 70, 97, 102, 48, 57, 65,
103 70, 97, 102, 32, 36, 95, 45, 46,
104 48, 57, 65, 90, 32, 36, 95, 45,
105 46, 48, 57, 65, 90, 32, 36, 95,
106 45, 46, 48, 57, 65, 90, 32, 36,
107 95, 45, 46, 48, 57, 65, 90, 32,
108 36, 95, 45, 46, 48, 57, 65, 90,
109 32, 36, 95, 45, 46, 48, 57, 65,
110 90, 32, 36, 95, 45, 46, 48, 57,
111 65, 90, 32, 36, 95, 45, 46, 48,
112 57, 65, 90, 32, 36, 95, 45, 46,
113 48, 57, 65, 90, 32, 36, 95, 45,
114 46, 48, 57, 65, 90, 32, 36, 95,
115 45, 46, 48, 57, 65, 90, 32, 36,
116 95, 45, 46, 48, 57, 65, 90, 32,
117 36, 95, 45, 46, 48, 57, 65, 90,
118 32, 36, 95, 45, 46, 48, 57, 65,
119 90, 32, 36, 95, 45, 46, 48, 57,
120 65, 90, 32, 36, 95, 45, 46, 48,
121 57, 65, 90, 32, 36, 95, 45, 46,
122 48, 57, 65, 90, 32, 36, 95, 45,
123 46, 48, 57, 65, 90, 32, 0
126 static const char _http_parser_single_lengths[] = {
127 0, 2, 3, 3, 2, 1, 1, 1,
128 1, 1, 1, 1, 0, 2, 5, 1,
129 4, 3, 2, 1, 5, 5, 0, 0,
130 9, 0, 0, 8, 0, 0, 7, 7,
131 0, 0, 1, 1, 1, 1, 7, 0,
132 0, 3, 3, 3, 3, 3, 3, 3,
133 3, 3, 3, 3, 3, 3, 3, 3,
134 3, 3, 3, 1, 0
137 static const char _http_parser_range_lengths[] = {
138 0, 3, 3, 0, 0, 0, 0, 0,
139 0, 0, 0, 0, 1, 0, 6, 0,
140 6, 0, 0, 0, 2, 2, 3, 3,
141 1, 3, 3, 1, 3, 3, 1, 1,
142 3, 3, 0, 0, 0, 0, 1, 3,
143 3, 3, 3, 3, 3, 3, 3, 3,
144 3, 3, 3, 3, 3, 3, 3, 3,
145 3, 3, 3, 0, 0
148 static const short _http_parser_index_offsets[] = {
149 0, 0, 6, 13, 17, 20, 22, 24,
150 26, 28, 30, 32, 34, 36, 39, 51,
151 53, 64, 68, 71, 73, 81, 89, 93,
152 97, 108, 112, 116, 126, 130, 134, 143,
153 152, 156, 160, 162, 164, 166, 168, 177,
154 181, 185, 192, 199, 206, 213, 220, 227,
155 234, 241, 248, 255, 262, 269, 276, 283,
156 290, 297, 304, 311, 313
159 static const char _http_parser_indicies[] = {
160 0, 0, 0, 0, 0, 1, 2, 3,
161 3, 3, 3, 3, 1, 4, 5, 6,
162 1, 7, 8, 1, 9, 1, 10, 1,
163 11, 1, 12, 1, 13, 1, 14, 1,
164 15, 1, 16, 1, 17, 18, 1, 19,
165 20, 21, 21, 21, 21, 21, 21, 21,
166 21, 21, 1, 19, 1, 22, 23, 22,
167 22, 22, 22, 22, 22, 22, 22, 1,
168 25, 26, 27, 24, 29, 30, 28, 31,
169 1, 33, 34, 1, 1, 1, 1, 1,
170 32, 36, 37, 1, 1, 1, 1, 1,
171 35, 38, 38, 38, 1, 35, 35, 35,
172 1, 40, 1, 41, 42, 43, 1, 1,
173 44, 1, 1, 39, 45, 45, 45, 1,
174 39, 39, 39, 1, 7, 1, 8, 47,
175 1, 1, 48, 1, 1, 46, 49, 49,
176 49, 1, 46, 46, 46, 1, 51, 1,
177 52, 53, 1, 1, 1, 1, 50, 55,
178 1, 56, 57, 1, 1, 1, 1, 54,
179 58, 58, 58, 1, 54, 54, 54, 1,
180 59, 1, 60, 1, 61, 1, 62, 1,
181 7, 1, 8, 63, 1, 1, 1, 1,
182 62, 64, 64, 64, 1, 62, 62, 62,
183 1, 2, 65, 65, 65, 65, 65, 1,
184 2, 66, 66, 66, 66, 66, 1, 2,
185 67, 67, 67, 67, 67, 1, 2, 68,
186 68, 68, 68, 68, 1, 2, 69, 69,
187 69, 69, 69, 1, 2, 70, 70, 70,
188 70, 70, 1, 2, 71, 71, 71, 71,
189 71, 1, 2, 72, 72, 72, 72, 72,
190 1, 2, 73, 73, 73, 73, 73, 1,
191 2, 74, 74, 74, 74, 74, 1, 2,
192 75, 75, 75, 75, 75, 1, 2, 76,
193 76, 76, 76, 76, 1, 2, 77, 77,
194 77, 77, 77, 1, 2, 78, 78, 78,
195 78, 78, 1, 2, 79, 79, 79, 79,
196 79, 1, 2, 80, 80, 80, 80, 80,
197 1, 2, 81, 81, 81, 81, 81, 1,
198 2, 82, 82, 82, 82, 82, 1, 2,
199 1, 1, 0
202 static const char _http_parser_trans_targs[] = {
203 2, 0, 3, 41, 4, 24, 34, 5,
204 20, 6, 7, 8, 9, 10, 11, 12,
205 13, 14, 19, 60, 15, 16, 16, 17,
206 18, 14, 19, 17, 18, 14, 19, 14,
207 21, 5, 22, 21, 5, 22, 23, 24,
208 5, 20, 25, 27, 30, 26, 27, 28,
209 30, 29, 31, 5, 20, 32, 31, 5,
210 20, 32, 33, 35, 36, 37, 38, 39,
211 40, 42, 43, 44, 45, 46, 47, 48,
212 49, 50, 51, 52, 53, 54, 55, 56,
213 57, 58, 59
216 static const char _http_parser_trans_actions[] = {
217 1, 0, 17, 0, 1, 1, 1, 19,
218 19, 1, 0, 0, 0, 0, 0, 0,
219 0, 13, 13, 23, 0, 3, 0, 5,
220 7, 28, 28, 7, 0, 9, 9, 0,
221 1, 25, 1, 0, 11, 0, 0, 0,
222 31, 31, 0, 15, 15, 0, 0, 0,
223 0, 0, 21, 37, 37, 21, 0, 34,
224 34, 0, 0, 0, 0, 0, 0, 0,
225 0, 0, 0, 0, 0, 0, 0, 0,
226 0, 0, 0, 0, 0, 0, 0, 0,
227 0, 0, 0
230 static const int http_parser_start = 1;
231 static const int http_parser_first_final = 60;
232 static const int http_parser_error = 0;
234 static const int http_parser_en_main = 1;
237 #line 165 "http11_parser.rl"
239 static int apply_element(http_parser *parser, int type, const char *begin, const char *end, int max_length)
241 int len = (int)(end-begin);
242 if(len > max_length) {
243 return(0);
245 if(parser->on_element)
246 parser->on_element(parser->data, type, begin, len);
247 return(1);
252 int http_parser_init(http_parser *parser) {
253 int cs = 0;
255 #line 256 "http11_parser.c"
257 cs = http_parser_start;
260 #line 182 "http11_parser.rl"
261 parser->cs = cs;
262 parser->body_start = 0;
263 parser->content_len = 0;
264 parser->mark = 0;
265 parser->nread = 0;
266 parser->field_len = 0;
267 parser->field_start = 0;
269 return(1);
272 /** exec **/
273 size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len, size_t off)
275 if(len == 0) return 0;
277 const char *p, *pe;
278 int cs = parser->cs;
280 assert(off <= len && "offset past end of buffer");
282 p = buffer+off;
283 pe = buffer+len;
285 assert(pe - p == (int)len - (int)off && "pointers aren't same distance");
288 #line 289 "http11_parser.c"
290 int _klen;
291 unsigned int _trans;
292 const char *_acts;
293 unsigned int _nacts;
294 const char *_keys;
296 if ( p == pe )
297 goto _test_eof;
298 if ( cs == 0 )
299 goto _out;
300 _resume:
301 _keys = _http_parser_trans_keys + _http_parser_key_offsets[cs];
302 _trans = _http_parser_index_offsets[cs];
304 _klen = _http_parser_single_lengths[cs];
305 if ( _klen > 0 ) {
306 const char *_lower = _keys;
307 const char *_mid;
308 const char *_upper = _keys + _klen - 1;
309 while (1) {
310 if ( _upper < _lower )
311 break;
313 _mid = _lower + ((_upper-_lower) >> 1);
314 if ( (*p) < *_mid )
315 _upper = _mid - 1;
316 else if ( (*p) > *_mid )
317 _lower = _mid + 1;
318 else {
319 _trans += (_mid - _keys);
320 goto _match;
323 _keys += _klen;
324 _trans += _klen;
327 _klen = _http_parser_range_lengths[cs];
328 if ( _klen > 0 ) {
329 const char *_lower = _keys;
330 const char *_mid;
331 const char *_upper = _keys + (_klen<<1) - 2;
332 while (1) {
333 if ( _upper < _lower )
334 break;
336 _mid = _lower + (((_upper-_lower) >> 1) & ~1);
337 if ( (*p) < _mid[0] )
338 _upper = _mid - 2;
339 else if ( (*p) > _mid[1] )
340 _lower = _mid + 2;
341 else {
342 _trans += ((_mid - _keys)>>1);
343 goto _match;
346 _trans += _klen;
349 _match:
350 _trans = _http_parser_indicies[_trans];
351 cs = _http_parser_trans_targs[_trans];
353 if ( _http_parser_trans_actions[_trans] == 0 )
354 goto _again;
356 _acts = _http_parser_actions + _http_parser_trans_actions[_trans];
357 _nacts = (unsigned int) *_acts++;
358 while ( _nacts-- > 0 )
360 switch ( *_acts++ )
362 case 0:
363 #line 52 "http11_parser.rl"
364 {MARK(mark, p); }
365 break;
366 case 1:
367 #line 55 "http11_parser.rl"
368 { MARK(field_start, p); }
369 break;
370 case 2:
371 #line 56 "http11_parser.rl"
373 parser->field_len = LEN(field_start, p);
375 break;
376 case 3:
377 #line 60 "http11_parser.rl"
378 { MARK(mark, p); }
379 break;
380 case 4:
381 #line 62 "http11_parser.rl"
383 if(parser->http_field != NULL) {
384 parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
387 break;
388 case 5:
389 #line 73 "http11_parser.rl"
391 if(!apply_element(parser, FRAGMENT, PTR_TO(mark), p, 10*1024))
392 {p++; goto _out; }
394 break;
395 case 6:
396 #line 78 "http11_parser.rl"
398 if(!apply_element(parser, HTTP_VERSION, PTR_TO(mark), p, 10))
399 {p++; goto _out; }
401 break;
402 case 7:
403 #line 83 "http11_parser.rl"
405 if(!apply_element(parser, REQUEST_PATH, PTR_TO(mark), p, 1024))
406 {p++; goto _out; }
408 break;
409 case 8:
410 #line 88 "http11_parser.rl"
412 if(!apply_element(parser, REQUEST_METHOD, PTR_TO(mark), p, 1024))
413 {p++; goto _out; }
415 break;
416 case 9:
417 #line 93 "http11_parser.rl"
419 if(!apply_element(parser, REQUEST_URI, PTR_TO(mark), p, 12*1024))
420 {p++; goto _out; }
422 break;
423 case 10:
424 #line 98 "http11_parser.rl"
425 {MARK(query_start, p); }
426 break;
427 case 11:
428 #line 100 "http11_parser.rl"
430 if(!apply_element(parser, QUERY_STRING, PTR_TO(query_start), p, 10*1024))
431 {p++; goto _out; }
433 break;
434 case 12:
435 #line 105 "http11_parser.rl"
437 parser->body_start = p - buffer + 1;
438 if(parser->header_done != NULL)
439 parser->header_done(parser->data, REQUEST_BODY, p + 1, pe - p - 1);
440 {p++; goto _out; }
442 break;
443 #line 444 "http11_parser.c"
447 _again:
448 if ( cs == 0 )
449 goto _out;
450 if ( ++p != pe )
451 goto _resume;
452 _test_eof: {}
453 _out: {}
456 #line 209 "http11_parser.rl"
458 assert(p <= pe && "Buffer overflow after parsing.");
460 if (!http_parser_has_error(parser)) {
461 parser->cs = cs;
464 parser->nread += p - (buffer + off);
466 assert(parser->nread <= len && "nread longer than length");
467 assert(parser->body_start <= len && "body starts after buffer end");
468 assert(parser->mark < len && "mark is after buffer end");
469 assert(parser->field_len <= len && "field has length longer than whole buffer");
470 assert(parser->field_start < len && "field starts after buffer end");
472 return(parser->nread);
475 int http_parser_finish(http_parser *parser)
477 if (http_parser_has_error(parser) ) {
478 return -1;
479 } else if (http_parser_is_finished(parser) ) {
480 return 1;
481 } else {
482 return 0;
486 int http_parser_has_error(http_parser *parser) {
487 return parser->cs == http_parser_error;
490 int http_parser_is_finished(http_parser *parser) {
491 return parser->cs >= http_parser_first_final;