~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/ngx_http_request.c

Version: ~ [ nginx-0.6.26 ] ~ [ nginx-0.5.35 ] ~ [ nginx-0.5.20 ] ~ [ nginx-0.5.19 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  */
  5 
  6 
  7 #include <ngx_config.h>
  8 #include <ngx_core.h>
  9 #include <ngx_event.h>
 10 #include <ngx_http.h>
 11 
 12 
 13 static void ngx_http_init_request(ngx_event_t *ev);
 14 static void ngx_http_process_request_line(ngx_event_t *rev);
 15 static void ngx_http_process_request_headers(ngx_event_t *rev);
 16 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
 17 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
 18     ngx_uint_t request_line);
 19 
 20 static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
 21     ngx_table_elt_t *h, ngx_uint_t offset);
 22 static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
 23     ngx_table_elt_t *h, ngx_uint_t offset);
 24 static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
 25     ngx_table_elt_t *h, ngx_uint_t offset);
 26 static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r,
 27     ngx_table_elt_t *h, ngx_uint_t offset);
 28 
 29 static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
 30 static void ngx_http_process_request(ngx_http_request_t *r);
 31 static void ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host,
 32     size_t len, ngx_uint_t hash);
 33 
 34 static void ngx_http_request_handler(ngx_event_t *ev);
 35 static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
 36 static void ngx_http_writer(ngx_http_request_t *r);
 37 
 38 static void ngx_http_test_reading(ngx_http_request_t *r);
 39 static void ngx_http_set_keepalive(ngx_http_request_t *r);
 40 static void ngx_http_keepalive_handler(ngx_event_t *ev);
 41 static void ngx_http_set_lingering_close(ngx_http_request_t *r);
 42 static void ngx_http_lingering_close_handler(ngx_event_t *ev);
 43 static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
 44 static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
 45 static void ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error);
 46 static void ngx_http_close_connection(ngx_connection_t *c);
 47 
 48 static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
 49 static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
 50     ngx_http_request_t *sr, u_char *buf, size_t len);
 51 
 52 #if (NGX_HTTP_SSL)
 53 static void ngx_http_ssl_handshake(ngx_event_t *rev);
 54 static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
 55 #endif
 56 
 57 
 58 static char *ngx_http_client_errors[] = {
 59 
 60     /* NGX_HTTP_PARSE_INVALID_METHOD */
 61     "client sent invalid method",
 62 
 63     /* NGX_HTTP_PARSE_INVALID_REQUEST */
 64     "client sent invalid request",
 65 
 66     /* NGX_HTTP_PARSE_INVALID_09_METHOD */
 67     "client sent invalid method in HTTP/0.9 request"
 68 };
 69 
 70 
 71 ngx_http_header_t  ngx_http_headers_in[] = {
 72     { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
 73                  ngx_http_process_unique_header_line },
 74 
 75     { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
 76                  ngx_http_process_connection },
 77 
 78     { ngx_string("If-Modified-Since"),
 79                  offsetof(ngx_http_headers_in_t, if_modified_since),
 80                  ngx_http_process_unique_header_line },
 81 
 82     { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
 83                  ngx_http_process_header_line },
 84 
 85     { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
 86                  ngx_http_process_header_line },
 87 
 88     { ngx_string("Content-Length"),
 89                  offsetof(ngx_http_headers_in_t, content_length),
 90                  ngx_http_process_unique_header_line },
 91 
 92     { ngx_string("Content-Type"),
 93                  offsetof(ngx_http_headers_in_t, content_type),
 94                  ngx_http_process_header_line },
 95 
 96     { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
 97                  ngx_http_process_header_line },
 98 
 99     { ngx_string("If-Range"),
100                  offsetof(ngx_http_headers_in_t, if_range),
101                  ngx_http_process_unique_header_line },
102 
103     { ngx_string("Transfer-Encoding"),
104                  offsetof(ngx_http_headers_in_t, transfer_encoding),
105                  ngx_http_process_header_line },
106 
107 #if (NGX_HTTP_GZIP)
108     { ngx_string("Accept-Encoding"),
109                  offsetof(ngx_http_headers_in_t, accept_encoding),
110                  ngx_http_process_header_line },
111 
112     { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
113                  ngx_http_process_header_line },
114 #endif
115 
116     { ngx_string("Authorization"),
117                  offsetof(ngx_http_headers_in_t, authorization),
118                  ngx_http_process_unique_header_line },
119 
120     { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
121                  ngx_http_process_header_line },
122 
123 #if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)
124     { ngx_string("X-Forwarded-For"),
125                  offsetof(ngx_http_headers_in_t, x_forwarded_for),
126                  ngx_http_process_header_line },
127 #endif
128 
129 #if (NGX_HTTP_REALIP)
130     { ngx_string("X-Real-IP"),
131                  offsetof(ngx_http_headers_in_t, x_real_ip),
132                  ngx_http_process_header_line },
133 #endif
134 
135 #if (NGX_HTTP_HEADERS)
136     { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
137                  ngx_http_process_header_line },
138 
139     { ngx_string("Accept-Language"),
140                  offsetof(ngx_http_headers_in_t, accept_language),
141                  ngx_http_process_header_line },
142 #endif
143 
144 #if (NGX_HTTP_DAV)
145     { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
146                  ngx_http_process_header_line },
147 
148     { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
149                  ngx_http_process_header_line },
150 
151     { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),
152                  ngx_http_process_header_line },
153 
154     { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
155                  ngx_http_process_header_line },
156 #endif
157 
158     { ngx_string("Cookie"), 0, ngx_http_process_cookie },
159 
160     { ngx_null_string, 0, NULL }
161 };
162 
163 
164 void
165 ngx_http_init_connection(ngx_connection_t *c)
166 {
167     ngx_event_t         *rev;
168     ngx_http_log_ctx_t  *ctx;
169 
170     ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
171     if (ctx == NULL) {
172         ngx_http_close_connection(c);
173         return;
174     }
175 
176     ctx->connection = c;
177     ctx->request = NULL;
178     ctx->current_request = NULL;
179 
180     c->log->connection = c->number;
181     c->log->handler = ngx_http_log_error;
182     c->log->data = ctx;
183     c->log->action = "reading client request line";
184 
185     c->log_error = NGX_ERROR_INFO;
186 
187     rev = c->read;
188     rev->handler = ngx_http_init_request;
189     c->write->handler = ngx_http_empty_handler;
190 
191 #if (NGX_STAT_STUB)
192     ngx_atomic_fetch_add(ngx_stat_reading, 1);
193 #endif
194 
195     if (rev->ready) {
196         /* the deferred accept(), rtsig, aio, iocp */
197 
198         if (ngx_use_accept_mutex) {
199             ngx_post_event(rev, &ngx_posted_events);
200             return;
201         }
202 
203         ngx_http_init_request(rev);
204         return;
205     }
206 
207     ngx_add_timer(rev, c->listening->post_accept_timeout);
208 
209     if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
210 #if (NGX_STAT_STUB)
211         ngx_atomic_fetch_add(ngx_stat_reading, -1);
212 #endif
213         ngx_http_close_connection(c);
214         return;
215     }
216 }
217 
218 
219 static void
220 ngx_http_init_request(ngx_event_t *rev)
221 {
222     ngx_time_t                 *tp;
223     ngx_uint_t                  i;
224     ngx_connection_t           *c;
225     ngx_http_request_t         *r;
226     ngx_http_in_port_t         *hip;
227     ngx_http_in_addr_t         *hia;
228     ngx_http_log_ctx_t         *ctx;
229     ngx_http_connection_t      *hc;
230     ngx_http_core_srv_conf_t   *cscf;
231     ngx_http_core_loc_conf_t   *clcf;
232     ngx_http_core_main_conf_t  *cmcf;
233 
234 #if (NGX_STAT_STUB)
235     ngx_atomic_fetch_add(ngx_stat_reading, -1);
236 #endif
237 
238     c = rev->data;
239 
240     if (rev->timedout) {
241         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
242 
243         ngx_http_close_connection(c);
244         return;
245     }
246 
247     hc = c->data;
248 
249     if (hc == NULL) {
250         hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
251         if (hc == NULL) {
252             ngx_http_close_connection(c);
253             return;
254         }
255     }
256 
257     r = hc->request;
258 
259     if (r) {
260         ngx_memzero(r, sizeof(ngx_http_request_t));
261 
262         r->pipeline = hc->pipeline;
263 
264         if (hc->nbusy) {
265             r->header_in = hc->busy[0];
266         }
267 
268     } else {
269         r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
270         if (r == NULL) {
271             ngx_http_close_connection(c);
272             return;
273         }
274 
275         hc->request = r;
276     }
277 
278     c->data = r;
279     r->http_connection = hc;
280 
281     c->sent = 0;
282     r->signature = NGX_HTTP_MODULE;
283 
284     /* find the server configuration for the address:port */
285 
286     /* AF_INET only */
287 
288     hip = c->listening->servers;
289     hia = hip->addrs;
290 
291     r->port = hip->port;
292     r->port_text = &hip->port_text;
293 
294     i = 0;
295 
296     r->connection = c;
297 
298     if (hip->naddrs > 1) {
299 
300         /*
301          * There are several addresses on this port and one of them
302          * is the "*:port" wildcard so getsockname() is needed to determine
303          * the server address.
304          *
305          * AcceptEx() already has given this address.
306          */
307 
308 #if (NGX_WIN32)
309         if (c->local_sockaddr) {
310             r->in_addr =
311                    ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
312 
313         } else
314 #endif
315         {
316             if (ngx_http_server_addr(r, NULL) != NGX_OK) {
317                 ngx_http_close_connection(c);
318                 return;
319             }
320         }
321 
322         /* the last address is "*" */
323 
324         for ( /* void */ ; i < hip->naddrs - 1; i++) {
325             if (hia[i].addr == r->in_addr) {
326                 break;
327             }
328         }
329 
330     } else {
331         r->in_addr = hia[0].addr;
332     }
333 
334     r->virtual_names = hia[i].virtual_names;
335 
336     /* the default server configuration for the address:port */
337     cscf = hia[i].core_srv_conf;
338 
339     r->main_conf = cscf->ctx->main_conf;
340     r->srv_conf = cscf->ctx->srv_conf;
341     r->loc_conf = cscf->ctx->loc_conf;
342 
343     rev->handler = ngx_http_process_request_line;
344 
345 #if (NGX_HTTP_SSL)
346 
347     {
348     ngx_http_ssl_srv_conf_t  *sscf;
349 
350     sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
351     if (sscf->enable) {
352 
353         if (c->ssl == NULL) {
354             if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
355                 == NGX_ERROR)
356             {
357                 ngx_http_close_connection(c);
358                 return;
359             }
360 
361             rev->handler = ngx_http_ssl_handshake;
362         }
363 
364         r->main_filter_need_in_memory = 1;
365     }
366     }
367 
368 #endif
369 
370     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
371     c->log->file = clcf->err_log->file;
372     if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
373         c->log->log_level = clcf->err_log->log_level;
374     }
375 
376     if (c->buffer == NULL) {
377         c->buffer = ngx_create_temp_buf(c->pool,
378                                         cscf->client_header_buffer_size);
379         if (c->buffer == NULL) {
380             ngx_http_close_connection(c);
381             return;
382         }
383     }
384 
385     if (r->header_in == NULL) {
386         r->header_in = c->buffer;
387     }
388 
389     r->pool = ngx_create_pool(cscf->request_pool_size, c->log);
390     if (r->pool == NULL) {
391         ngx_http_close_connection(c);
392         return;
393     }
394 
395 
396     if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
397                       sizeof(ngx_table_elt_t))
398         == NGX_ERROR)
399     {
400         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
401         return;
402     }
403 
404     r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
405     if (r->ctx == NULL) {
406         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
407         return;
408     }
409 
410     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
411 
412     r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
413                                         * sizeof(ngx_http_variable_value_t));
414     if (r->variables == NULL) {
415         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
416         return;
417     }
418 
419     c->single_connection = 1;
420     c->destroyed = 0;
421 
422     r->main = r;
423 
424     tp = ngx_timeofday();
425     r->start_sec = tp->sec;
426     r->start_msec = tp->msec;
427 
428     r->method = NGX_HTTP_UNKNOWN;
429 
430     r->headers_in.content_length_n = -1;
431     r->headers_in.keep_alive_n = -1;
432     r->headers_out.content_length_n = -1;
433     r->headers_out.last_modified_time = -1;
434 
435     r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
436     r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;
437 
438     r->http_state = NGX_HTTP_READING_REQUEST_STATE;
439 
440     ctx = c->log->data;
441     ctx->request = r;
442     ctx->current_request = r;
443     r->log_handler = ngx_http_log_error_handler;
444 
445 #if (NGX_STAT_STUB)
446     ngx_atomic_fetch_add(ngx_stat_reading, 1);
447     r->stat_reading = 1;
448     ngx_atomic_fetch_add(ngx_stat_requests, 1);
449 #endif
450 
451     rev->handler(rev);
452 }
453 
454 
455 #if (NGX_HTTP_SSL)
456 
457 static void
458 ngx_http_ssl_handshake(ngx_event_t *rev)
459 {
460     u_char               buf[1];
461     ssize_t              n;
462     ngx_int_t            rc;
463     ngx_connection_t    *c;
464     ngx_http_request_t  *r;
465 
466     c = rev->data;
467     r = c->data;
468 
469     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
470                    "http check ssl handshake");
471 
472     if (rev->timedout) {
473         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
474         c->timedout = 1;
475         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
476         return;
477     }
478 
479     n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
480 
481     if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
482 
483         if (!rev->timer_set) {
484             ngx_add_timer(rev, c->listening->post_accept_timeout);
485         }
486 
487         if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
488             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
489         }
490 
491         return;
492     }
493 
494     if (n == 1) {
495         if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
496             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
497                            "https ssl handshake: 0x%02Xd", buf[0]);
498 
499             rc = ngx_ssl_handshake(c);
500 
501             if (rc == NGX_AGAIN) {
502 
503                 if (!rev->timer_set) {
504                     ngx_add_timer(rev, c->listening->post_accept_timeout);
505                 }
506 
507                 c->ssl->handler = ngx_http_ssl_handshake_handler;
508                 return;
509             }
510 
511             ngx_http_ssl_handshake_handler(c);
512 
513             return;
514 
515         } else {
516             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
517                            "plain http");
518 
519             r->plain_http = 1;
520         }
521     }
522 
523     rev->handler = ngx_http_process_request_line;
524     ngx_http_process_request_line(rev);
525 }
526 
527 
528 static void
529 ngx_http_ssl_handshake_handler(ngx_connection_t *c)
530 {
531     ngx_http_request_t  *r;
532 
533     if (c->ssl->handshaked) {
534 
535         /*
536          * The majority of browsers do not send the "close notify" alert.
537          * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
538          * and Links.  And what is more, MSIE ignores the server's alert.
539          *
540          * Opera and recent Mozilla send the alert.
541          */
542 
543         c->ssl->no_wait_shutdown = 1;
544 
545         c->read->handler = ngx_http_process_request_line;
546         /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
547 
548         ngx_http_process_request_line(c->read);
549 
550         return;
551     }
552 
553     r = c->data;
554 
555     ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
556 
557     return;
558 }
559 
560 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
561 
562 int
563 ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
564 {
565     u_char                   *p;
566     ngx_uint_t                hash;
567     const char               *servername;
568     ngx_connection_t         *c;
569     ngx_http_request_t       *r;
570     ngx_http_ssl_srv_conf_t  *sscf;
571 
572     servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
573 
574     if (servername == NULL) {
575         return SSL_TLSEXT_ERR_NOACK;
576     }
577 
578     c = ngx_ssl_get_connection(ssl_conn);
579 
580     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
581                    "SSL server name: \"%s\"", servername);
582 
583     r = c->data;
584 
585     if (r->virtual_names == NULL) {
586         return SSL_TLSEXT_ERR_NOACK;
587     }
588 
589     /* it seems browsers send low case server name */
590 
591     hash = 0;
592 
593     for (p = (u_char *) servername; *p; p++) {
594         hash = ngx_hash(hash, *p);
595     }
596 
597     ngx_http_find_virtual_server(r, (u_char *) servername,
598                                  p - (u_char *) servername, hash);
599 
600     sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
601 
602     SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
603 
604     return SSL_TLSEXT_ERR_OK;
605 }
606 
607 #endif
608 
609 #endif
610 
611 
612 static void
613 ngx_http_process_request_line(ngx_event_t *rev)
614 {
615     ssize_t                    n;
616     ngx_int_t                  rc, rv;
617     ngx_connection_t          *c;
618     ngx_http_request_t        *r;
619     ngx_http_core_srv_conf_t  *cscf;
620 
621     c = rev->data;
622     r = c->data;
623 
624     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
625                    "http process request line");
626 
627     if (rev->timedout) {
628         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
629         c->timedout = 1;
630         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
631         return;
632     }
633 
634     rc = NGX_AGAIN;
635 
636     for ( ;; ) {
637 
638         if (rc == NGX_AGAIN) {
639             n = ngx_http_read_request_header(r);
640 
641             if (n == NGX_AGAIN || n == NGX_ERROR) {
642                 return;
643             }
644         }
645 
646         rc = ngx_http_parse_request_line(r, r->header_in);
647 
648         if (rc == NGX_OK) {
649 
650             /* the request line has been parsed successfully */
651 
652             r->request_line.len = r->request_end - r->request_start;
653             r->request_line.data = r->request_start;
654 
655 
656             if (r->args_start) {
657                 r->uri.len = r->args_start - 1 - r->uri_start;
658             } else {
659                 r->uri.len = r->uri_end - r->uri_start;
660             }
661 
662 
663             if (r->complex_uri || r->quoted_uri) {
664 
665                 r->uri.data = ngx_palloc(r->pool, r->uri.len + 1);
666                 if (r->uri.data == NULL) {
667                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
668                     return;
669                 }
670 
671                 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
672 
673                 rc = ngx_http_parse_complex_uri(r, cscf->merge_slashes);
674 
675                 if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) {
676                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
677                                   "client sent invalid request");
678                     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
679                     return;
680                 }
681 
682             } else {
683                 r->uri.data = r->uri_start;
684             }
685 
686 
687             r->unparsed_uri.len = r->uri_end - r->uri_start;
688             r->unparsed_uri.data = r->uri_start;
689 
690 
691             r->method_name.len = r->method_end - r->request_start + 1;
692             r->method_name.data = r->request_line.data;
693 
694 
695             if (r->http_protocol.data) {
696                 r->http_protocol.len = r->request_end - r->http_protocol.data;
697             }
698 
699 
700             if (r->uri_ext) {
701                 if (r->args_start) {
702                     r->exten.len = r->args_start - 1 - r->uri_ext;
703                 } else {
704                     r->exten.len = r->uri_end - r->uri_ext;
705                 }
706 
707                 r->exten.data = r->uri_ext;
708             }
709 
710 
711             if (r->args_start && r->uri_end > r->args_start) {
712                 r->args.len = r->uri_end - r->args_start;
713                 r->args.data = r->args_start;
714             }
715 
716 
717             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
718                            "http request line: \"%V\"", &r->request_line);
719 
720             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
721                            "http uri: \"%V\"", &r->uri);
722 
723             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
724                            "http args: \"%V\"", &r->args);
725 
726             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
727                            "http exten: \"%V\"", &r->exten);
728 
729             if (r->http_version < NGX_HTTP_VERSION_10) {
730                 ngx_http_process_request(r);
731                 return;
732             }
733 
734 
735             if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
736                               sizeof(ngx_table_elt_t))
737                 == NGX_ERROR)
738             {
739                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
740                 return;
741             }
742 
743 
744             if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,
745                                sizeof(ngx_table_elt_t *))
746                 == NGX_ERROR)
747             {
748                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
749                 return;
750             }
751 
752             c->log->action = "reading client request headers";
753 
754             rev->handler = ngx_http_process_request_headers;
755             ngx_http_process_request_headers(rev);
756 
757             return;
758         }
759 
760         if (rc != NGX_AGAIN) {
761 
762             /* there was error while a request line parsing */
763 
764             ngx_log_error(NGX_LOG_INFO, c->log, 0,
765                           ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
766             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
767             return;
768         }
769 
770         /* NGX_AGAIN: a request line parsing is still incomplete */
771 
772         if (r->header_in->pos == r->header_in->end) {
773 
774             rv = ngx_http_alloc_large_header_buffer(r, 1);
775 
776             if (rv == NGX_ERROR) {
777                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
778                 return;
779             }
780 
781             if (rv == NGX_DECLINED) {
782                 r->request_line.len = r->header_in->end - r->request_start;
783                 r->request_line.data = r->request_start;
784 
785                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
786                               "client sent too long URI");
787                 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
788                 return;
789             }
790         }
791     }
792 }
793 
794 
795 static void
796 ngx_http_process_request_headers(ngx_event_t *rev)
797 {
798     ssize_t                     n;
799     ngx_int_t                   rc, rv;
800     ngx_str_t                   header;
801     ngx_uint_t                  i;
802     ngx_table_elt_t            *h;
803     ngx_connection_t           *c;
804     ngx_http_header_t          *hh;
805     ngx_http_request_t         *r;
806     ngx_http_core_srv_conf_t   *cscf;
807     ngx_http_core_main_conf_t  *cmcf;
808 
809     c = rev->data;
810     r = c->data;
811 
812     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
813                    "http process request header line");
814 
815     if (rev->timedout) {
816         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
817         c->timedout = 1;
818         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
819         return;
820     }
821 
822     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
823     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
824 
825     rc = NGX_AGAIN;
826 
827     for ( ;; ) {
828 
829         if (rc == NGX_AGAIN) {
830 
831             if (r->header_in->pos == r->header_in->end) {
832 
833                 rv = ngx_http_alloc_large_header_buffer(r, 0);
834 
835                 if (rv == NGX_ERROR) {
836                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
837                     return;
838                 }
839 
840                 if (rv == NGX_DECLINED) {
841                     header.len = r->header_in->end - r->header_name_start;
842                     header.data = r->header_name_start;
843 
844                     if (header.len > NGX_MAX_ERROR_STR - 300) {
845                         header.len = NGX_MAX_ERROR_STR - 300;
846                         header.data[header.len++] = '.';
847                         header.data[header.len++] = '.';
848                         header.data[header.len++] = '.';
849                     }
850 
851                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
852                                   "client sent too long header line: \"%V\"",
853                                   &header);
854                     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
855                     return;
856                 }
857             }
858 
859             n = ngx_http_read_request_header(r);
860 
861             if (n == NGX_AGAIN || n == NGX_ERROR) {
862                 return;
863             }
864         }
865 
866         rc = ngx_http_parse_header_line(r, r->header_in);
867 
868         if (rc == NGX_OK) {
869 
870             if (r->invalid_header && cscf->ignore_invalid_headers) {
871 
872                 /* there was error while a header line parsing */
873 
874                 header.len = r->header_end - r->header_name_start;
875                 header.data = r->header_name_start;
876 
877                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
878                               "client sent invalid header line: \"%V\"",
879                               &header);
880                 continue;
881             }
882 
883             /* a header line has been parsed successfully */
884 
885             h = ngx_list_push(&r->headers_in.headers);
886             if (h == NULL) {
887                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
888                 return;
889             }
890 
891             h->hash = r->header_hash;
892 
893             h->key.len = r->header_name_end - r->header_name_start;
894             h->key.data = r->header_name_start;
895             h->key.data[h->key.len] = '\0';
896 
897             h->value.len = r->header_end - r->header_start;
898             h->value.data = r->header_start;
899             h->value.data[h->value.len] = '\0';
900 
901             h->lowcase_key = ngx_palloc(r->pool, h->key.len);
902             if (h->lowcase_key == NULL) {
903                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
904                 return;
905             }
906 
907             if (h->key.len == r->lowcase_index) {
908                 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
909 
910             } else {
911                 for (i = 0; i < h->key.len; i++) {
912                     h->lowcase_key[i] = ngx_tolower(h->key.data[i]);
913                 }
914             }
915 
916             hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
917                                h->lowcase_key, h->key.len);
918 
919             if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
920                 return;
921             }
922 
923             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
924                            "http header: \"%V: %V\"",
925                            &h->key, &h->value);
926 
927             continue;
928         }
929 
930         if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
931 
932             /* a whole header has been parsed successfully */
933 
934             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
935                            "http header done");
936 
937             r->request_length += r->header_in->pos - r->header_in->start;
938 
939             r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
940 
941             rc = ngx_http_process_request_header(r);
942 
943             if (rc != NGX_OK) {
944                 return;
945             }
946 
947             ngx_http_process_request(r);
948 
949             return;
950         }
951 
952         if (rc == NGX_AGAIN) {
953 
954             /* a header line parsing is still not complete */
955 
956             continue;
957         }
958 
959         /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
960 
961         header.len = r->header_end - r->header_name_start;
962         header.data = r->header_name_start;
963         ngx_log_error(NGX_LOG_INFO, c->log, 0,
964                       "client sent invalid header line: \"%V\\r...\"",
965                       &header);
966         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
967         return;
968     }
969 }
970 
971 
972 static ssize_t
973 ngx_http_read_request_header(ngx_http_request_t *r)
974 {
975     ssize_t                    n;
976     ngx_event_t               *rev;
977     ngx_connection_t          *c;
978     ngx_http_core_srv_conf_t  *cscf;
979 
980     c = r->connection;
981     rev = c->read;
982 
983     n = r->header_in->last - r->header_in->pos;
984 
985     if (n > 0) {
986         return n;
987     }
988 
989     if (rev->ready) {
990         n = c->recv(c, r->header_in->last,
991                     r->header_in->end - r->header_in->last);
992     } else {
993         n = NGX_AGAIN;
994     }
995 
996     if (n == NGX_AGAIN) {
997         if (!rev->timer_set) {
998             cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
999             ngx_add_timer(rev, cscf->client_header_timeout);
1000         }
1001 
1002         if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
1003             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1004             return NGX_ERROR;
1005         }
1006 
1007         return NGX_AGAIN;
1008     }
1009 
1010     if (n == 0) {
1011         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1012                       "client closed prematurely connection");
1013     }
1014 
1015     if (n == 0 || n == NGX_ERROR) {
1016         c->error = 1;
1017         c->log->action = "reading client request headers";
1018 
1019         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1020         return NGX_ERROR;
1021     }
1022 
1023     r->header_in->last += n;
1024 
1025     return n;
1026 }
1027 
1028 
1029 static ngx_int_t
1030 ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
1031     ngx_uint_t request_line)
1032 {
1033     u_char                    *old, *new;
1034     ngx_buf_t                 *b;
1035     ngx_http_connection_t     *hc;
1036     ngx_http_core_srv_conf_t  *cscf;
1037 
1038     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1039                    "http alloc large header buffer");
1040 
1041     if (request_line && r->state == 0) {
1042 
1043         /* the client fills up the buffer with "\r\n" */
1044 
1045         r->request_length +=