Mercurial > hg > nginx
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 } |