upstream nginx-0.7.37
[nginx.git] / nginx / src / http / ngx_http_request.c
1
2 /*
3  * Copyright (C) Igor Sysoev
4  */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_http.h>
10
11
12 static void ngx_http_init_request(ngx_event_t *ev);
13 static void ngx_http_process_request_line(ngx_event_t *rev);
14 static void ngx_http_process_request_headers(ngx_event_t *rev);
15 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
16 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
17     ngx_uint_t request_line);
18
19 static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
20     ngx_table_elt_t *h, ngx_uint_t offset);
21 static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
22     ngx_table_elt_t *h, ngx_uint_t offset);
23 static ngx_int_t ngx_http_process_host(ngx_http_request_t *r,
24     ngx_table_elt_t *h, ngx_uint_t offset);
25 static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
26     ngx_table_elt_t *h, ngx_uint_t offset);
27 static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r,
28     ngx_table_elt_t *h, ngx_uint_t offset);
29 static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r,
30     ngx_table_elt_t *h, ngx_uint_t offset);
31
32 static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
33 static void ngx_http_process_request(ngx_http_request_t *r);
34 static ssize_t ngx_http_validate_host(u_char *host, size_t len);
35 static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r,
36     u_char *host, size_t len);
37
38 static void ngx_http_request_handler(ngx_event_t *ev);
39 static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
40 static void ngx_http_writer(ngx_http_request_t *r);
41 static void ngx_http_request_finalizer(ngx_http_request_t *r);
42
43 static void ngx_http_set_keepalive(ngx_http_request_t *r);
44 static void ngx_http_keepalive_handler(ngx_event_t *ev);
45 static void ngx_http_set_lingering_close(ngx_http_request_t *r);
46 static void ngx_http_lingering_close_handler(ngx_event_t *ev);
47 static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
48 static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
49 static void ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error);
50 static void ngx_http_log_request(ngx_http_request_t *r);
51 static void ngx_http_close_connection(ngx_connection_t *c);
52
53 static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
54 static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
55     ngx_http_request_t *sr, u_char *buf, size_t len);
56
57 #if (NGX_HTTP_SSL)
58 static void ngx_http_ssl_handshake(ngx_event_t *rev);
59 static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
60 #endif
61
62
63 static char *ngx_http_client_errors[] = {
64
65     /* NGX_HTTP_PARSE_INVALID_METHOD */
66     "client sent invalid method",
67
68     /* NGX_HTTP_PARSE_INVALID_REQUEST */
69     "client sent invalid request",
70
71     /* NGX_HTTP_PARSE_INVALID_09_METHOD */
72     "client sent invalid method in HTTP/0.9 request"
73 };
74
75
76 ngx_http_header_t  ngx_http_headers_in[] = {
77     { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
78                  ngx_http_process_host },
79
80     { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
81                  ngx_http_process_connection },
82
83     { ngx_string("If-Modified-Since"),
84                  offsetof(ngx_http_headers_in_t, if_modified_since),
85                  ngx_http_process_unique_header_line },
86
87     { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
88                  ngx_http_process_user_agent },
89
90     { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
91                  ngx_http_process_header_line },
92
93     { ngx_string("Content-Length"),
94                  offsetof(ngx_http_headers_in_t, content_length),
95                  ngx_http_process_unique_header_line },
96
97     { ngx_string("Content-Type"),
98                  offsetof(ngx_http_headers_in_t, content_type),
99                  ngx_http_process_header_line },
100
101     { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
102                  ngx_http_process_header_line },
103
104     { ngx_string("If-Range"),
105                  offsetof(ngx_http_headers_in_t, if_range),
106                  ngx_http_process_unique_header_line },
107
108     { ngx_string("Transfer-Encoding"),
109                  offsetof(ngx_http_headers_in_t, transfer_encoding),
110                  ngx_http_process_header_line },
111
112     { ngx_string("Expect"),
113                  offsetof(ngx_http_headers_in_t, expect),
114                  ngx_http_process_unique_header_line },
115
116 #if (NGX_HTTP_GZIP)
117     { ngx_string("Accept-Encoding"),
118                  offsetof(ngx_http_headers_in_t, accept_encoding),
119                  ngx_http_process_header_line },
120
121     { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
122                  ngx_http_process_header_line },
123 #endif
124
125     { ngx_string("Authorization"),
126                  offsetof(ngx_http_headers_in_t, authorization),
127                  ngx_http_process_unique_header_line },
128
129     { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
130                  ngx_http_process_header_line },
131
132 #if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)
133     { ngx_string("X-Forwarded-For"),
134                  offsetof(ngx_http_headers_in_t, x_forwarded_for),
135                  ngx_http_process_header_line },
136 #endif
137
138 #if (NGX_HTTP_REALIP)
139     { ngx_string("X-Real-IP"),
140                  offsetof(ngx_http_headers_in_t, x_real_ip),
141                  ngx_http_process_header_line },
142 #endif
143
144 #if (NGX_HTTP_HEADERS)
145     { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
146                  ngx_http_process_header_line },
147
148     { ngx_string("Accept-Language"),
149                  offsetof(ngx_http_headers_in_t, accept_language),
150                  ngx_http_process_header_line },
151 #endif
152
153 #if (NGX_HTTP_DAV)
154     { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
155                  ngx_http_process_header_line },
156
157     { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
158                  ngx_http_process_header_line },
159
160     { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),
161                  ngx_http_process_header_line },
162
163     { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
164                  ngx_http_process_header_line },
165 #endif
166
167     { ngx_string("Cookie"), 0, ngx_http_process_cookie },
168
169     { ngx_null_string, 0, NULL }
170 };
171
172
173 void
174 ngx_http_init_connection(ngx_connection_t *c)
175 {
176     ngx_event_t         *rev;
177     ngx_http_log_ctx_t  *ctx;
178
179     ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
180     if (ctx == NULL) {
181         ngx_http_close_connection(c);
182         return;
183     }
184
185     ctx->connection = c;
186     ctx->request = NULL;
187     ctx->current_request = NULL;
188
189     c->log->connection = c->number;
190     c->log->handler = ngx_http_log_error;
191     c->log->data = ctx;
192     c->log->action = "reading client request line";
193
194     c->log_error = NGX_ERROR_INFO;
195
196     rev = c->read;
197     rev->handler = ngx_http_init_request;
198     c->write->handler = ngx_http_empty_handler;
199
200 #if (NGX_STAT_STUB)
201     ngx_atomic_fetch_add(ngx_stat_reading, 1);
202 #endif
203
204     if (rev->ready) {
205         /* the deferred accept(), rtsig, aio, iocp */
206
207         if (ngx_use_accept_mutex) {
208             ngx_post_event(rev, &ngx_posted_events);
209             return;
210         }
211
212         ngx_http_init_request(rev);
213         return;
214     }
215
216     ngx_add_timer(rev, c->listening->post_accept_timeout);
217
218     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
219 #if (NGX_STAT_STUB)
220         ngx_atomic_fetch_add(ngx_stat_reading, -1);
221 #endif
222         ngx_http_close_connection(c);
223         return;
224     }
225 }
226
227
228 static void
229 ngx_http_init_request(ngx_event_t *rev)
230 {
231     ngx_time_t                 *tp;
232     ngx_uint_t                  i;
233     ngx_connection_t           *c;
234     ngx_http_request_t         *r;
235     struct sockaddr_in         *sin;
236     ngx_http_port_t            *port;
237     ngx_http_in_addr_t         *addr;
238     ngx_http_log_ctx_t         *ctx;
239     ngx_http_addr_conf_t       *addr_conf;
240     ngx_http_connection_t      *hc;
241     ngx_http_core_srv_conf_t   *cscf;
242     ngx_http_core_loc_conf_t   *clcf;
243     ngx_http_core_main_conf_t  *cmcf;
244 #if (NGX_HAVE_INET6)
245     struct sockaddr_in6        *sin6;
246     ngx_http_in6_addr_t        *addr6;
247 #endif
248
249 #if (NGX_STAT_STUB)
250     ngx_atomic_fetch_add(ngx_stat_reading, -1);
251 #endif
252
253     c = rev->data;
254
255     if (rev->timedout) {
256         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
257
258         ngx_http_close_connection(c);
259         return;
260     }
261
262     hc = c->data;
263
264     if (hc == NULL) {
265         hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
266         if (hc == NULL) {
267             ngx_http_close_connection(c);
268             return;
269         }
270     }
271
272     r = hc->request;
273
274     if (r) {
275         ngx_memzero(r, sizeof(ngx_http_request_t));
276
277         r->pipeline = hc->pipeline;
278
279         if (hc->nbusy) {
280             r->header_in = hc->busy[0];
281         }
282
283     } else {
284         r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
285         if (r == NULL) {
286             ngx_http_close_connection(c);
287             return;
288         }
289
290         hc->request = r;
291     }
292
293     c->data = r;
294     r->http_connection = hc;
295
296     c->sent = 0;
297     r->signature = NGX_HTTP_MODULE;
298
299     /* find the server configuration for the address:port */
300
301     port = c->listening->servers;
302
303     r->port = port->port;
304     r->port_text = &port->port_text;
305
306     r->connection = c;
307
308     if (port->naddrs > 1) {
309
310         /*
311          * there are several addresses on this port and one of them
312          * is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
313          * is required to determine a server address
314          */
315
316         c->local_sockaddr = NULL;
317
318         if (ngx_http_server_addr(r, NULL) != NGX_OK) {
319             ngx_http_close_connection(c);
320             return;
321         }
322
323         switch (c->local_sockaddr->sa_family) {
324
325 #if (NGX_HAVE_INET6)
326         case AF_INET6:
327             sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
328
329             addr6 = (ngx_http_in6_addr_t *) port->addrs;
330
331             /* the last address is "*" */
332
333             for (i = 0; i < port->naddrs - 1; i++) {
334                 if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
335                     break;
336                 }
337             }
338
339             addr_conf = &addr6[i].conf;
340
341             break;
342 #endif
343
344         default: /* AF_INET */
345             sin = (struct sockaddr_in *) c->local_sockaddr;
346
347             addr = port->addrs;
348
349             /* the last address is "*" */
350
351             for (i = 0; i < port->naddrs - 1; i++) {
352                 if (addr[i].addr == sin->sin_addr.s_addr) {
353                     break;
354                 }
355             }
356
357             addr_conf = &addr[i].conf;
358
359             break;
360         }
361
362     } else {
363
364         switch (c->local_sockaddr->sa_family) {
365
366 #if (NGX_HAVE_INET6)
367         case AF_INET6:
368             addr6 = (ngx_http_in6_addr_t *) port->addrs;
369             addr_conf = &addr6[0].conf;
370             break;
371 #endif
372
373         default: /* AF_INET */
374             addr = port->addrs;
375             addr_conf = &addr[0].conf;
376             r->in_addr = addr[0].addr;
377             break;
378         }
379     }
380
381     r->virtual_names = addr_conf->virtual_names;
382
383     /* the default server configuration for the address:port */
384     cscf = addr_conf->core_srv_conf;
385
386     r->main_conf = cscf->ctx->main_conf;
387     r->srv_conf = cscf->ctx->srv_conf;
388     r->loc_conf = cscf->ctx->loc_conf;
389
390     rev->handler = ngx_http_process_request_line;
391
392 #if (NGX_HTTP_SSL)
393
394     {
395     ngx_http_ssl_srv_conf_t  *sscf;
396
397     sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
398     if (sscf->enable || addr_conf->ssl) {
399
400         if (c->ssl == NULL) {
401
402             c->log->action = "SSL handshaking";
403
404             if (addr_conf->ssl && sscf->ssl.ctx == NULL) {
405                 ngx_log_error(NGX_LOG_ERR, c->log, 0,
406                               "no \"ssl_certificate\" is defined "
407                               "in server listening on SSL port");
408                 ngx_http_close_connection(c);
409                 return;
410             }
411
412             if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
413                 == NGX_ERROR)
414             {
415                 ngx_http_close_connection(c);
416                 return;
417             }
418
419             rev->handler = ngx_http_ssl_handshake;
420         }
421
422         r->main_filter_need_in_memory = 1;
423     }
424     }
425
426 #endif
427
428     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
429     c->log->file = clcf->err_log->file;
430     if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
431         c->log->log_level = clcf->err_log->log_level;
432     }
433
434     if (c->buffer == NULL) {
435         c->buffer = ngx_create_temp_buf(c->pool,
436                                         cscf->client_header_buffer_size);
437         if (c->buffer == NULL) {
438             ngx_http_close_connection(c);
439             return;
440         }
441     }
442
443     if (r->header_in == NULL) {
444         r->header_in = c->buffer;
445     }
446
447     r->pool = ngx_create_pool(cscf->request_pool_size, c->log);
448     if (r->pool == NULL) {
449         ngx_http_close_connection(c);
450         return;
451     }
452
453
454     if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
455                       sizeof(ngx_table_elt_t))
456         == NGX_ERROR)
457     {
458         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
459         return;
460     }
461
462     r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
463     if (r->ctx == NULL) {
464         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
465         return;
466     }
467
468     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
469
470     r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
471                                         * sizeof(ngx_http_variable_value_t));
472     if (r->variables == NULL) {
473         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
474         return;
475     }
476
477     c->single_connection = 1;
478     c->destroyed = 0;
479
480     r->main = r;
481
482     tp = ngx_timeofday();
483     r->start_sec = tp->sec;
484     r->start_msec = tp->msec;
485
486     r->method = NGX_HTTP_UNKNOWN;
487
488     r->headers_in.content_length_n = -1;
489     r->headers_in.keep_alive_n = -1;
490     r->headers_out.content_length_n = -1;
491     r->headers_out.last_modified_time = -1;
492
493     r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
494     r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;
495
496     r->http_state = NGX_HTTP_READING_REQUEST_STATE;
497
498     ctx = c->log->data;
499     ctx->request = r;
500     ctx->current_request = r;
501     r->log_handler = ngx_http_log_error_handler;
502
503 #if (NGX_STAT_STUB)
504     ngx_atomic_fetch_add(ngx_stat_reading, 1);
505     r->stat_reading = 1;
506     ngx_atomic_fetch_add(ngx_stat_requests, 1);
507 #endif
508
509     rev->handler(rev);
510 }
511
512
513 #if (NGX_HTTP_SSL)
514
515 static void
516 ngx_http_ssl_handshake(ngx_event_t *rev)
517 {
518     u_char               buf[1];
519     ssize_t              n;
520     ngx_int_t            rc;
521     ngx_connection_t    *c;
522     ngx_http_request_t  *r;
523
524     c = rev->data;
525     r = c->data;
526
527     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
528                    "http check ssl handshake");
529
530     if (rev->timedout) {
531         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
532         c->timedout = 1;
533         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
534         return;
535     }
536
537     n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
538
539     if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
540
541         if (!rev->timer_set) {
542             ngx_add_timer(rev, c->listening->post_accept_timeout);
543         }
544
545         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
546             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
547         }
548
549         return;
550     }
551
552     if (n == 1) {
553         if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
554             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
555                            "https ssl handshake: 0x%02Xd", buf[0]);
556
557             rc = ngx_ssl_handshake(c);
558
559             if (rc == NGX_AGAIN) {
560
561                 if (!rev->timer_set) {
562                     ngx_add_timer(rev, c->listening->post_accept_timeout);
563                 }
564
565                 c->ssl->handler = ngx_http_ssl_handshake_handler;
566                 return;
567             }
568
569             ngx_http_ssl_handshake_handler(c);
570
571             return;
572
573         } else {
574             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
575                            "plain http");
576
577             r->plain_http = 1;
578         }
579     }
580
581     c->log->action = "reading client request line";
582
583     rev->handler = ngx_http_process_request_line;
584     ngx_http_process_request_line(rev);
585 }
586
587
588 static void
589 ngx_http_ssl_handshake_handler(ngx_connection_t *c)
590 {
591     ngx_http_request_t  *r;
592
593     if (c->ssl->handshaked) {
594
595         /*
596          * The majority of browsers do not send the "close notify" alert.
597          * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
598          * and Links.  And what is more, MSIE ignores the server's alert.
599          *
600          * Opera and recent Mozilla send the alert.
601          */
602
603         c->ssl->no_wait_shutdown = 1;
604
605         c->read->handler = ngx_http_process_request_line;
606         /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
607
608         ngx_http_process_request_line(c->read);
609
610         return;
611     }
612
613     r = c->data;
614
615     ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
616
617     return;
618 }
619
620 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
621
622 int
623 ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
624 {
625     size_t                    len;
626     const char               *servername;
627     ngx_connection_t         *c;
628     ngx_http_request_t       *r;
629     ngx_http_ssl_srv_conf_t  *sscf;
630
631     servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
632
633     if (servername == NULL) {
634         return SSL_TLSEXT_ERR_NOACK;
635     }
636
637     c = ngx_ssl_get_connection(ssl_conn);
638
639     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
640                    "SSL server name: \"%s\"", servername);
641
642     len = ngx_strlen(servername);
643
644     if (len == 0) {
645         return SSL_TLSEXT_ERR_NOACK;
646     }
647
648     r = c->data;
649
650     if (ngx_http_find_virtual_server(r, (u_char *) servername, len) != NGX_OK) {
651         return SSL_TLSEXT_ERR_NOACK;
652     }
653
654     sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
655
656     SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
657
658     return SSL_TLSEXT_ERR_OK;
659 }
660
661 #endif
662
663 #endif
664
665
666 static void
667 ngx_http_process_request_line(ngx_event_t *rev)
668 {
669     ssize_t                    n;
670     ngx_int_t                  rc, rv;
671     ngx_connection_t          *c;
672     ngx_http_request_t        *r;
673     ngx_http_core_srv_conf_t  *cscf;
674
675     c = rev->data;
676     r = c->data;
677
678     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
679                    "http process request line");
680
681     if (rev->timedout) {
682         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
683         c->timedout = 1;
684         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
685         return;
686     }
687
688     rc = NGX_AGAIN;
689
690     for ( ;; ) {
691
692         if (rc == NGX_AGAIN) {
693             n = ngx_http_read_request_header(r);
694
695             if (n == NGX_AGAIN || n == NGX_ERROR) {
696                 return;
697             }
698         }
699
700         rc = ngx_http_parse_request_line(r, r->header_in);
701
702         if (rc == NGX_OK) {
703
704             /* the request line has been parsed successfully */
705
706             r->request_line.len = r->request_end - r->request_start;
707             r->request_line.data = r->request_start;
708             *r->request_end = '\0';
709
710
711             if (r->args_start) {
712                 r->uri.len = r->args_start - 1 - r->uri_start;
713             } else {
714                 r->uri.len = r->uri_end - r->uri_start;
715             }
716
717
718             if (r->complex_uri || r->quoted_uri) {
719
720                 r->uri.data = ngx_pnalloc(r->pool, r->uri.len + 1);
721                 if (r->uri.data == NULL) {
722                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
723                     return;
724                 }
725
726                 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
727
728                 rc = ngx_http_parse_complex_uri(r, cscf->merge_slashes);
729
730                 if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) {
731                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
732                                   "client sent invalid request");
733                     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
734                     return;
735                 }
736
737             } else {
738                 r->uri.data = r->uri_start;
739             }
740
741
742             r->unparsed_uri.len = r->uri_end - r->uri_start;
743             r->unparsed_uri.data = r->uri_start;
744
745
746             r->method_name.len = r->method_end - r->request_start + 1;
747             r->method_name.data = r->request_line.data;
748
749
750             if (r->http_protocol.data) {
751                 r->http_protocol.len = r->request_end - r->http_protocol.data;
752             }
753
754
755             if (r->uri_ext) {
756                 if (r->args_start) {
757                     r->exten.len = r->args_start - 1 - r->uri_ext;
758                 } else {
759                     r->exten.len = r->uri_end - r->uri_ext;
760                 }
761
762                 r->exten.data = r->uri_ext;
763             }
764
765
766             if (r->args_start && r->uri_end > r->args_start) {
767                 r->args.len = r->uri_end - r->args_start;
768                 r->args.data = r->args_start;
769             }
770
771
772             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
773                            "http request line: \"%V\"", &r->request_line);
774
775             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
776                            "http uri: \"%V\"", &r->uri);
777
778             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
779                            "http args: \"%V\"", &r->args);
780
781             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
782                            "http exten: \"%V\"", &r->exten);
783
784             if (r->host_start && r->host_end) {
785                 n = ngx_http_validate_host(r->host_start,
786                                            r->host_end - r->host_start);
787
788                 if (n <= 0) {
789                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
790                                   "client sent invalid host in request line");
791                     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
792                     return;
793                 }
794
795                 r->headers_in.server.len = n;
796                 r->headers_in.server.data = r->host_start;
797             }
798
799             if (r->http_version < NGX_HTTP_VERSION_10) {
800
801                 if (ngx_http_find_virtual_server(r, r->headers_in.server.data,
802                                                  r->headers_in.server.len)
803                     == NGX_ERROR)
804                 {
805                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
806                     return;
807                 }
808
809                 ngx_http_process_request(r);
810                 return;
811             }
812
813
814             if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
815                               sizeof(ngx_table_elt_t))
816                 == NGX_ERROR)
817             {
818                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
819                 return;
820             }
821
822
823             if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,
824                                sizeof(ngx_table_elt_t *))
825                 == NGX_ERROR)
826             {
827                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
828                 return;
829             }
830
831             c->log->action = "reading client request headers";
832
833             rev->handler = ngx_http_process_request_headers;
834             ngx_http_process_request_headers(rev);
835
836             return;
837         }
838
839         if (rc != NGX_AGAIN) {
840
841             /* there was error while a request line parsing */
842
843             ngx_log_error(NGX_LOG_INFO, c->log, 0,
844                           ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
845             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
846             return;
847         }
848
849         /* NGX_AGAIN: a request line parsing is still incomplete */
850
851         if (r->header_in->pos == r->header_in->end) {
852
853             rv = ngx_http_alloc_large_header_buffer(r, 1);
854
855             if (rv == NGX_ERROR) {
856                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
857                 return;
858             }
859
860             if (rv == NGX_DECLINED) {
861                 r->request_line.len = r->header_in->end - r->request_start;
862                 r->request_line.data = r->request_start;
863
864                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
865                               "client sent too long URI");
866                 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
867                 return;
868             }
869         }
870     }
871 }
872
873
874 static void
875 ngx_http_process_request_headers(ngx_event_t *rev)
876 {
877     ssize_t                     n;
878     ngx_int_t                   rc, rv;
879     ngx_str_t                   header;
880     ngx_table_elt_t            *h;
881     ngx_connection_t           *c;
882     ngx_http_header_t          *hh;
883     ngx_http_request_t         *r;
884     ngx_http_core_srv_conf_t   *cscf;
885     ngx_http_core_main_conf_t  *cmcf;
886
887     c = rev->data;
888     r = c->data;
889
890     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
891                    "http process request header line");
892
893     if (rev->timedout) {
894         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
895         c->timedout = 1;
896         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
897         return;
898     }
899
900     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
901     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
902
903     rc = NGX_AGAIN;
904
905     for ( ;; ) {
906
907         if (rc == NGX_AGAIN) {
908
909             if (r->header_in->pos == r->header_in->end) {
910
911                 rv = ngx_http_alloc_large_header_buffer(r, 0);
912
913                 if (rv == NGX_ERROR) {
914                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
915                     return;
916                 }
917
918                 if (rv == NGX_DECLINED) {
919                     header.len = r->header_in->end - r->header_name_start;
920                     header.data = r->header_name_start;
921
922                     if (header.len > NGX_MAX_ERROR_STR - 300) {
923                         header.len = NGX_MAX_ERROR_STR - 300;
924                         header.data[header.len++] = '.';
925                         header.data[header.len++] = '.';
926                         header.data[header.len++] = '.';
927                     }
928
929                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
930                                   "client sent too long header line: \"%V\"",
931                                   &header);
932                     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
933                     return;
934                 }
935             }
936
937             n = ngx_http_read_request_header(r);
938
939             if (n == NGX_AGAIN || n == NGX_ERROR) {
940                 return;
941             }
942         }
943
944         rc = ngx_http_parse_header_line(r, r->header_in,
945                                         cscf->underscores_in_headers);
946
947         if (rc == NGX_OK) {
948
949             if (r->invalid_header && cscf->ignore_invalid_headers) {
950
951                 /* there was error while a header line parsing */
952
953                 header.len = r->header_end - r->header_name_start;
954                 header.data = r->header_name_start;
955
956                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
957                               "client sent invalid header line: \"%V\"",
958                               &header);
959                 continue;
960             }
961
962             /* a header line has been parsed successfully */
963
964             h = ngx_list_push(&r->headers_in.headers);
965             if (h == NULL) {
966                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
967                 return;
968             }
969
970             h->hash = r->header_hash;
971
972             h->key.len = r->header_name_end - r->header_name_start;
973             h->key.data = r->header_name_start;
974             h->key.data[h->key.len] = '\0';
975
976             h->value.len = r->header_end - r->header_start;
977             h->value.data = r->header_start;
978             h->value.data[h->value.len] = '\0';
979
980             h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
981             if (h->lowcase_key == NULL) {
982                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
983                 return;
984             }
985
986             if (h->key.len == r->lowcase_index) {
987                 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
988
989             } else {
990                 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
991             }
992
993             hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
994                                h->lowcase_key, h->key.len);
995
996             if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
997                 return;
998             }
999
1000             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1001                            "http header: \"%V: %V\"",
1002                            &h->key, &h->value);
1003
1004             continue;
1005         }
1006
1007         if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1008
1009             /* a whole header has been parsed successfully */
1010
1011             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1012                            "http header done");
1013
1014             r->request_length += r->header_in->pos - r->header_in->start;
1015
1016             r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
1017
1018             rc = ngx_http_process_request_header(r);
1019
1020             if (rc != NGX_OK) {
1021                 return;
1022             }
1023
1024             ngx_http_process_request(r);
1025
1026             return;
1027         }
1028
1029         if (rc == NGX_AGAIN) {
1030
1031             /* a header line parsing is still not complete */
1032
1033             continue;
1034         }
1035
1036         /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
1037
1038         header.len = r->header_end - r->header_name_start;
1039         header.data = r->header_name_start;
1040         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1041                       "client sent invalid header line: \"%V\\r...\"",
1042                       &header);
1043         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1044         return;
1045     }
1046 }
1047
1048
1049 static ssize_t
1050 ngx_http_read_request_header(ngx_http_request_t *r)
1051 {
1052     ssize_t                    n;
1053     ngx_event_t               *rev;
1054     ngx_connection_t          *c;
1055     ngx_http_core_srv_conf_t  *cscf;
1056
1057     c = r->connection;
1058     rev = c->read;
1059
1060     n = r->header_in->last - r->header_in->pos;
1061
1062     if (n > 0) {
1063         return n;
1064     }
1065
1066     if (rev->ready) {
1067         n = c->recv(c, r->header_in->last,
1068                     r->header_in->end - r->header_in->last);
1069     } else {
1070         n = NGX_AGAIN;
1071     }
1072
1073     if (n == NGX_AGAIN) {
1074         if (!rev->timer_set) {
1075             cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1076             ngx_add_timer(rev, cscf->client_header_timeout);
1077         }
1078
1079         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1080             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1081             return NGX_ERROR;
1082         }
1083
1084         return NGX_AGAIN;
1085     }
1086
1087     if (n == 0) {
1088         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1089                       "client closed prematurely connection");
1090     }
1091
1092     if (n == 0 || n == NGX_ERROR) {
1093         c->error = 1;
1094         c->log->action = "reading client request headers";
1095
1096         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1097         return NGX_ERROR;
1098     }
1099
1100     r->header_in->last += n;
1101
1102     return n;
1103 }
1104
1105
1106 static ngx_int_t
1107 ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
1108     ngx_uint_t request_line)
1109 {
1110     u_char                    *old, *new;
1111     ngx_buf_t                 *b;
1112     ngx_http_connection_t     *hc;
1113     ngx_http_core_srv_conf_t  *cscf;
1114
1115     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1116                    "http alloc large header buffer");
1117
1118     if (request_line && r->state == 0) {
1119
1120         /* the client fills up the buffer with "\r\n" */
1121
1122         r->request_length += r->header_in->end - r->header_in->start;
1123
1124         r->header_in->pos = r->header_in->start;
1125         r->header_in->last = r->header_in->start;
1126
1127         return NGX_OK;
1128     }
1129
1130     old = request_line ? r->request_start : r->header_name_start;
1131
1132     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1133
1134     if (r->state != 0
1135         && (size_t) (r->header_in->pos - old)
1136                                      >= cscf->large_client_header_buffers.size)
1137     {
1138         return NGX_DECLINED;
1139     }
1140
1141     hc = r->http_connection;
1142
1143     if (hc->nfree) {
1144         b = hc->free[--hc->nfree];
1145
1146         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1147                        "http large header free: %p %uz",
1148                        b->pos, b->end - b->last);
1149
1150     } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
1151
1152         if (hc->busy == NULL) {
1153             hc->busy = ngx_palloc(r->connection->pool,
1154                   cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
1155             if (hc->busy == NULL) {
1156                 return NGX_ERROR;
1157             }
1158         }
1159
1160         b = ngx_create_temp_buf(r->connection->pool,
1161                                 cscf->large_client_header_buffers.size);
1162         if (b == NULL) {
1163             return NGX_ERROR;
1164         }
1165
1166         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1167                        "http large header alloc: %p %uz",
1168                        b->pos, b->end - b->last);
1169
1170     } else {
1171         return NGX_DECLINED;
1172     }
1173
1174     hc->busy[hc->nbusy++] = b;
1175
1176     if (r->state == 0) {
1177         /*
1178          * r->state == 0 means that a header line was parsed successfully
1179          * and we do not need to copy incomplete header line and
1180          * to relocate the parser header pointers
1181          */
1182
1183         r->request_length += r->header_in->end - r->header_in->start;
1184
1185         r->header_in = b;
1186
1187         return NGX_OK;
1188     }
1189
1190     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1191                    "http large header copy: %d", r->header_in->pos - old);
1192
1193     r->request_length += old - r->header_in->start;
1194
1195     new = b->start;
1196
1197     ngx_memcpy(new, old, r->header_in->pos - old);
1198
1199     b->pos = new + (r->header_in->pos - old);
1200     b->last = new + (r->header_in->pos - old);
1201
1202     if (request_line) {
1203         r->request_start = new;
1204
1205         if (r->request_end) {
1206             r->request_end = new + (r->request_end - old);
1207         }
1208
1209         r->method_end = new + (r->method_end - old);
1210
1211         r->uri_start = new + (r->uri_start - old);
1212         r->uri_end = new + (r->uri_end - old);
1213
1214         if (r->schema_start) {
1215             r->schema_start = new + (r->schema_start - old);
1216             r->schema_end = new + (r->schema_end - old);
1217         }
1218
1219         if (r->host_start) {
1220             r->host_start = new + (r->host_start - old);
1221             if (r->host_end) {
1222                 r->host_end = new + (r->host_end - old);
1223             }
1224         }
1225
1226         if (r->port_start) {
1227             r->port_start = new + (r->port_start - old);
1228             r->port_end = new + (r->port_end - old);
1229         }
1230
1231         if (r->uri_ext) {
1232             r->uri_ext = new + (r->uri_ext - old);
1233         }
1234
1235         if (r->args_start) {
1236             r->args_start = new + (r->args_start - old);
1237         }
1238
1239         if (r->http_protocol.data) {
1240             r->http_protocol.data = new + (r->http_protocol.data - old);
1241         }
1242
1243     } else {
1244         r->header_name_start = new;
1245         r->header_name_end = new + (r->header_name_end - old);
1246         r->header_start = new + (r->header_start - old);
1247         r->header_end = new + (r->header_end - old);
1248     }
1249
1250     r->header_in = b;
1251
1252     return NGX_OK;
1253 }
1254
1255
1256 static ngx_int_t
1257 ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1258     ngx_uint_t offset)
1259 {
1260     ngx_table_elt_t  **ph;
1261
1262     ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1263
1264     if (*ph == NULL) {
1265         *ph = h;
1266     }
1267
1268     return NGX_OK;
1269 }
1270
1271
1272 static ngx_int_t
1273 ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1274     ngx_uint_t offset)
1275 {
1276     ngx_table_elt_t  **ph;
1277
1278     ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1279
1280     if (*ph == NULL) {
1281         *ph = h;
1282         return NGX_OK;
1283     }
1284
1285     ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1286                   "client sent duplicate header line: \"%V: %V\", "
1287                   "previous value: \"%V: %V\"",
1288                   &h->key, &h->value, &(*ph)->key, &(*ph)->value);
1289
1290     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1291
1292     return NGX_ERROR;
1293 }
1294
1295
1296 static ngx_int_t
1297 ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
1298     ngx_uint_t offset)
1299 {
1300     ssize_t  len;
1301
1302     if (r->headers_in.host == NULL) {
1303         r->headers_in.host = h;
1304     }
1305
1306     len = ngx_http_validate_host(h->value.data, h->value.len);
1307
1308     if (len <= 0) {
1309         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1310                       "client sent invalid host header");
1311         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1312         return NGX_ERROR;
1313     }
1314
1315     if (r->headers_in.server.len) {
1316         return NGX_OK;
1317     }
1318
1319     r->headers_in.server.len = len;
1320     r->headers_in.server.data = h->value.data;
1321
1322     return NGX_OK;
1323 }
1324
1325
1326 static ngx_int_t
1327 ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
1328     ngx_uint_t offset)
1329 {
1330     if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
1331         r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1332
1333     } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {
1334         r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1335     }
1336
1337     return NGX_OK;
1338 }
1339
1340
1341 static ngx_int_t
1342 ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
1343     ngx_uint_t offset)
1344 {
1345     u_char  *user_agent, *msie;
1346
1347     if (r->headers_in.user_agent) {
1348         return NGX_OK;
1349     }
1350
1351     r->headers_in.user_agent = h;
1352
1353     /* check some widespread browsers while the header is in CPU cache */
1354
1355     user_agent = h->value.data;
1356
1357     msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
1358
1359     if (msie && msie + 7 < user_agent + h->value.len) {
1360
1361         r->headers_in.msie = 1;
1362
1363         if (msie[6] == '.') {
1364
1365             switch (msie[5]) {
1366             case '4':
1367                 r->headers_in.msie4 = 1;
1368                 /* fall through */
1369             case '5':
1370             case '6':
1371                 r->headers_in.msie6 = 1;
1372             }
1373         }
1374
1375 #if 0
1376         /* MSIE ignores the SSL "close notify" alert */
1377         if (c->ssl) {
1378             c->ssl->no_send_shutdown = 1;
1379         }
1380 #endif
1381     }
1382
1383     if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
1384         r->headers_in.opera = 1;
1385         r->headers_in.msie = 0;
1386         r->headers_in.msie4 = 0;
1387         r->headers_in.msie6 = 0;
1388     }
1389
1390     if (!r->headers_in.msie && !r->headers_in.opera) {
1391
1392         if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
1393             r->headers_in.gecko = 1;
1394
1395         } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
1396             r->headers_in.konqueror = 1;
1397         }
1398     }
1399
1400     return NGX_OK;
1401 }
1402
1403
1404 static ngx_int_t
1405 ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
1406     ngx_uint_t offset)
1407 {
1408     ngx_table_elt_t  **cookie;
1409
1410     cookie = ngx_array_push(&r->headers_in.cookies);
1411     if (cookie) {
1412         *cookie = h;
1413         return NGX_OK;
1414     }
1415
1416     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1417
1418     return NGX_ERROR;
1419 }
1420
1421
1422 static ngx_int_t
1423 ngx_http_process_request_header(ngx_http_request_t *r)
1424 {
1425     if (ngx_http_find_virtual_server(r, r->headers_in.server.data,
1426                                      r->headers_in.server.len)
1427         == NGX_ERROR)
1428     {
1429         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1430         return NGX_ERROR;
1431     }
1432
1433     if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) {
1434         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1435                    "client sent HTTP/1.1 request without \"Host\" header");
1436         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1437         return NGX_ERROR;
1438     }
1439
1440     if (r->headers_in.content_length) {
1441         r->headers_in.content_length_n =
1442                             ngx_atoof(r->headers_in.content_length->value.data,
1443                                       r->headers_in.content_length->value.len);
1444
1445         if (r->headers_in.content_length_n == NGX_ERROR) {
1446             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1447                           "client sent invalid \"Content-Length\" header");
1448             ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
1449             return NGX_ERROR;
1450         }
1451     }
1452
1453     if (r->method & NGX_HTTP_PUT && r->headers_in.content_length_n == -1) {
1454         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1455                   "client sent %V method without \"Content-Length\" header",
1456                   &r->method_name);
1457         ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
1458         return NGX_ERROR;
1459     }
1460
1461     if (r->method & NGX_HTTP_TRACE) {
1462         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1463                       "client sent TRACE method");
1464         ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
1465         return NGX_ERROR;
1466     }
1467
1468     if (r->headers_in.transfer_encoding
1469         && ngx_strcasestrn(r->headers_in.transfer_encoding->value.data,
1470                            "chunked", 7 - 1))
1471     {
1472         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1473                       "client sent \"Transfer-Encoding: chunked\" header");
1474         ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
1475         return NGX_ERROR;
1476     }
1477
1478     if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
1479         if (r->headers_in.keep_alive) {
1480             r->headers_in.keep_alive_n =
1481                             ngx_atotm(r->headers_in.keep_alive->value.data,
1482                                       r->headers_in.keep_alive->value.len);
1483         }
1484     }
1485
1486     return NGX_OK;
1487 }
1488
1489
1490 static void
1491 ngx_http_process_request(ngx_http_request_t *r)
1492 {
1493     ngx_connection_t  *c;
1494
1495     c = r->connection;
1496
1497     if (r->plain_http) {
1498         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1499                       "client sent plain HTTP request to HTTPS port");
1500         ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1501         return;
1502     }
1503
1504 #if (NGX_HTTP_SSL)
1505
1506     if (c->ssl) {
1507         long                      rc;
1508         X509                     *cert;
1509         ngx_http_ssl_srv_conf_t  *sscf;
1510
1511         sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
1512
1513         if (sscf->verify == 1) {
1514             rc = SSL_get_verify_result(c->ssl->connection);
1515
1516             if (rc != X509_V_OK) {
1517                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1518                               "client SSL certificate verify error: (%l:%s)",
1519                               rc, X509_verify_cert_error_string(rc));
1520
1521                 ngx_ssl_remove_cached_session(sscf->ssl.ctx,
1522                                        (SSL_get0_session(c->ssl->connection)));
1523
1524                 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
1525                 return;
1526             }
1527
1528             cert = SSL_get_peer_certificate(c->ssl->connection);
1529
1530             if (cert == NULL) {
1531                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1532                               "client sent no required SSL certificate");
1533
1534                 ngx_ssl_remove_cached_session(sscf->ssl.ctx,
1535                                        (SSL_get0_session(c->ssl->connection)));
1536
1537                 ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
1538                 return;
1539             }
1540
1541             X509_free(cert);
1542         }
1543     }
1544
1545 #endif
1546
1547     if (c->read->timer_set) {
1548         ngx_del_timer(c->read);
1549     }
1550
1551 #if (NGX_STAT_STUB)
1552     ngx_atomic_fetch_add(ngx_stat_reading, -1);
1553     r->stat_reading = 0;
1554     ngx_atomic_fetch_add(ngx_stat_writing, 1);
1555     r->stat_writing = 1;
1556 #endif
1557
1558     c->read->handler = ngx_http_request_handler;
1559     c->write->handler = ngx_http_request_handler;
1560     r->read_event_handler = ngx_http_block_reading;
1561
1562     ngx_http_handler(r);
1563
1564     ngx_http_run_posted_requests(c);
1565 }
1566
1567
1568 static ssize_t
1569 ngx_http_validate_host(u_char *host, size_t len)
1570 {
1571     u_char      ch;
1572     size_t      i, last;
1573     ngx_uint_t  dot;
1574
1575     last = len;
1576     dot = 0;
1577
1578     for (i = 0; i < len; i++) {
1579         ch = host[i];
1580
1581         if (ch == '.') {
1582             if (dot) {
1583                 return -1;
1584             }
1585
1586             dot = 1;
1587             continue;
1588         }
1589
1590         dot = 0;
1591
1592         if (ch == ':') {
1593             last = i;
1594             continue;
1595         }
1596
1597         if (ch == '/' || ch == '\0') {
1598             return -1;
1599         }
1600
1601 #if (NGX_WIN32)
1602         if (ch == '\\') {
1603             return -1;
1604         }
1605 #endif
1606     }
1607
1608     if (dot) {
1609         last--;
1610     }
1611
1612     return last;
1613 }
1614
1615
1616 static ngx_int_t
1617 ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len)
1618 {
1619     u_char                    *server;
1620     ngx_uint_t                 hash;
1621     ngx_http_core_loc_conf_t  *clcf;
1622     ngx_http_core_srv_conf_t  *cscf;
1623     u_char                     buf[32];
1624
1625     if (r->virtual_names == NULL) {
1626         return NGX_DECLINED;
1627     }
1628
1629     if (len <= 32) {
1630         server = buf;
1631
1632     } else {
1633         server = ngx_pnalloc(r->pool, len);
1634         if (server == NULL) {
1635             return NGX_ERROR;
1636         }
1637     }
1638
1639     hash = ngx_hash_strlow(server, host, len);
1640
1641     cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, server, len);
1642
1643     if (cscf) {
1644         goto found;
1645     }
1646
1647 #if (NGX_PCRE)
1648
1649     if (r->virtual_names->nregex) {
1650         ngx_int_t                n;
1651         ngx_uint_t               i;
1652         ngx_str_t                name;
1653         ngx_http_server_name_t  *sn;
1654
1655         name.len = len;
1656         name.data = server;
1657
1658         sn = r->virtual_names->regex;
1659
1660         for (i = 0; i < r->virtual_names->nregex; i++) {
1661
1662             n = ngx_regex_exec(sn[i].regex, &name, NULL, 0);
1663
1664             if (n == NGX_REGEX_NO_MATCHED) {
1665                 continue;
1666             }
1667
1668             if (n < 0) {
1669                 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1670                               ngx_regex_exec_n
1671                               " failed: %d on \"%V\" using \"%V\"",
1672                               n, &name, &sn[i].name);
1673                 return NGX_ERROR;
1674             }
1675
1676             /* match */
1677
1678             cscf = sn[i].core_srv_conf;
1679
1680             goto found;
1681         }
1682     }
1683
1684 #endif
1685
1686     return NGX_OK;
1687
1688 found:
1689
1690     r->srv_conf = cscf->ctx->srv_conf;
1691     r->loc_conf = cscf->ctx->loc_conf;
1692
1693     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1694     r->connection->log->file = clcf->err_log->file;
1695
1696     if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1697         r->connection->log->log_level = clcf->err_log->log_level;
1698     }
1699
1700     return NGX_OK;
1701 }
1702
1703
1704 static void
1705 ngx_http_request_handler(ngx_event_t *ev)
1706 {
1707     ngx_connection_t    *c;
1708     ngx_http_request_t  *r;
1709     ngx_http_log_ctx_t  *ctx;
1710
1711     c = ev->data;
1712     r = c->data;
1713
1714     ctx = c->log->data;
1715     ctx->current_request = r;
1716
1717     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1718                    "http run request: \"%V?%V\"", &r->uri, &r->args);
1719
1720     if (ev->write) {
1721         r->write_event_handler(r);
1722
1723     } else {
1724         r->read_event_handler(r);
1725     }
1726
1727     ngx_http_run_posted_requests(c);
1728 }
1729
1730
1731 void
1732 ngx_http_run_posted_requests(ngx_connection_t *c)
1733 {
1734     ngx_http_request_t         *r;
1735     ngx_http_log_ctx_t         *ctx;
1736     ngx_http_posted_request_t  *pr;
1737
1738     for ( ;; ) {
1739
1740         if (c->destroyed) {
1741             return;
1742         }
1743
1744         r = c->data;
1745         pr = r->main->posted_requests;
1746
1747         if (pr == NULL) {
1748             return;
1749         }
1750
1751         r->main->posted_requests = pr->next;
1752
1753         r = pr->request;
1754
1755         ctx = c->log->data;
1756         ctx->current_request = r;
1757
1758         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1759                        "http posted request: \"%V?%V\"", &r->uri, &r->args);
1760
1761         r->write_event_handler(r);
1762     }
1763 }
1764
1765
1766 ngx_int_t
1767 ngx_http_post_request(ngx_http_request_t *r)
1768 {
1769     ngx_http_posted_request_t  *pr, **p;
1770
1771     pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
1772     if (pr == NULL) {
1773         return NGX_ERROR;
1774     }
1775
1776     pr->request = r;
1777     pr->next = NULL;
1778
1779     for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ }
1780
1781     *p = pr;
1782
1783     return NGX_OK;
1784 }
1785
1786
1787 void
1788 ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1789 {
1790     ngx_connection_t          *c;
1791     ngx_http_request_t        *pr;
1792     ngx_http_core_loc_conf_t  *clcf;
1793
1794     if (rc == NGX_DONE) {
1795         /* the request pool may be already destroyed */
1796         return;
1797     }
1798
1799     c = r->connection;
1800
1801     ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0,
1802                    "http finalize request: %d, \"%V?%V\" %d",
1803                    rc, &r->uri, &r->args, r == c->data);
1804
1805     if (rc == NGX_DECLINED) {
1806         r->content_handler = NULL;
1807         r->write_event_handler = ngx_http_core_run_phases;
1808         ngx_http_core_run_phases(r);
1809         return;
1810     }
1811
1812     if (r != r->main && r->post_subrequest) {
1813         rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
1814     }
1815
1816     if (rc == NGX_ERROR
1817         || rc == NGX_HTTP_REQUEST_TIME_OUT
1818         || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
1819         || c->error)
1820     {
1821         if (rc > 0 && r->headers_out.status == 0) {
1822             r->headers_out.status = rc;
1823         }
1824
1825         if (ngx_http_post_action(r) == NGX_OK) {
1826             return;
1827         }
1828
1829         ngx_http_close_request(r, 0);
1830         return;
1831     }
1832
1833     if (rc >= NGX_HTTP_SPECIAL_RESPONSE
1834         || rc == NGX_HTTP_CREATED
1835         || rc == NGX_HTTP_NO_CONTENT)
1836     {
1837         if (rc == NGX_HTTP_CLOSE) {
1838             ngx_http_close_request(r, rc);
1839             return;
1840         }
1841
1842         if (r == r->main) {
1843             if (c->read->timer_set) {
1844                 ngx_del_timer(c->read);
1845             }
1846
1847             if (c->write->timer_set) {
1848                 ngx_del_timer(c->write);
1849             }
1850         }
1851
1852         c->read->handler = ngx_http_request_handler;
1853         c->write->handler = ngx_http_request_handler;
1854
1855         ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
1856         return;
1857     }
1858
1859     if (r != r->main) {
1860
1861         if (r->buffered || r->postponed) {
1862
1863             if (ngx_http_set_write_handler(r) != NGX_OK) {
1864                 ngx_http_close_request(r->main, 0);
1865             }
1866
1867             return;
1868         }
1869
1870 #if (NGX_DEBUG)
1871         if (r != c->data) {
1872             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1873                            "http finalize non-active request: \"%V?%V\"",
1874                            &r->uri, &r->args);
1875         }
1876 #endif
1877
1878         pr = r->parent;
1879
1880         if (r == c->data) {
1881
1882             if (!r->logged) {
1883
1884                 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1885
1886                 if (clcf->log_subrequest) {
1887                     ngx_http_log_request(r);
1888                 }
1889
1890                 r->logged = 1;
1891
1892             } else {
1893                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
1894                               "subrequest: \"%V?%V\" logged again",
1895                               &r->uri, &r->args);
1896             }
1897
1898             r->done = 1;
1899
1900             if (pr->postponed && pr->postponed->request == r) {
1901                 pr->postponed = pr->postponed->next;
1902             }
1903
1904             c->data = pr;
1905
1906         } else {
1907
1908             r->write_event_handler = ngx_http_request_finalizer;
1909
1910             if (r->waited) {
1911                 r->done = 1;
1912             }
1913         }
1914
1915         if (ngx_http_post_request(pr) != NGX_OK) {
1916             ngx_http_close_request(r->main, 0);
1917             return;
1918         }
1919
1920         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1921                        "http wake parent request: \"%V?%V\"",
1922                        &pr->uri, &pr->args);
1923
1924         return;
1925     }
1926
1927     if (r->buffered || c->buffered || r->postponed) {
1928
1929         if (ngx_http_set_write_handler(r) != NGX_OK) {
1930             ngx_http_close_request(r, 0);
1931         }
1932
1933         return;
1934     }
1935
1936     if (r != c->data) {
1937         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
1938                       "http finalize non-active request: \"%V?%V\"",
1939                       &r->uri, &r->args);
1940         return;
1941     }
1942
1943     r->done = 1;
1944
1945     if (!r->post_action) {
1946         r->request_complete = 1;
1947     }
1948
1949     if (ngx_http_post_action(r) == NGX_OK) {
1950         return;
1951     }
1952
1953     if (c->read->timer_set) {
1954         ngx_del_timer(c->read);
1955     }
1956
1957     if (c->write->timer_set) {
1958         c->write->delayed = 0;
1959         ngx_del_timer(c->write);
1960     }
1961
1962     if (c->destroyed) {
1963         return;
1964     }
1965
1966     if (c->read->eof) {
1967         ngx_http_close_request(r, 0);
1968         return;
1969     }
1970
1971     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1972
1973     if (!ngx_terminate
1974          && !ngx_exiting
1975          && r->keepalive
1976          && clcf->keepalive_timeout > 0)
1977     {
1978         ngx_http_set_keepalive(r);
1979         return;
1980
1981     } else if (r->lingering_close && clcf->lingering_timeout > 0) {
1982         ngx_http_set_lingering_close(r);
1983         return;
1984     }
1985
1986     ngx_http_close_request(r, 0);
1987 }
1988
1989
1990 static ngx_int_t
1991 ngx_http_set_write_handler(ngx_http_request_t *r)
1992 {
1993     ngx_event_t               *wev;
1994     ngx_http_core_loc_conf_t  *clcf;
1995
1996     r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
1997
1998     r->read_event_handler = ngx_http_test_reading;
1999     r->write_event_handler = ngx_http_writer;
2000
2001     wev = r->connection->write;
2002
2003     if (wev->ready && wev->delayed) {
2004         return NGX_OK;
2005     }
2006
2007     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2008     if (!wev->delayed) {
2009         ngx_add_timer(wev, clcf->send_timeout);
2010     }
2011
2012     if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2013         ngx_http_close_request(r, 0);
2014         return NGX_ERROR;
2015     }
2016
2017     return NGX_OK;
2018 }
2019
2020
2021 static void
2022 ngx_http_writer(ngx_http_request_t *r)
2023 {
2024     int                        rc;
2025     ngx_event_t               *wev;
2026     ngx_connection_t          *c;
2027     ngx_http_core_loc_conf_t  *clcf;
2028
2029     c = r->connection;
2030     wev = c->write;
2031
2032     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2033                    "http writer handler: \"%V?%V\"", &r->uri, &r->args);
2034
2035     clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
2036
2037     if (wev->timedout) {
2038         if (!wev->delayed) {
2039             ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
2040                           "client timed out");
2041             c->timedout = 1;
2042
2043             ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
2044             return;
2045         }
2046
2047         wev->timedout = 0;
2048         wev->delayed = 0;
2049
2050         if (!wev->ready) {
2051             ngx_add_timer(wev, clcf->send_timeout);
2052
2053             if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2054                 ngx_http_close_request(r, 0);
2055             }
2056
2057             return;
2058         }
2059
2060     } else {
2061         if (wev->delayed) {
2062             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2063                            "http writer delayed");
2064
2065             if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2066                 ngx_http_close_request(r, 0);
2067             }
2068
2069             return;
2070         }
2071     }
2072
2073     rc = ngx_http_output_filter(r, NULL);
2074
2075     if (c->destroyed) {
2076         return;
2077     }
2078
2079     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
2080                    "http writer output filter: %d, \"%V?%V\"",
2081                    rc, &r->uri, &r->args);
2082
2083     if (r->buffered || r->postponed || (r == r->main && c->buffered)) {
2084
2085         if (!wev->ready && !wev->delayed) {
2086             ngx_add_timer(wev, clcf->send_timeout);
2087         }
2088
2089         if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2090             ngx_http_close_request(r, 0);
2091         }
2092
2093         return;
2094     }
2095
2096     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2097                    "http writer done: \"%V?%V\"", &r->uri, &r->args);
2098
2099     ngx_http_finalize_request(r, rc);
2100 }
2101
2102
2103 static void
2104 ngx_http_request_finalizer(ngx_http_request_t *r)
2105 {
2106     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2107                    "http finalizer done: \"%V?%V\"", &r->uri, &r->args);
2108
2109     ngx_http_finalize_request(r, 0);
2110 }
2111
2112
2113 void
2114 ngx_http_block_reading(ngx_http_request_t *r)
2115 {
2116     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2117                    "http reading blocked");
2118
2119     /* aio does not call this handler */
2120
2121     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
2122         && r->connection->read->active)
2123     {
2124         if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) != NGX_OK) {
2125             ngx_http_close_request(r, 0);
2126         }
2127     }
2128 }
2129
2130
2131 void
2132 ngx_http_test_reading(ngx_http_request_t *r)
2133 {
2134     int                n;
2135     char               buf[1];
2136     ngx_err_t          err;
2137     ngx_event_t       *rev;
2138     ngx_connection_t  *c;
2139
2140     c = r->connection;
2141     rev = c->read;
2142
2143     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading");
2144
2145 #if (NGX_HAVE_KQUEUE)
2146
2147     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2148
2149         if (!rev->pending_eof) {
2150             return;
2151         }
2152
2153         rev->eof = 1;
2154         c->error = 1;
2155         err = rev->kq_errno;
2156
2157         goto closed;
2158     }
2159
2160 #endif
2161
2162     n = recv(c->fd, buf, 1, MSG_PEEK);
2163
2164     if (n == 0) {
2165         rev->eof = 1;
2166         c->error = 1;
2167         err = 0;
2168
2169         goto closed;
2170
2171     } else if (n == -1) {
2172         err = ngx_socket_errno;
2173
2174         if (err != NGX_EAGAIN) {
2175             rev->eof = 1;
2176             c->error = 1;
2177
2178             goto closed;
2179         }
2180     }
2181
2182     /* aio does not call this handler */
2183
2184     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
2185
2186         if (ngx_del_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
2187             ngx_http_close_request(r, 0);
2188         }
2189     }
2190
2191     return;
2192
2193 closed:
2194
2195     if (err) {
2196         rev->error = 1;
2197     }
2198
2199     ngx_log_error(NGX_LOG_INFO, c->log, err,
2200                   "client closed prematurely connection");
2201
2202     ngx_http_finalize_request(r, 0);
2203 }
2204
2205
2206 static void
2207 ngx_http_set_keepalive(ngx_http_request_t *r)
2208 {
2209     int                        tcp_nodelay;
2210     ngx_int_t                  i;
2211     ngx_buf_t                 *b, *f;
2212     ngx_event_t               *rev, *wev;
2213     ngx_connection_t          *c;
2214     ngx_http_connection_t     *hc;
2215     ngx_http_core_srv_conf_t  *cscf;
2216     ngx_http_core_loc_conf_t  *clcf;
2217
2218     c = r->connection;
2219     rev = c->read;
2220
2221     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2222
2223     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
2224
2225     if (r->discard_body) {
2226         r->write_event_handler = ngx_http_request_empty_handler;
2227         r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
2228         ngx_add_timer(rev, clcf->lingering_timeout);
2229         return;
2230     }
2231
2232     c->log->action = "closing request";
2233
2234     hc = r->http_connection;
2235     b = r->header_in;
2236
2237     if (b->pos < b->last) {
2238
2239         /* the pipelined request */
2240
2241         if (b != c->buffer) {
2242
2243             /*
2244              * If the large header buffers were allocated while the previous
2245              * request processing then we do not use c->buffer for
2246              * the pipelined request (see ngx_http_init_request()).
2247              *
2248              * Now we would move the large header buffers to the free list.
2249              */
2250
2251             cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2252
2253             if (hc->free == NULL) {
2254                 hc->free = ngx_palloc(c->pool,
2255                   cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
2256
2257                 if (hc->free == NULL) {
2258                     ngx_http_close_request(r, 0);
2259                     return;
2260                 }
2261             }
2262
2263             for (i = 0; i < hc->nbusy - 1; i++) {
2264                 f = hc->busy[i];
2265                 hc->free[hc->nfree++] = f;
2266                 f->pos = f->start;
2267                 f->last = f->start;
2268             }
2269
2270             hc->busy[0] = b;
2271             hc->nbusy = 1;
2272         }
2273     }
2274
2275     ngx_http_request_done(r, 0);
2276
2277     c->data = hc;
2278
2279     ngx_add_timer(rev, clcf->keepalive_timeout);
2280
2281     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2282         ngx_http_close_connection(c);
2283         return;
2284     }
2285
2286     wev = c->write;
2287     wev->handler = ngx_http_empty_handler;
2288
2289     if (b->pos < b->last) {
2290
2291         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
2292
2293 #if (NGX_STAT_STUB)
2294         ngx_atomic_fetch_add(ngx_stat_reading, 1);
2295 #endif
2296
2297         hc->pipeline = 1;
2298         c->log->action = "reading client pipelined request line";
2299
2300         rev->handler = ngx_http_init_request;
2301         ngx_post_event(rev, &ngx_posted_events);
2302         return;
2303     }
2304
2305     hc->pipeline = 0;
2306
2307     /*
2308      * To keep a memory footprint as small as possible for an idle
2309      * keepalive connection we try to free the ngx_http_request_t and
2310      * c->buffer's memory if they were allocated outside the c->pool.
2311      * The large header buffers are always allocated outside the c->pool and
2312      * are freed too.
2313      */
2314
2315     if (ngx_pfree(c->pool, r) == NGX_OK) {
2316         hc->request = NULL;
2317     }
2318
2319     b = c->buffer;
2320
2321     if (ngx_pfree(c->pool, b->start) == NGX_OK) {
2322
2323         /*
2324          * the special note for ngx_http_keepalive_handler() that
2325          * c->buffer's memory was freed
2326          */
2327
2328         b->pos = NULL;
2329
2330     } else {
2331         b->pos = b->start;
2332         b->last = b->start;
2333     }
2334
2335     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",
2336                    hc->free, hc->nfree);
2337
2338     if (hc->free) {
2339         for (i = 0; i < hc->nfree; i++) {
2340             ngx_pfree(c->pool, hc->free[i]->start);
2341             hc->free[i] = NULL;
2342         }
2343
2344         hc->nfree = 0;
2345     }
2346
2347     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",
2348                    hc->busy, hc->nbusy);
2349
2350     if (hc->busy) {
2351         for (i = 0; i < hc->nbusy; i++) {
2352             ngx_pfree(c->pool, hc->busy[i]->start);
2353             hc->busy[i] = NULL;
2354         }
2355
2356         hc->nbusy = 0;
2357     }
2358
2359 #if (NGX_HTTP_SSL)
2360     if (c->ssl) {
2361         ngx_ssl_free_buffer(c);
2362     }
2363 #endif
2364
2365     rev->handler = ngx_http_keepalive_handler;
2366
2367     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2368         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
2369             ngx_http_close_connection(c);
2370             return;
2371         }
2372     }
2373
2374     c->log->action = "keepalive";
2375
2376     if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
2377         if (ngx_tcp_push(c->fd) == -1) {
2378             ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
2379             ngx_http_close_connection(c);
2380             return;
2381         }
2382
2383         c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
2384         tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
2385
2386     } else {
2387         tcp_nodelay = 1;
2388     }
2389
2390     if (tcp_nodelay
2391         && clcf->tcp_nodelay
2392         && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
2393     {
2394         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
2395
2396         if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
2397                        (const void *) &tcp_nodelay, sizeof(int))
2398             == -1)
2399         {
2400             ngx_connection_error(c, ngx_socket_errno,
2401                                  "setsockopt(TCP_NODELAY) failed");
2402             ngx_http_close_connection(c);
2403             return;
2404         }
2405
2406         c->tcp_nodelay = NGX_TCP_NODELAY_SET;
2407     }
2408
2409 #if 0
2410     /* if ngx_http_request_t was freed then we need some other place */
2411     r->http_state = NGX_HTTP_KEEPALIVE_STATE;
2412 #endif
2413
2414     c->idle = 1;
2415
2416     if (rev->ready) {
2417         ngx_post_event(rev, &ngx_posted_events);
2418     }
2419 }
2420
2421
2422 static void
2423 ngx_http_keepalive_handler(ngx_event_t *rev)
2424 {
2425     size_t             size;
2426     ssize_t            n;
2427     ngx_buf_t         *b;
2428     ngx_connection_t  *c;
2429
2430     c = rev->data;
2431
2432     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
2433
2434     if (rev->timedout || c->close) {
2435         ngx_http_close_connection(c);
2436         return;
2437     }
2438
2439 #if (NGX_HAVE_KQUEUE)
2440
2441     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2442         if (rev->pending_eof) {
2443             c->log->handler = NULL;
2444             ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
2445                           "kevent() reported that client %V closed "
2446                           "keepalive connection", &c->addr_text);
2447 #if (NGX_HTTP_SSL)
2448             if (c->ssl) {
2449                 c->ssl->no_send_shutdown = 1;
2450             }
2451 #endif
2452             ngx_http_close_connection(c);
2453             return;
2454         }
2455     }
2456
2457 #endif
2458
2459     b = c->buffer;
2460     size = b->end - b->start;
2461
2462     if (b->pos == NULL) {
2463
2464         /*
2465          * The c->buffer's memory was freed by ngx_http_set_keepalive().
2466          * However, the c->buffer->start and c->buffer->end were not changed
2467          * to keep the buffer size.
2468          */
2469
2470         b->pos = ngx_palloc(c->pool, size);
2471         if (b->pos == NULL) {
2472             ngx_http_close_connection(c);
2473             return;
2474         }
2475
2476         b->start = b->pos;
2477         b->last = b->pos;
2478         b->end = b->pos + size;
2479     }
2480
2481     /*
2482      * MSIE closes a keepalive connection with RST flag
2483      * so we ignore ECONNRESET here.
2484      */
2485
2486     c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
2487     ngx_set_socket_errno(0);
2488
2489     n = c->recv(c, b->last, size);
2490     c->log_error = NGX_ERROR_INFO;
2491
2492     if (n == NGX_AGAIN) {
2493         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2494             ngx_http_close_connection(c);
2495         }
2496
2497         return;
2498     }
2499
2500     if (n == NGX_ERROR) {
2501         ngx_http_close_connection(c);
2502         return;
2503     }
2504
2505     c->log->handler = NULL;
2506
2507     if (n == 0) {
2508         ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
2509                       "client %V closed keepalive connection", &c->addr_text);
2510         ngx_http_close_connection(c);
2511         return;
2512     }
2513
2514     b->last += n;
2515
2516 #if (NGX_STAT_STUB)
2517     ngx_atomic_fetch_add(ngx_stat_reading, 1);
2518 #endif
2519
2520     c->log->handler = ngx_http_log_error;
2521     c->log->action = "reading client request line";
2522
2523     c->idle = 0;
2524
2525     ngx_http_init_request(rev);
2526 }
2527
2528
2529 static void
2530 ngx_http_set_lingering_close(ngx_http_request_t *r)
2531 {
2532     ngx_event_t               *rev, *wev;
2533     ngx_connection_t          *c;
2534     ngx_http_core_loc_conf_t  *clcf;
2535
2536     c = r->connection;
2537
2538     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2539
2540     rev = c->read;
2541     rev->handler = ngx_http_lingering_close_handler;
2542
2543     r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
2544     ngx_add_timer(rev, clcf->lingering_timeout);
2545
2546     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2547         ngx_http_close_request(r, 0);
2548         return;
2549     }
2550
2551     wev = c->write;
2552     wev->handler = ngx_http_empty_handler;
2553
2554     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2555         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
2556             ngx_http_close_request(r, 0);
2557             return;
2558         }
2559     }
2560
2561     if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
2562         ngx_connection_error(c, ngx_socket_errno,
2563                              ngx_shutdown_socket_n " failed");
2564         ngx_http_close_request(r, 0);
2565         return;
2566     }
2567
2568     if (rev->ready) {
2569         ngx_http_lingering_close_handler(rev);
2570     }
2571 }
2572
2573
2574 static void
2575 ngx_http_lingering_close_handler(ngx_event_t *rev)
2576 {
2577     ssize_t                    n;
2578     ngx_msec_t                 timer;
2579     ngx_connection_t          *c;
2580     ngx_http_request_t        *r;
2581     ngx_http_core_loc_conf_t  *clcf;
2582     u_char                     buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
2583
2584     c = rev->data;
2585     r = c->data;
2586
2587     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2588                    "http lingering close handler");
2589
2590     if (rev->timedout) {
2591         c->timedout = 1;
2592         ngx_http_close_request(r, 0);
2593         return;
2594     }
2595
2596     timer = (ngx_msec_t) (r->lingering_time - ngx_time());
2597     if (timer <= 0) {
2598         ngx_http_close_request(r, 0);
2599         return;
2600     }
2601
2602     do {
2603         n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
2604
2605         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
2606
2607         if (n == NGX_ERROR || n == 0) {
2608             ngx_http_close_request(r, 0);
2609             return;
2610         }
2611
2612     } while (rev->ready);
2613
2614     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2615         ngx_http_close_request(r, 0);
2616         return;
2617     }
2618
2619     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2620
2621     timer *= 1000;
2622
2623     if (timer > clcf->lingering_timeout) {
2624         timer = clcf->lingering_timeout;
2625     }
2626
2627     ngx_add_timer(rev, timer);
2628 }
2629
2630
2631 void
2632 ngx_http_empty_handler(ngx_event_t *wev)
2633 {
2634     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
2635
2636     return;
2637 }
2638
2639
2640 void
2641 ngx_http_request_empty_handler(ngx_http_request_t *r)
2642 {
2643     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2644                    "http request empty handler");
2645
2646     return;
2647 }
2648
2649
2650 ngx_int_t
2651 ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
2652 {
2653     ngx_buf_t    *b;
2654     ngx_chain_t   out;
2655
2656     b = ngx_calloc_buf(r->pool);
2657     if (b == NULL) {
2658         return NGX_ERROR;
2659     }
2660
2661     if (flags & NGX_HTTP_LAST) {
2662         b->last_buf = 1;
2663     }
2664
2665     if (flags & NGX_HTTP_FLUSH) {
2666         b->flush = 1;
2667     }
2668
2669     out.buf = b;
2670     out.next = NULL;
2671
2672     return ngx_http_output_filter(r, &out);
2673 }
2674
2675
2676 static ngx_int_t
2677 ngx_http_post_action(ngx_http_request_t *r)
2678 {
2679     ngx_http_core_loc_conf_t  *clcf;
2680
2681     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2682
2683     if (clcf->post_action.data == NULL) {
2684         return NGX_DECLINED;
2685     }
2686
2687     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2688                    "post action: \"%V\"", &clcf->post_action);
2689
2690     r->http_version = NGX_HTTP_VERSION_9;
2691     r->header_only = 1;
2692     r->post_action = 1;
2693
2694     r->read_event_handler = ngx_http_block_reading;
2695
2696     if (clcf->post_action.data[0] == '/') {
2697         ngx_http_internal_redirect(r, &clcf->post_action, NULL);
2698
2699     } else {
2700         ngx_http_named_location(r, &clcf->post_action);
2701     }
2702
2703     return NGX_OK;
2704 }
2705
2706
2707 static void
2708 ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error)
2709 {
2710     ngx_connection_t  *c;
2711
2712     c = r->connection;
2713
2714     ngx_http_request_done(r->main, error);
2715     ngx_http_close_connection(c);
2716 }
2717
2718
2719 static void
2720 ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error)
2721 {
2722     ngx_log_t                 *log;
2723     struct linger              linger;
2724     ngx_http_cleanup_t        *cln;
2725     ngx_http_log_ctx_t        *ctx;
2726     ngx_http_core_loc_conf_t  *clcf;
2727
2728     log = r->connection->log;
2729
2730     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
2731
2732     if (r->pool == NULL) {
2733         ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
2734         return;
2735     }
2736
2737     for (cln = r->cleanup; cln; cln = cln->next) {
2738         if (cln->handler) {
2739             cln->handler(cln->data);
2740         }
2741     }
2742
2743 #if (NGX_STAT_STUB)
2744
2745     if (r->stat_reading) {
2746         ngx_atomic_fetch_add(ngx_stat_reading, -1);
2747     }
2748
2749     if (r->stat_writing) {
2750         ngx_atomic_fetch_add(ngx_stat_writing, -1);
2751     }
2752
2753 #endif
2754
2755     if (error && r->headers_out.status == 0) {
2756         r->headers_out.status = error;
2757     }
2758
2759     log->action = "logging request";
2760
2761     ngx_http_log_request(r);
2762
2763     log->action = "closing request";
2764
2765     if (r->connection->timedout) {
2766         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2767
2768         if (clcf->reset_timedout_connection) {
2769             linger.l_onoff = 1;
2770             linger.l_linger = 0;
2771
2772             if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
2773                            (const void *) &linger, sizeof(struct linger)) == -1)
2774             {
2775                 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
2776                               "setsockopt(SO_LINGER) failed");
2777             }
2778         }
2779     }
2780
2781     /* the various request strings were allocated from r->pool */
2782     ctx = log->data;
2783     ctx->request = NULL;
2784
2785     r->request_line.len = 0;
2786
2787     r->connection->destroyed = 1;
2788
2789     ngx_destroy_pool(r->pool);
2790 }
2791
2792
2793 static void
2794 ngx_http_log_request(ngx_http_request_t *r)
2795 {
2796     ngx_uint_t                  i, n;
2797     ngx_http_handler_pt        *log_handler;
2798     ngx_http_core_main_conf_t  *cmcf;
2799
2800     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2801
2802     log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
2803     n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
2804
2805     for (i = 0; i < n; i++) {
2806         log_handler[i](r);
2807     }
2808 }
2809
2810
2811 static void
2812 ngx_http_close_connection(ngx_connection_t *c)
2813 {
2814     ngx_pool_t  *pool;
2815
2816     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
2817                    "close http connection: %d", c->fd);
2818
2819 #if (NGX_HTTP_SSL)
2820
2821     if (c->ssl) {
2822         if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
2823             c->ssl->handler = ngx_http_close_connection;
2824             return;
2825         }
2826     }
2827
2828 #endif
2829
2830 #if (NGX_STAT_STUB)
2831     ngx_atomic_fetch_add(ngx_stat_active, -1);
2832 #endif
2833
2834     c->destroyed = 1;
2835
2836     pool = c->pool;
2837
2838     ngx_close_connection(c);
2839
2840     ngx_destroy_pool(pool);
2841 }
2842
2843
2844 static u_char *
2845 ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
2846 {
2847     u_char              *p;
2848     ngx_http_request_t  *r;
2849     ngx_http_log_ctx_t  *ctx;
2850
2851     if (log->action) {
2852         p = ngx_snprintf(buf, len, " while %s", log->action);
2853         len -= p - buf;
2854         buf = p;
2855     }
2856
2857     ctx = log->data;
2858
2859     p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text);
2860     len -= p - buf;
2861
2862     r = ctx->request;
2863
2864     if (r) {
2865         return r->log_handler(r, ctx->current_request, p, len);
2866
2867     } else {
2868         p = ngx_snprintf(p, len, ", server: %V",
2869                          &ctx->connection->listening->addr_text);
2870     }
2871
2872     return p;
2873 }
2874
2875
2876 static u_char *
2877 ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
2878     u_char *buf, size_t len)
2879 {
2880     char                      *uri_separator;
2881     u_char                    *p;
2882     ngx_http_upstream_t       *u;
2883     ngx_http_core_srv_conf_t  *cscf;
2884
2885     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2886
2887     p = ngx_snprintf(buf, len, ", server: %V", &cscf->server_name);
2888     len -= p - buf;
2889     buf = p;
2890
2891     if (r->request_line.data == NULL && r->request_start) {
2892         for (p = r->request_start; p < r->header_in->last; p++) {
2893             if (*p == CR || *p == LF) {
2894                 break;
2895             }
2896         }
2897
2898         r->request_line.len = p - r->request_start;
2899         r->request_line.data = r->request_start;
2900     }
2901
2902     if (r->request_line.len) {
2903         p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
2904         len -= p - buf;
2905         buf = p;
2906     }
2907
2908     if (r != sr) {
2909         p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
2910         len -= p - buf;
2911         buf = p;
2912     }
2913
2914     u = sr->upstream;
2915
2916     if (u && u->peer.name) {
2917
2918         uri_separator = "";
2919
2920 #if (NGX_HAVE_UNIX_DOMAIN)
2921         if (u->peer.sockaddr && u->peer.sockaddr->sa_family == AF_UNIX) {
2922             uri_separator = ":";
2923         }
2924 #endif
2925
2926         p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
2927                          &u->schema, u->peer.name,
2928                          uri_separator, &u->uri);
2929         len -= p - buf;
2930         buf = p;
2931     }
2932
2933     if (r->headers_in.host) {
2934         p = ngx_snprintf(buf, len, ", host: \"%V\"",
2935                          &r->headers_in.host->value);
2936         len -= p - buf;
2937         buf = p;
2938     }
2939
2940     if (r->headers_in.referer) {
2941         p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
2942                          &r->headers_in.referer->value);
2943         buf = p;
2944     }
2945
2946     return buf;
2947 }