comparison src/http/ngx_http_parse.c @ 1:d220029ac7f3

nginx-0.0.1-2002-08-15-21:20:26 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 15 Aug 2002 17:20:26 +0000
parents
children b5481d6fbbd4
comparison
equal deleted inserted replaced
0:4eff17414a43 1:d220029ac7f3
1
2 #include <ngx_config.h>
3 #include <ngx_http.h>
4
5 int ngx_read_http_request_line(ngx_http_request_t *r)
6 {
7 char ch;
8 char *buff = r->buff->buff;
9 char *p = r->buff->pos;
10 enum {
11 rl_start = 0,
12 rl_space_after_method,
13 rl_spaces_before_uri,
14 rl_after_slash_in_uri,
15 rl_check_uri,
16 rl_uri,
17 rl_http_09,
18 rl_http_version,
19 rl_first_major_digit,
20 rl_major_digit,
21 rl_first_minor_digit,
22 rl_minor_digit,
23 rl_almost_done,
24 rl_done
25 } state = r->state;
26
27 while (p < r->buff->last && state < rl_done) {
28 ch = *p++;
29
30 /*
31 printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
32 state, p, r->buff->last, ch, p);
33 */
34
35 /* GCC complie it as jump table */
36
37 switch (state) {
38
39 /* HTTP methods: GET, HEAD, POST */
40 case rl_start:
41 switch (ch) {
42 case 'G':
43 if (p + 1 >= r->buff->last)
44 return 0;
45
46 if (*p != 'E' || *(p + 1) != 'T')
47 return NGX_HTTP_INVALID_METHOD;
48
49 r->method = NGX_HTTP_GET;
50 p += 2;
51 break;
52
53 case 'H':
54 if (p + 2 >= r->buff->last)
55 return 0;
56
57 if (*p != 'E' || *(p + 1) != 'A' || *(p + 2) != 'D')
58 return NGX_HTTP_INVALID_METHOD;
59
60 r->method = NGX_HTTP_HEAD;
61 p += 3;
62 break;
63
64 case 'P':
65 if (p + 2 >= r->buff->last)
66 return 0;
67
68 if (*p != 'O' || *(p + 1) != 'S' || *(p + 2) != 'T')
69 return NGX_HTTP_INVALID_METHOD;
70
71 r->method = NGX_HTTP_POST;
72 p += 3;
73 break;
74
75 default:
76 return NGX_HTTP_INVALID_METHOD;
77 }
78
79 state = rl_space_after_method;
80 break;
81
82 /* single space after method */
83 case rl_space_after_method:
84 switch (ch) {
85 case ' ':
86 state = rl_spaces_before_uri;
87 break;
88 default:
89 return NGX_HTTP_INVALID_METHOD;
90 }
91 break;
92
93 /* space* before URI */
94 case rl_spaces_before_uri:
95 switch (ch) {
96 case '/':
97 r->uri_start = p - 1;
98 state = rl_after_slash_in_uri;
99 break;
100 case ' ':
101 break;
102 default:
103 r->unusual_uri = 1;
104 r->uri_start = p - 1;
105 state = rl_uri;
106 break;
107 }
108 break;
109
110 /* check dot after slash */
111 case rl_after_slash_in_uri:
112 switch (ch) {
113 case CR:
114 r->uri_end = p - 1;
115 r->http_minor = 9;
116 state = rl_almost_done;
117 break;
118 case LF:
119 r->uri_end = p - 1;
120 r->http_minor = 9;
121 state = rl_done;
122 break;
123 case ' ':
124 r->uri_end = p - 1;
125 state = rl_http_09;
126 break;
127 case '.':
128 r->complex_uri = 1;
129 state = rl_uri;
130 break;
131 case '/':
132 r->complex_uri = 1;
133 state = rl_uri;
134 break;
135 case '?':
136 r->args_start = p;
137 state = rl_uri;
138 break;
139 default:
140 state = rl_check_uri;
141 break;
142 }
143 break;
144
145 /* check slash in URI */
146 case rl_check_uri:
147 switch (ch) {
148 case CR:
149 r->uri_end = p - 1;
150 r->http_minor = 9;
151 state = rl_almost_done;
152 break;
153 case LF:
154 r->uri_end = p - 1;
155 r->http_minor = 9;
156 state = rl_done;
157 break;
158 case ' ':
159 r->uri_end = p - 1;
160 state = rl_http_09;
161 break;
162 case '.':
163 r->uri_ext = p;
164 break;
165 case '/':
166 r->uri_ext = NULL;
167 state = rl_after_slash_in_uri;
168 break;
169 case '?':
170 r->args_start = p;
171 state = rl_uri;
172 break;
173 }
174 break;
175
176 /* URI */
177 case rl_uri:
178 switch (ch) {
179 case CR:
180 r->uri_end = p - 1;
181 r->http_minor = 9;
182 state = rl_almost_done;
183 break;
184 case LF:
185 r->uri_end = p - 1;
186 r->http_minor = 9;
187 state = rl_done;
188 break;
189 case ' ':
190 r->uri_end = p - 1;
191 state = rl_http_09;
192 break;
193 }
194 break;
195
196 /* space+ after URI */
197 case rl_http_09:
198 switch (ch) {
199 case ' ':
200 break;
201 case CR:
202 r->http_minor = 9;
203 state = rl_almost_done;
204 break;
205 case LF:
206 r->http_minor = 9;
207 state = rl_done;
208 break;
209 case 'H':
210 state = rl_http_version;
211 break;
212 default:
213 return NGX_HTTP_INVALID_REQUEST;
214 }
215 break;
216
217 /* TTP/ */
218 case rl_http_version:
219 if (p + 2 >= r->buff->last) {
220 r->state = rl_http_version;
221 r->buff->pos = p - 1;
222 return 0;
223 }
224
225 if (ch != 'T' || *p != 'T' || *(p + 1) != 'P' || *(p + 2) != '/')
226 return NGX_HTTP_INVALID_REQUEST;
227
228 p += 3;
229 state = rl_first_major_digit;
230 break;
231
232 /* first digit of major HTTP version */
233 case rl_first_major_digit:
234 if (ch < '1' || ch > '9')
235 return NGX_HTTP_INVALID_REQUEST;
236
237 r->http_major = ch - '0';
238 state = rl_major_digit;
239 break;
240
241 /* major HTTP version or dot */
242 case rl_major_digit:
243 if (ch == '.') {
244 state = rl_first_minor_digit;
245 break;
246 }
247
248 if (ch < '0' || ch > '9')
249 return NGX_HTTP_INVALID_REQUEST;
250
251 r->http_major = r->http_major * 10 + ch - '0';
252 break;
253
254 /* first digit of minor HTTP version */
255 case rl_first_minor_digit:
256 if (ch < '0' || ch > '9')
257 return NGX_HTTP_INVALID_REQUEST;
258
259 r->http_minor = ch - '0';
260
261 state = rl_minor_digit;
262 break;
263
264 /* minor HTTP version or end of request line */
265 case rl_minor_digit:
266 if (ch == CR) {
267 state = rl_almost_done;
268 break;
269 }
270
271 if (ch == LF) {
272 state = rl_done;
273 break;
274 }
275
276 if (ch < '0' || ch > '9')
277 return NGX_HTTP_INVALID_REQUEST;
278
279 r->http_minor = r->http_minor * 10 + ch - '0';
280 break;
281
282 /* end of request line */
283 case rl_almost_done:
284 switch (ch) {
285 case LF:
286 state = rl_done;
287 break;
288 default:
289 return NGX_HTTP_INVALID_METHOD;
290 }
291 break;
292 }
293 }
294
295 r->buff->pos = p;
296
297 if (state == rl_done) {
298 r->http_version = r->http_major * 1000 + r->http_minor;
299 r->state = rl_start;
300 return 1;
301 } else {
302 r->state = state;
303 return 0;
304 }
305 }
306
307 int ngx_read_http_header_line(ngx_http_request_t *r)
308 {
309 char c, ch;
310 char *buff = r->buff->buff;
311 char *p = r->buff->pos;
312 enum {
313 hl_start = 0,
314 hl_name,
315 hl_space_before_value,
316 hl_value,
317 hl_space_after_value,
318 hl_almost_done,
319 header_almost_done,
320 hl_done,
321 header_done
322 } state = r->state;
323
324 while (p < r->buff->last && state < hl_done) {
325 ch = *p++;
326
327 /*
328 printf("\nstate: %d, pos: %x, end: %x, char: '%c' buf: %s",
329 state, p, r->buff->last, ch, p);
330 */
331
332 switch (state) {
333
334 /* first char */
335 case hl_start:
336 switch (ch) {
337 case CR:
338 r->header_end = p - 1;
339 state = header_almost_done;
340 break;
341 case LF:
342 r->header_end = p - 1;
343 state = header_done;
344 break;
345 default:
346 state = hl_name;
347 r->header_name_start = p - 1;
348
349 c = ch | 0x20;
350 if (c >= 'a' && c <= 'z')
351 break;
352
353 if (ch == '-')
354 break;
355
356 if (ch >= '0' && ch <= '9')
357 break;
358
359 return NGX_HTTP_INVALID_HEADER;
360
361 }
362 break;
363
364 /* header name */
365 case hl_name:
366 c = ch | 0x20;
367 if (c >= 'a' && c <= 'z')
368 break;
369
370 if (ch == ':') {
371 r->header_name_end = p - 1;
372 state = hl_space_before_value;
373 break;
374 }
375
376 if (ch == '-')
377 break;
378
379 if (ch >= '0' && ch <= '9')
380 break;
381
382 return NGX_HTTP_INVALID_HEADER;
383
384 /* space* before header value */
385 case hl_space_before_value:
386 switch (ch) {
387 case ' ':
388 break;
389 case CR:
390 r->header_start = r->header_end = p - 1;
391 state = hl_almost_done;
392 break;
393 case LF:
394 r->header_start = r->header_end = p - 1;
395 state = hl_done;
396 break;
397 default:
398 r->header_start = p - 1;
399 state = hl_value;
400 break;
401 }
402 break;
403
404 /* header value */
405 case hl_value:
406 switch (ch) {
407 case ' ':
408 r->header_end = p - 1;
409 state = hl_space_after_value;
410 break;
411 case CR:
412 r->header_end = p - 1;
413 state = hl_almost_done;
414 break;
415 case LF:
416 r->header_end = p - 1;
417 state = hl_done;
418 break;
419 }
420 break;
421
422 /* space* before end of header line */
423 case hl_space_after_value:
424 switch (ch) {
425 case ' ':
426 break;
427 case CR:
428 state = hl_almost_done;
429 break;
430 case LF:
431 state = hl_done;
432 break;
433 default:
434 state = hl_value;
435 break;
436 }
437 break;
438
439 /* end of header line */
440 case hl_almost_done:
441 switch (ch) {
442 case LF:
443 state = hl_done;
444 break;
445 default:
446 return NGX_HTTP_INVALID_HEADER;
447 }
448 break;
449
450 /* end of header */
451 case header_almost_done:
452 switch (ch) {
453 case LF:
454 state = header_done;
455 break;
456 default:
457 return NGX_HTTP_INVALID_HEADER;
458 }
459 break;
460 }
461 }
462
463 r->buff->pos = p;
464
465 if (state == hl_done) {
466 r->state = hl_start;
467 return 1;
468 } else if (state == header_done) {
469 r->state = hl_start;
470 return 2;
471 } else {
472 r->state = state;
473 return 0;
474 }
475 }