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