nginx 0.8.16
[nginx-catap.git] / src / http / ngx_http_request.c
blob07afe676df8a0bd3f561320199e7912f5dd79707
2 /*
3 * Copyright (C) Igor Sysoev
4 */
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_http.h>
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);
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);
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);
38 static void ngx_http_request_handler(ngx_event_t *ev);
39 static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc);
40 static void ngx_http_terminate_handler(ngx_http_request_t *r);
41 static void ngx_http_finalize_connection(ngx_http_request_t *r);
42 static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
43 static void ngx_http_writer(ngx_http_request_t *r);
44 static void ngx_http_request_finalizer(ngx_http_request_t *r);
46 static void ngx_http_set_keepalive(ngx_http_request_t *r);
47 static void ngx_http_keepalive_handler(ngx_event_t *ev);
48 static void ngx_http_set_lingering_close(ngx_http_request_t *r);
49 static void ngx_http_lingering_close_handler(ngx_event_t *ev);
50 static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
51 static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
52 static void ngx_http_free_request(ngx_http_request_t *r, ngx_int_t error);
53 static void ngx_http_log_request(ngx_http_request_t *r);
54 static void ngx_http_close_connection(ngx_connection_t *c);
56 static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
57 static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
58 ngx_http_request_t *sr, u_char *buf, size_t len);
60 #if (NGX_HTTP_SSL)
61 static void ngx_http_ssl_handshake(ngx_event_t *rev);
62 static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
63 #endif
66 static char *ngx_http_client_errors[] = {
68 /* NGX_HTTP_PARSE_INVALID_METHOD */
69 "client sent invalid method",
71 /* NGX_HTTP_PARSE_INVALID_REQUEST */
72 "client sent invalid request",
74 /* NGX_HTTP_PARSE_INVALID_09_METHOD */
75 "client sent invalid method in HTTP/0.9 request"
79 ngx_http_header_t ngx_http_headers_in[] = {
80 { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
81 ngx_http_process_host },
83 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
84 ngx_http_process_connection },
86 { ngx_string("If-Modified-Since"),
87 offsetof(ngx_http_headers_in_t, if_modified_since),
88 ngx_http_process_unique_header_line },
90 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
91 ngx_http_process_user_agent },
93 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
94 ngx_http_process_header_line },
96 { ngx_string("Content-Length"),
97 offsetof(ngx_http_headers_in_t, content_length),
98 ngx_http_process_unique_header_line },
100 { ngx_string("Content-Type"),
101 offsetof(ngx_http_headers_in_t, content_type),
102 ngx_http_process_header_line },
104 { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
105 ngx_http_process_header_line },
107 { ngx_string("If-Range"),
108 offsetof(ngx_http_headers_in_t, if_range),
109 ngx_http_process_unique_header_line },
111 { ngx_string("Transfer-Encoding"),
112 offsetof(ngx_http_headers_in_t, transfer_encoding),
113 ngx_http_process_header_line },
115 { ngx_string("Expect"),
116 offsetof(ngx_http_headers_in_t, expect),
117 ngx_http_process_unique_header_line },
119 #if (NGX_HTTP_GZIP)
120 { ngx_string("Accept-Encoding"),
121 offsetof(ngx_http_headers_in_t, accept_encoding),
122 ngx_http_process_header_line },
124 { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
125 ngx_http_process_header_line },
126 #endif
128 { ngx_string("Authorization"),
129 offsetof(ngx_http_headers_in_t, authorization),
130 ngx_http_process_unique_header_line },
132 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
133 ngx_http_process_header_line },
135 #if (NGX_HTTP_PROXY || NGX_HTTP_REALIP || NGX_HTTP_GEO)
136 { ngx_string("X-Forwarded-For"),
137 offsetof(ngx_http_headers_in_t, x_forwarded_for),
138 ngx_http_process_header_line },
139 #endif
141 #if (NGX_HTTP_REALIP)
142 { ngx_string("X-Real-IP"),
143 offsetof(ngx_http_headers_in_t, x_real_ip),
144 ngx_http_process_header_line },
145 #endif
147 #if (NGX_HTTP_HEADERS)
148 { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
149 ngx_http_process_header_line },
151 { ngx_string("Accept-Language"),
152 offsetof(ngx_http_headers_in_t, accept_language),
153 ngx_http_process_header_line },
154 #endif
156 #if (NGX_HTTP_DAV)
157 { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
158 ngx_http_process_header_line },
160 { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
161 ngx_http_process_header_line },
163 { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),
164 ngx_http_process_header_line },
166 { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
167 ngx_http_process_header_line },
168 #endif
170 { ngx_string("Cookie"), 0, ngx_http_process_cookie },
172 { ngx_null_string, 0, NULL }
176 void
177 ngx_http_init_connection(ngx_connection_t *c)
179 ngx_event_t *rev;
180 ngx_http_log_ctx_t *ctx;
182 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
183 if (ctx == NULL) {
184 ngx_http_close_connection(c);
185 return;
188 ctx->connection = c;
189 ctx->request = NULL;
190 ctx->current_request = NULL;
192 c->log->connection = c->number;
193 c->log->handler = ngx_http_log_error;
194 c->log->data = ctx;
195 c->log->action = "reading client request line";
197 c->log_error = NGX_ERROR_INFO;
199 rev = c->read;
200 rev->handler = ngx_http_init_request;
201 c->write->handler = ngx_http_empty_handler;
203 #if (NGX_STAT_STUB)
204 (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
205 #endif
207 if (rev->ready) {
208 /* the deferred accept(), rtsig, aio, iocp */
210 if (ngx_use_accept_mutex) {
211 ngx_post_event(rev, &ngx_posted_events);
212 return;
215 ngx_http_init_request(rev);
216 return;
219 ngx_add_timer(rev, c->listening->post_accept_timeout);
221 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
222 #if (NGX_STAT_STUB)
223 (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
224 #endif
225 ngx_http_close_connection(c);
226 return;
231 static void
232 ngx_http_init_request(ngx_event_t *rev)
234 ngx_time_t *tp;
235 ngx_uint_t i;
236 ngx_connection_t *c;
237 ngx_http_request_t *r;
238 struct sockaddr_in *sin;
239 ngx_http_port_t *port;
240 ngx_http_in_addr_t *addr;
241 ngx_http_log_ctx_t *ctx;
242 ngx_http_addr_conf_t *addr_conf;
243 ngx_http_connection_t *hc;
244 ngx_http_core_srv_conf_t *cscf;
245 ngx_http_core_loc_conf_t *clcf;
246 ngx_http_core_main_conf_t *cmcf;
247 #if (NGX_HAVE_INET6)
248 struct sockaddr_in6 *sin6;
249 ngx_http_in6_addr_t *addr6;
250 #endif
252 #if (NGX_STAT_STUB)
253 (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
254 #endif
256 c = rev->data;
258 if (rev->timedout) {
259 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
261 ngx_http_close_connection(c);
262 return;
265 c->requests++;
267 hc = c->data;
269 if (hc == NULL) {
270 hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
271 if (hc == NULL) {
272 ngx_http_close_connection(c);
273 return;
277 r = hc->request;
279 if (r) {
280 ngx_memzero(r, sizeof(ngx_http_request_t));
282 r->pipeline = hc->pipeline;
284 if (hc->nbusy) {
285 r->header_in = hc->busy[0];
288 } else {
289 r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
290 if (r == NULL) {
291 ngx_http_close_connection(c);
292 return;
295 hc->request = r;
298 c->data = r;
299 r->http_connection = hc;
301 c->sent = 0;
302 r->signature = NGX_HTTP_MODULE;
304 /* find the server configuration for the address:port */
306 port = c->listening->servers;
308 r->connection = c;
310 if (port->naddrs > 1) {
313 * there are several addresses on this port and one of them
314 * is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
315 * is required to determine a server address
318 if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
319 ngx_http_close_connection(c);
320 return;
323 switch (c->local_sockaddr->sa_family) {
325 #if (NGX_HAVE_INET6)
326 case AF_INET6:
327 sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
329 addr6 = port->addrs;
331 /* the last address is "*" */
333 for (i = 0; i < port->naddrs - 1; i++) {
334 if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
335 break;
339 addr_conf = &addr6[i].conf;
341 break;
342 #endif
344 default: /* AF_INET */
345 sin = (struct sockaddr_in *) c->local_sockaddr;
347 addr = port->addrs;
349 /* the last address is "*" */
351 for (i = 0; i < port->naddrs - 1; i++) {
352 if (addr[i].addr == sin->sin_addr.s_addr) {
353 break;
357 addr_conf = &addr[i].conf;
359 break;
362 } else {
364 switch (c->local_sockaddr->sa_family) {
366 #if (NGX_HAVE_INET6)
367 case AF_INET6:
368 addr6 = port->addrs;
369 addr_conf = &addr6[0].conf;
370 break;
371 #endif
373 default: /* AF_INET */
374 addr = port->addrs;
375 addr_conf = &addr[0].conf;
376 break;
380 r->virtual_names = addr_conf->virtual_names;
382 /* the default server configuration for the address:port */
383 cscf = addr_conf->core_srv_conf;
385 r->main_conf = cscf->ctx->main_conf;
386 r->srv_conf = cscf->ctx->srv_conf;
387 r->loc_conf = cscf->ctx->loc_conf;
389 rev->handler = ngx_http_process_request_line;
390 r->read_event_handler = ngx_http_block_reading;
392 #if (NGX_HTTP_SSL)
395 ngx_http_ssl_srv_conf_t *sscf;
397 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
398 if (sscf->enable || addr_conf->ssl) {
400 if (c->ssl == NULL) {
402 c->log->action = "SSL handshaking";
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;
412 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
413 != NGX_OK)
415 ngx_http_close_connection(c);
416 return;
419 rev->handler = ngx_http_ssl_handshake;
422 r->main_filter_need_in_memory = 1;
426 #endif
428 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
429 c->log->file = clcf->error_log->file;
430 if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
431 c->log->log_level = clcf->error_log->log_level;
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;
443 if (r->header_in == NULL) {
444 r->header_in = c->buffer;
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;
454 if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
455 sizeof(ngx_table_elt_t))
456 != NGX_OK)
458 ngx_destroy_pool(r->pool);
459 ngx_http_close_connection(c);
460 return;
463 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
464 if (r->ctx == NULL) {
465 ngx_destroy_pool(r->pool);
466 ngx_http_close_connection(c);
467 return;
470 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
472 r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
473 * sizeof(ngx_http_variable_value_t));
474 if (r->variables == NULL) {
475 ngx_destroy_pool(r->pool);
476 ngx_http_close_connection(c);
477 return;
480 c->single_connection = 1;
481 c->destroyed = 0;
483 r->main = r;
484 r->count = 1;
486 tp = ngx_timeofday();
487 r->start_sec = tp->sec;
488 r->start_msec = tp->msec;
490 r->method = NGX_HTTP_UNKNOWN;
492 r->headers_in.content_length_n = -1;
493 r->headers_in.keep_alive_n = -1;
494 r->headers_out.content_length_n = -1;
495 r->headers_out.last_modified_time = -1;
497 r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
498 r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;
500 r->http_state = NGX_HTTP_READING_REQUEST_STATE;
502 ctx = c->log->data;
503 ctx->request = r;
504 ctx->current_request = r;
505 r->log_handler = ngx_http_log_error_handler;
507 #if (NGX_STAT_STUB)
508 (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
509 r->stat_reading = 1;
510 (void) ngx_atomic_fetch_add(ngx_stat_requests, 1);
511 #endif
513 rev->handler(rev);
517 #if (NGX_HTTP_SSL)
519 static void
520 ngx_http_ssl_handshake(ngx_event_t *rev)
522 u_char buf[1];
523 ssize_t n;
524 ngx_int_t rc;
525 ngx_connection_t *c;
526 ngx_http_request_t *r;
528 c = rev->data;
529 r = c->data;
531 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
532 "http check ssl handshake");
534 if (rev->timedout) {
535 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
536 c->timedout = 1;
537 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
538 return;
541 n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
543 if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
545 if (!rev->timer_set) {
546 ngx_add_timer(rev, c->listening->post_accept_timeout);
549 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
550 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
553 return;
556 if (n == 1) {
557 if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
558 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
559 "https ssl handshake: 0x%02Xd", buf[0]);
561 rc = ngx_ssl_handshake(c);
563 if (rc == NGX_AGAIN) {
565 if (!rev->timer_set) {
566 ngx_add_timer(rev, c->listening->post_accept_timeout);
569 c->ssl->handler = ngx_http_ssl_handshake_handler;
570 return;
573 ngx_http_ssl_handshake_handler(c);
575 return;
577 } else {
578 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
579 "plain http");
581 r->plain_http = 1;
585 c->log->action = "reading client request line";
587 rev->handler = ngx_http_process_request_line;
588 ngx_http_process_request_line(rev);
592 static void
593 ngx_http_ssl_handshake_handler(ngx_connection_t *c)
595 ngx_http_request_t *r;
597 if (c->ssl->handshaked) {
600 * The majority of browsers do not send the "close notify" alert.
601 * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
602 * and Links. And what is more, MSIE ignores the server's alert.
604 * Opera and recent Mozilla send the alert.
607 c->ssl->no_wait_shutdown = 1;
609 c->read->handler = ngx_http_process_request_line;
610 /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
612 ngx_http_process_request_line(c->read);
614 return;
617 r = c->data;
619 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
621 return;
624 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
627 ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
629 size_t len;
630 const char *servername;
631 ngx_connection_t *c;
632 ngx_http_request_t *r;
633 ngx_http_ssl_srv_conf_t *sscf;
635 servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
637 if (servername == NULL) {
638 return SSL_TLSEXT_ERR_NOACK;
641 c = ngx_ssl_get_connection(ssl_conn);
643 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
644 "SSL server name: \"%s\"", servername);
646 len = ngx_strlen(servername);
648 if (len == 0) {
649 return SSL_TLSEXT_ERR_NOACK;
652 r = c->data;
654 if (ngx_http_find_virtual_server(r, (u_char *) servername, len) != NGX_OK) {
655 return SSL_TLSEXT_ERR_NOACK;
658 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
660 SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
662 return SSL_TLSEXT_ERR_OK;
665 #endif
667 #endif
670 static void
671 ngx_http_process_request_line(ngx_event_t *rev)
673 ssize_t n;
674 ngx_int_t rc, rv;
675 ngx_connection_t *c;
676 ngx_http_request_t *r;
677 ngx_http_core_srv_conf_t *cscf;
679 c = rev->data;
680 r = c->data;
682 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
683 "http process request line");
685 if (rev->timedout) {
686 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
687 c->timedout = 1;
688 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
689 return;
692 rc = NGX_AGAIN;
694 for ( ;; ) {
696 if (rc == NGX_AGAIN) {
697 n = ngx_http_read_request_header(r);
699 if (n == NGX_AGAIN || n == NGX_ERROR) {
700 return;
704 rc = ngx_http_parse_request_line(r, r->header_in);
706 if (rc == NGX_OK) {
708 /* the request line has been parsed successfully */
710 r->request_line.len = r->request_end - r->request_start;
711 r->request_line.data = r->request_start;
714 if (r->args_start) {
715 r->uri.len = r->args_start - 1 - r->uri_start;
716 } else {
717 r->uri.len = r->uri_end - r->uri_start;
721 if (r->complex_uri || r->quoted_uri) {
723 r->uri.data = ngx_pnalloc(r->pool, r->uri.len + 1);
724 if (r->uri.data == NULL) {
725 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
726 return;
729 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
731 rc = ngx_http_parse_complex_uri(r, cscf->merge_slashes);
733 if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) {
734 ngx_log_error(NGX_LOG_INFO, c->log, 0,
735 "client sent invalid request");
736 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
737 return;
740 } else {
741 r->uri.data = r->uri_start;
745 r->unparsed_uri.len = r->uri_end - r->uri_start;
746 r->unparsed_uri.data = r->uri_start;
749 r->method_name.len = r->method_end - r->request_start + 1;
750 r->method_name.data = r->request_line.data;
753 if (r->http_protocol.data) {
754 r->http_protocol.len = r->request_end - r->http_protocol.data;
758 if (r->uri_ext) {
759 if (r->args_start) {
760 r->exten.len = r->args_start - 1 - r->uri_ext;
761 } else {
762 r->exten.len = r->uri_end - r->uri_ext;
765 r->exten.data = r->uri_ext;
769 if (r->args_start && r->uri_end > r->args_start) {
770 r->args.len = r->uri_end - r->args_start;
771 r->args.data = r->args_start;
774 #if (NGX_WIN32)
776 u_char *p;
778 p = r->uri.data + r->uri.len - 1;
780 if (*p == '.') {
782 while (--p > r->uri.data && *p == '.') { /* void */ }
784 r->uri.len = p + 1 - r->uri.data;
786 ngx_http_set_exten(r);
789 #endif
791 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
792 "http request line: \"%V\"", &r->request_line);
794 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
795 "http uri: \"%V\"", &r->uri);
797 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
798 "http args: \"%V\"", &r->args);
800 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
801 "http exten: \"%V\"", &r->exten);
803 if (r->host_start && r->host_end) {
804 n = ngx_http_validate_host(r->host_start,
805 r->host_end - r->host_start);
807 if (n <= 0) {
808 ngx_log_error(NGX_LOG_INFO, c->log, 0,
809 "client sent invalid host in request line");
810 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
811 return;
814 r->headers_in.server.len = n;
815 r->headers_in.server.data = r->host_start;
818 if (r->http_version < NGX_HTTP_VERSION_10) {
820 if (ngx_http_find_virtual_server(r, r->headers_in.server.data,
821 r->headers_in.server.len)
822 == NGX_ERROR)
824 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
825 return;
828 ngx_http_process_request(r);
829 return;
833 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
834 sizeof(ngx_table_elt_t))
835 != NGX_OK)
837 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
838 return;
842 if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,
843 sizeof(ngx_table_elt_t *))
844 != NGX_OK)
846 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
847 return;
850 c->log->action = "reading client request headers";
852 rev->handler = ngx_http_process_request_headers;
853 ngx_http_process_request_headers(rev);
855 return;
858 if (rc != NGX_AGAIN) {
860 /* there was error while a request line parsing */
862 ngx_log_error(NGX_LOG_INFO, c->log, 0,
863 ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
864 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
865 return;
868 /* NGX_AGAIN: a request line parsing is still incomplete */
870 if (r->header_in->pos == r->header_in->end) {
872 rv = ngx_http_alloc_large_header_buffer(r, 1);
874 if (rv == NGX_ERROR) {
875 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
876 return;
879 if (rv == NGX_DECLINED) {
880 r->request_line.len = r->header_in->end - r->request_start;
881 r->request_line.data = r->request_start;
883 ngx_log_error(NGX_LOG_INFO, c->log, 0,
884 "client sent too long URI");
885 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
886 return;
893 static void
894 ngx_http_process_request_headers(ngx_event_t *rev)
896 u_char *p;
897 size_t len;
898 ssize_t n;
899 ngx_int_t rc, rv;
900 ngx_table_elt_t *h;
901 ngx_connection_t *c;
902 ngx_http_header_t *hh;
903 ngx_http_request_t *r;
904 ngx_http_core_srv_conf_t *cscf;
905 ngx_http_core_main_conf_t *cmcf;
907 c = rev->data;
908 r = c->data;
910 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
911 "http process request header line");
913 if (rev->timedout) {
914 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
915 c->timedout = 1;
916 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
917 return;
920 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
921 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
923 rc = NGX_AGAIN;
925 for ( ;; ) {
927 if (rc == NGX_AGAIN) {
929 if (r->header_in->pos == r->header_in->end) {
931 rv = ngx_http_alloc_large_header_buffer(r, 0);
933 if (rv == NGX_ERROR) {
934 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
935 return;
938 if (rv == NGX_DECLINED) {
939 len = r->header_in->end - r->header_name_start;
940 p = r->header_name_start;
942 if (len > NGX_MAX_ERROR_STR - 300) {
943 len = NGX_MAX_ERROR_STR - 300;
944 p[len++] = '.'; p[len++] = '.'; p[len++] = '.';
947 ngx_log_error(NGX_LOG_INFO, c->log, 0,
948 "client sent too long header line: \"%*s\"",
949 len, r->header_name_start);
950 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
951 return;
955 n = ngx_http_read_request_header(r);
957 if (n == NGX_AGAIN || n == NGX_ERROR) {
958 return;
962 rc = ngx_http_parse_header_line(r, r->header_in,
963 cscf->underscores_in_headers);
965 if (rc == NGX_OK) {
967 if (r->invalid_header && cscf->ignore_invalid_headers) {
969 /* there was error while a header line parsing */
971 ngx_log_error(NGX_LOG_INFO, c->log, 0,
972 "client sent invalid header line: \"%*s\"",
973 r->header_end - r->header_name_start,
974 r->header_name_start);
975 continue;
978 /* a header line has been parsed successfully */
980 h = ngx_list_push(&r->headers_in.headers);
981 if (h == NULL) {
982 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
983 return;
986 h->hash = r->header_hash;
988 h->key.len = r->header_name_end - r->header_name_start;
989 h->key.data = r->header_name_start;
990 h->key.data[h->key.len] = '\0';
992 h->value.len = r->header_end - r->header_start;
993 h->value.data = r->header_start;
994 h->value.data[h->value.len] = '\0';
996 h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
997 if (h->lowcase_key == NULL) {
998 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
999 return;
1002 if (h->key.len == r->lowcase_index) {
1003 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
1005 } else {
1006 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
1009 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
1010 h->lowcase_key, h->key.len);
1012 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
1013 return;
1016 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1017 "http header: \"%V: %V\"",
1018 &h->key, &h->value);
1020 continue;
1023 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1025 /* a whole header has been parsed successfully */
1027 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1028 "http header done");
1030 r->request_length += r->header_in->pos - r->header_in->start;
1032 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
1034 rc = ngx_http_process_request_header(r);
1036 if (rc != NGX_OK) {
1037 return;
1040 ngx_http_process_request(r);
1042 return;
1045 if (rc == NGX_AGAIN) {
1047 /* a header line parsing is still not complete */
1049 continue;
1052 /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
1054 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1055 "client sent invalid header line: \"%*s\\r...\"",
1056 r->header_end - r->header_name_start,
1057 r->header_name_start);
1058 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1059 return;
1064 static ssize_t
1065 ngx_http_read_request_header(ngx_http_request_t *r)
1067 ssize_t n;
1068 ngx_event_t *rev;
1069 ngx_connection_t *c;
1070 ngx_http_core_srv_conf_t *cscf;
1072 c = r->connection;
1073 rev = c->read;
1075 n = r->header_in->last - r->header_in->pos;
1077 if (n > 0) {
1078 return n;
1081 if (rev->ready) {
1082 n = c->recv(c, r->header_in->last,
1083 r->header_in->end - r->header_in->last);
1084 } else {
1085 n = NGX_AGAIN;
1088 if (n == NGX_AGAIN) {
1089 if (!rev->timer_set) {
1090 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1091 ngx_add_timer(rev, cscf->client_header_timeout);
1094 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1095 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1096 return NGX_ERROR;
1099 return NGX_AGAIN;
1102 if (n == 0) {
1103 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1104 "client closed prematurely connection");
1107 if (n == 0 || n == NGX_ERROR) {
1108 c->error = 1;
1109 c->log->action = "reading client request headers";
1111 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1112 return NGX_ERROR;
1115 r->header_in->last += n;
1117 return n;
1121 static ngx_int_t
1122 ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
1123 ngx_uint_t request_line)
1125 u_char *old, *new;
1126 ngx_buf_t *b;
1127 ngx_http_connection_t *hc;
1128 ngx_http_core_srv_conf_t *cscf;
1130 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1131 "http alloc large header buffer");
1133 if (request_line && r->state == 0) {
1135 /* the client fills up the buffer with "\r\n" */
1137 r->request_length += r->header_in->end - r->header_in->start;
1139 r->header_in->pos = r->header_in->start;
1140 r->header_in->last = r->header_in->start;
1142 return NGX_OK;
1145 old = request_line ? r->request_start : r->header_name_start;
1147 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1149 if (r->state != 0
1150 && (size_t) (r->header_in->pos - old)
1151 >= cscf->large_client_header_buffers.size)
1153 return NGX_DECLINED;
1156 hc = r->http_connection;
1158 if (hc->nfree) {
1159 b = hc->free[--hc->nfree];
1161 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1162 "http large header free: %p %uz",
1163 b->pos, b->end - b->last);
1165 } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
1167 if (hc->busy == NULL) {
1168 hc->busy = ngx_palloc(r->connection->pool,
1169 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
1170 if (hc->busy == NULL) {
1171 return NGX_ERROR;
1175 b = ngx_create_temp_buf(r->connection->pool,
1176 cscf->large_client_header_buffers.size);
1177 if (b == NULL) {
1178 return NGX_ERROR;
1181 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1182 "http large header alloc: %p %uz",
1183 b->pos, b->end - b->last);
1185 } else {
1186 return NGX_DECLINED;
1189 hc->busy[hc->nbusy++] = b;
1191 if (r->state == 0) {
1193 * r->state == 0 means that a header line was parsed successfully
1194 * and we do not need to copy incomplete header line and
1195 * to relocate the parser header pointers
1198 r->request_length += r->header_in->end - r->header_in->start;
1200 r->header_in = b;
1202 return NGX_OK;
1205 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1206 "http large header copy: %d", r->header_in->pos - old);
1208 r->request_length += old - r->header_in->start;
1210 new = b->start;
1212 ngx_memcpy(new, old, r->header_in->pos - old);
1214 b->pos = new + (r->header_in->pos - old);
1215 b->last = new + (r->header_in->pos - old);
1217 if (request_line) {
1218 r->request_start = new;
1220 if (r->request_end) {
1221 r->request_end = new + (r->request_end - old);
1224 r->method_end = new + (r->method_end - old);
1226 r->uri_start = new + (r->uri_start - old);
1227 r->uri_end = new + (r->uri_end - old);
1229 if (r->schema_start) {
1230 r->schema_start = new + (r->schema_start - old);
1231 r->schema_end = new + (r->schema_end - old);
1234 if (r->host_start) {
1235 r->host_start = new + (r->host_start - old);
1236 if (r->host_end) {
1237 r->host_end = new + (r->host_end - old);
1241 if (r->port_start) {
1242 r->port_start = new + (r->port_start - old);
1243 r->port_end = new + (r->port_end - old);
1246 if (r->uri_ext) {
1247 r->uri_ext = new + (r->uri_ext - old);
1250 if (r->args_start) {
1251 r->args_start = new + (r->args_start - old);
1254 if (r->http_protocol.data) {
1255 r->http_protocol.data = new + (r->http_protocol.data - old);
1258 } else {
1259 r->header_name_start = new;
1260 r->header_name_end = new + (r->header_name_end - old);
1261 r->header_start = new + (r->header_start - old);
1262 r->header_end = new + (r->header_end - old);
1265 r->header_in = b;
1267 return NGX_OK;
1271 static ngx_int_t
1272 ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1273 ngx_uint_t offset)
1275 ngx_table_elt_t **ph;
1277 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1279 if (*ph == NULL) {
1280 *ph = h;
1283 return NGX_OK;
1287 static ngx_int_t
1288 ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1289 ngx_uint_t offset)
1291 ngx_table_elt_t **ph;
1293 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1295 if (*ph == NULL) {
1296 *ph = h;
1297 return NGX_OK;
1300 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1301 "client sent duplicate header line: \"%V: %V\", "
1302 "previous value: \"%V: %V\"",
1303 &h->key, &h->value, &(*ph)->key, &(*ph)->value);
1305 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1307 return NGX_ERROR;
1311 static ngx_int_t
1312 ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
1313 ngx_uint_t offset)
1315 ssize_t len;
1317 if (r->headers_in.host == NULL) {
1318 r->headers_in.host = h;
1321 len = ngx_http_validate_host(h->value.data, h->value.len);
1323 if (len <= 0) {
1324 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1325 "client sent invalid host header");
1326 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1327 return NGX_ERROR;
1330 if (r->headers_in.server.len) {
1331 return NGX_OK;
1334 r->headers_in.server.len = len;
1335 r->headers_in.server.data = h->value.data;
1337 return NGX_OK;
1341 static ngx_int_t
1342 ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
1343 ngx_uint_t offset)
1345 if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
1346 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1348 } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {
1349 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1352 return NGX_OK;
1356 static ngx_int_t
1357 ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
1358 ngx_uint_t offset)
1360 u_char *user_agent, *msie;
1362 if (r->headers_in.user_agent) {
1363 return NGX_OK;
1366 r->headers_in.user_agent = h;
1368 /* check some widespread browsers while the header is in CPU cache */
1370 user_agent = h->value.data;
1372 msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
1374 if (msie && msie + 7 < user_agent + h->value.len) {
1376 r->headers_in.msie = 1;
1378 if (msie[6] == '.') {
1380 switch (msie[5]) {
1381 case '4':
1382 r->headers_in.msie4 = 1;
1383 /* fall through */
1384 case '5':
1385 r->headers_in.msie6 = 1;
1386 break;
1387 case '6':
1388 if (ngx_strstrn(msie + 8, "SV1", 3 - 1) == NULL) {
1389 r->headers_in.msie6 = 1;
1391 break;
1395 #if 0
1396 /* MSIE ignores the SSL "close notify" alert */
1397 if (c->ssl) {
1398 c->ssl->no_send_shutdown = 1;
1400 #endif
1403 if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
1404 r->headers_in.opera = 1;
1405 r->headers_in.msie = 0;
1406 r->headers_in.msie4 = 0;
1407 r->headers_in.msie6 = 0;
1410 if (!r->headers_in.msie && !r->headers_in.opera) {
1412 if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
1413 r->headers_in.gecko = 1;
1415 } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
1416 r->headers_in.konqueror = 1;
1420 return NGX_OK;
1424 static ngx_int_t
1425 ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
1426 ngx_uint_t offset)
1428 ngx_table_elt_t **cookie;
1430 cookie = ngx_array_push(&r->headers_in.cookies);
1431 if (cookie) {
1432 *cookie = h;
1433 return NGX_OK;
1436 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1438 return NGX_ERROR;
1442 static ngx_int_t
1443 ngx_http_process_request_header(ngx_http_request_t *r)
1445 if (ngx_http_find_virtual_server(r, r->headers_in.server.data,
1446 r->headers_in.server.len)
1447 == NGX_ERROR)
1449 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1450 return NGX_ERROR;
1453 if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) {
1454 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1455 "client sent HTTP/1.1 request without \"Host\" header");
1456 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1457 return NGX_ERROR;
1460 if (r->headers_in.content_length) {
1461 r->headers_in.content_length_n =
1462 ngx_atoof(r->headers_in.content_length->value.data,
1463 r->headers_in.content_length->value.len);
1465 if (r->headers_in.content_length_n == NGX_ERROR) {
1466 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1467 "client sent invalid \"Content-Length\" header");
1468 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
1469 return NGX_ERROR;
1473 if (r->method & NGX_HTTP_PUT && r->headers_in.content_length_n == -1) {
1474 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1475 "client sent %V method without \"Content-Length\" header",
1476 &r->method_name);
1477 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
1478 return NGX_ERROR;
1481 if (r->method & NGX_HTTP_TRACE) {
1482 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1483 "client sent TRACE method");
1484 ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
1485 return NGX_ERROR;
1488 if (r->headers_in.transfer_encoding
1489 && ngx_strcasestrn(r->headers_in.transfer_encoding->value.data,
1490 "chunked", 7 - 1))
1492 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1493 "client sent \"Transfer-Encoding: chunked\" header");
1494 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
1495 return NGX_ERROR;
1498 if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
1499 if (r->headers_in.keep_alive) {
1500 r->headers_in.keep_alive_n =
1501 ngx_atotm(r->headers_in.keep_alive->value.data,
1502 r->headers_in.keep_alive->value.len);
1506 return NGX_OK;
1510 static void
1511 ngx_http_process_request(ngx_http_request_t *r)
1513 ngx_connection_t *c;
1515 c = r->connection;
1517 if (r->plain_http) {
1518 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1519 "client sent plain HTTP request to HTTPS port");
1520 ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1521 return;
1524 #if (NGX_HTTP_SSL)
1526 if (c->ssl) {
1527 long rc;
1528 X509 *cert;
1529 ngx_http_ssl_srv_conf_t *sscf;
1531 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
1533 if (sscf->verify) {
1534 rc = SSL_get_verify_result(c->ssl->connection);
1536 if (rc != X509_V_OK) {
1537 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1538 "client SSL certificate verify error: (%l:%s)",
1539 rc, X509_verify_cert_error_string(rc));
1541 ngx_ssl_remove_cached_session(sscf->ssl.ctx,
1542 (SSL_get0_session(c->ssl->connection)));
1544 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
1545 return;
1548 if (sscf->verify == 1) {
1549 cert = SSL_get_peer_certificate(c->ssl->connection);
1551 if (cert == NULL) {
1552 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1553 "client sent no required SSL certificate");
1555 ngx_ssl_remove_cached_session(sscf->ssl.ctx,
1556 (SSL_get0_session(c->ssl->connection)));
1558 ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
1559 return;
1562 X509_free(cert);
1567 #endif
1569 if (c->read->timer_set) {
1570 ngx_del_timer(c->read);
1573 #if (NGX_STAT_STUB)
1574 (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
1575 r->stat_reading = 0;
1576 (void) ngx_atomic_fetch_add(ngx_stat_writing, 1);
1577 r->stat_writing = 1;
1578 #endif
1580 c->read->handler = ngx_http_request_handler;
1581 c->write->handler = ngx_http_request_handler;
1582 r->read_event_handler = ngx_http_block_reading;
1584 ngx_http_handler(r);
1586 ngx_http_run_posted_requests(c);
1590 static ssize_t
1591 ngx_http_validate_host(u_char *host, size_t len)
1593 u_char ch;
1594 size_t i, last;
1595 ngx_uint_t dot;
1597 last = len;
1598 dot = 0;
1600 for (i = 0; i < len; i++) {
1601 ch = host[i];
1603 if (ch == '.') {
1604 if (dot) {
1605 return -1;
1608 dot = 1;
1609 continue;
1612 dot = 0;
1614 if (ch == ':') {
1615 last = i;
1616 continue;
1619 if (ngx_path_separator(ch) || ch == '\0') {
1620 return -1;
1624 if (dot) {
1625 last--;
1628 return last;
1632 static ngx_int_t
1633 ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len)
1635 u_char *server;
1636 ngx_uint_t hash;
1637 ngx_http_core_loc_conf_t *clcf;
1638 ngx_http_core_srv_conf_t *cscf;
1639 u_char buf[32];
1641 if (r->virtual_names == NULL) {
1642 return NGX_DECLINED;
1645 if (len <= 32) {
1646 server = buf;
1648 } else {
1649 server = ngx_pnalloc(r->pool, len);
1650 if (server == NULL) {
1651 return NGX_ERROR;
1655 hash = ngx_hash_strlow(server, host, len);
1657 cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, server, len);
1659 if (cscf) {
1660 goto found;
1663 #if (NGX_PCRE)
1665 if (r->virtual_names->nregex) {
1666 size_t ncaptures;
1667 ngx_int_t n;
1668 ngx_uint_t i;
1669 ngx_str_t name;
1670 ngx_http_server_name_t *sn;
1672 name.len = len;
1673 name.data = server;
1675 ncaptures = 0;
1677 sn = r->virtual_names->regex;
1679 for (i = 0; i < r->virtual_names->nregex; i++) {
1681 if (sn[i].captures && r->captures == NULL) {
1683 ncaptures = (NGX_HTTP_MAX_CAPTURES + 1) * 3;
1685 r->captures = ngx_palloc(r->pool, ncaptures * sizeof(int));
1686 if (r->captures == NULL) {
1687 return NGX_ERROR;
1690 if (server == buf) {
1691 server = ngx_pnalloc(r->pool, len);
1692 if (server == NULL) {
1693 return NGX_ERROR;
1696 ngx_memcpy(server, buf, len);
1697 name.data = server;
1701 n = ngx_regex_exec(sn[i].regex, &name, r->captures, ncaptures);
1703 if (n == NGX_REGEX_NO_MATCHED) {
1704 continue;
1707 if (n < 0) {
1708 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1709 ngx_regex_exec_n
1710 " failed: %d on \"%V\" using \"%V\"",
1711 n, &name, &sn[i].name);
1712 return NGX_ERROR;
1715 /* match */
1717 cscf = sn[i].core_srv_conf;
1719 r->ncaptures = ncaptures;
1720 r->captures_data = server;
1722 goto found;
1726 #endif
1728 return NGX_OK;
1730 found:
1732 r->srv_conf = cscf->ctx->srv_conf;
1733 r->loc_conf = cscf->ctx->loc_conf;
1735 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1736 r->connection->log->file = clcf->error_log->file;
1738 if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1739 r->connection->log->log_level = clcf->error_log->log_level;
1742 return NGX_OK;
1746 static void
1747 ngx_http_request_handler(ngx_event_t *ev)
1749 ngx_connection_t *c;
1750 ngx_http_request_t *r;
1751 ngx_http_log_ctx_t *ctx;
1753 c = ev->data;
1754 r = c->data;
1756 ctx = c->log->data;
1757 ctx->current_request = r;
1759 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1760 "http run request: \"%V?%V\"", &r->uri, &r->args);
1762 if (ev->write) {
1763 r->write_event_handler(r);
1765 } else {
1766 r->read_event_handler(r);
1769 ngx_http_run_posted_requests(c);
1773 void
1774 ngx_http_run_posted_requests(ngx_connection_t *c)
1776 ngx_http_request_t *r;
1777 ngx_http_log_ctx_t *ctx;
1778 ngx_http_posted_request_t *pr;
1780 for ( ;; ) {
1782 if (c->destroyed) {
1783 return;
1786 r = c->data;
1787 pr = r->main->posted_requests;
1789 if (pr == NULL) {
1790 return;
1793 r->main->posted_requests = pr->next;
1795 r = pr->request;
1797 ctx = c->log->data;
1798 ctx->current_request = r;
1800 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1801 "http posted request: \"%V?%V\"", &r->uri, &r->args);
1803 r->write_event_handler(r);
1808 ngx_int_t
1809 ngx_http_post_request(ngx_http_request_t *r, ngx_http_posted_request_t *pr)
1811 ngx_http_posted_request_t **p;
1813 if (pr == NULL) {
1814 pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
1815 if (pr == NULL) {
1816 return NGX_ERROR;
1820 pr->request = r;
1821 pr->next = NULL;
1823 for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ }
1825 *p = pr;
1827 return NGX_OK;
1831 void
1832 ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1834 ngx_connection_t *c;
1835 ngx_http_request_t *pr;
1836 ngx_http_core_loc_conf_t *clcf;
1838 c = r->connection;
1840 ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
1841 "http finalize request: %d, \"%V?%V\" a:%d, c:%d",
1842 rc, &r->uri, &r->args, r == c->data, r->main->count);
1844 if (rc == NGX_DONE) {
1845 ngx_http_finalize_connection(r);
1846 return;
1849 if (rc == NGX_OK && r->filter_finalize) {
1850 c->error = 1;
1851 return;
1854 if (rc == NGX_DECLINED) {
1855 r->content_handler = NULL;
1856 r->write_event_handler = ngx_http_core_run_phases;
1857 ngx_http_core_run_phases(r);
1858 return;
1861 if (r != r->main && r->post_subrequest) {
1862 rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
1865 if (rc == NGX_ERROR
1866 || rc == NGX_HTTP_REQUEST_TIME_OUT
1867 || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
1868 || c->error)
1870 if (ngx_http_post_action(r) == NGX_OK) {
1871 return;
1874 if (r->main->blocked) {
1875 r->write_event_handler = ngx_http_request_finalizer;
1878 ngx_http_terminate_request(r, rc);
1879 return;
1882 if (rc >= NGX_HTTP_SPECIAL_RESPONSE
1883 || rc == NGX_HTTP_CREATED
1884 || rc == NGX_HTTP_NO_CONTENT)
1886 if (rc == NGX_HTTP_CLOSE) {
1887 ngx_http_terminate_request(r, rc);
1888 return;
1891 if (r == r->main) {
1892 if (c->read->timer_set) {
1893 ngx_del_timer(c->read);
1896 if (c->write->timer_set) {
1897 ngx_del_timer(c->write);
1901 c->read->handler = ngx_http_request_handler;
1902 c->write->handler = ngx_http_request_handler;
1904 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
1905 return;
1908 if (r != r->main) {
1910 if (r->buffered || r->postponed) {
1912 if (ngx_http_set_write_handler(r) != NGX_OK) {
1913 ngx_http_terminate_request(r, 0);
1916 return;
1919 #if (NGX_DEBUG)
1920 if (r != c->data) {
1921 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1922 "http finalize non-active request: \"%V?%V\"",
1923 &r->uri, &r->args);
1925 #endif
1927 pr = r->parent;
1929 if (r == c->data) {
1931 r->main->count--;
1933 if (!r->logged) {
1935 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1937 if (clcf->log_subrequest) {
1938 ngx_http_log_request(r);
1941 r->logged = 1;
1943 } else {
1944 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
1945 "subrequest: \"%V?%V\" logged again",
1946 &r->uri, &r->args);
1949 r->done = 1;
1951 if (pr->postponed && pr->postponed->request == r) {
1952 pr->postponed = pr->postponed->next;
1955 c->data = pr;
1957 } else {
1959 r->write_event_handler = ngx_http_request_finalizer;
1961 if (r->waited) {
1962 r->done = 1;
1966 if (ngx_http_post_request(pr, NULL) != NGX_OK) {
1967 r->main->count++;
1968 ngx_http_terminate_request(r, 0);
1969 return;
1972 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1973 "http wake parent request: \"%V?%V\"",
1974 &pr->uri, &pr->args);
1976 return;
1979 if (r->buffered || c->buffered || r->postponed || r->blocked) {
1981 if (ngx_http_set_write_handler(r) != NGX_OK) {
1982 ngx_http_terminate_request(r, 0);
1985 return;
1988 if (r != c->data) {
1989 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
1990 "http finalize non-active request: \"%V?%V\"",
1991 &r->uri, &r->args);
1992 return;
1995 r->done = 1;
1997 if (!r->post_action) {
1998 r->request_complete = 1;
2001 if (ngx_http_post_action(r) == NGX_OK) {
2002 return;
2005 if (c->read->timer_set) {
2006 ngx_del_timer(c->read);
2009 if (c->write->timer_set) {
2010 c->write->delayed = 0;
2011 ngx_del_timer(c->write);
2014 if (c->read->eof) {
2015 ngx_http_close_request(r, 0);
2016 return;
2019 ngx_http_finalize_connection(r);
2023 static void
2024 ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc)
2026 ngx_http_cleanup_t *cln;
2027 ngx_http_request_t *mr;
2028 ngx_http_ephemeral_t *e;
2030 mr = r->main;
2032 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2033 "http terminate request count:%d", mr->count);
2035 cln = mr->cleanup;
2036 mr->cleanup = NULL;
2038 while (cln) {
2039 if (cln->handler) {
2040 cln->handler(cln->data);
2043 cln = cln->next;
2046 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2047 "http terminate cleanup count:%d blk:%d",
2048 mr->count, mr->blocked);
2050 if (mr->write_event_handler) {
2052 if (mr->blocked) {
2053 return;
2056 e = ngx_http_ephemeral(mr);
2057 mr->posted_requests = NULL;
2058 mr->write_event_handler = ngx_http_terminate_handler;
2059 (void) ngx_http_post_request(mr, &e->terminal_posted_request);
2060 return;
2063 ngx_http_close_request(mr, rc);
2067 static void
2068 ngx_http_terminate_handler(ngx_http_request_t *r)
2070 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2071 "http terminate handler count:%d", r->count);
2073 r->count = 1;
2075 ngx_http_close_request(r, 0);
2079 static void
2080 ngx_http_finalize_connection(ngx_http_request_t *r)
2082 ngx_http_core_loc_conf_t *clcf;
2084 if (r->main->count != 1) {
2085 ngx_http_close_request(r, 0);
2086 return;
2089 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2091 if (!ngx_terminate
2092 && !ngx_exiting
2093 && r->keepalive
2094 && clcf->keepalive_timeout > 0)
2096 ngx_http_set_keepalive(r);
2097 return;
2099 } else if (r->lingering_close && clcf->lingering_timeout > 0) {
2100 ngx_http_set_lingering_close(r);
2101 return;
2104 ngx_http_close_request(r, 0);
2108 static ngx_int_t
2109 ngx_http_set_write_handler(ngx_http_request_t *r)
2111 ngx_event_t *wev;
2112 ngx_http_core_loc_conf_t *clcf;
2114 r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
2116 r->read_event_handler = ngx_http_test_reading;
2117 r->write_event_handler = ngx_http_writer;
2119 wev = r->connection->write;
2121 if (wev->ready && wev->delayed) {
2122 return NGX_OK;
2125 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2126 if (!wev->delayed) {
2127 ngx_add_timer(wev, clcf->send_timeout);
2130 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2131 ngx_http_close_request(r, 0);
2132 return NGX_ERROR;
2135 return NGX_OK;
2139 static void
2140 ngx_http_writer(ngx_http_request_t *r)
2142 int rc;
2143 ngx_event_t *wev;
2144 ngx_connection_t *c;
2145 ngx_http_core_loc_conf_t *clcf;
2147 c = r->connection;
2148 wev = c->write;
2150 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2151 "http writer handler: \"%V?%V\"", &r->uri, &r->args);
2153 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
2155 if (wev->timedout) {
2156 if (!wev->delayed) {
2157 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
2158 "client timed out");
2159 c->timedout = 1;
2161 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
2162 return;
2165 wev->timedout = 0;
2166 wev->delayed = 0;
2168 if (!wev->ready) {
2169 ngx_add_timer(wev, clcf->send_timeout);
2171 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2172 ngx_http_close_request(r, 0);
2175 return;
2178 } else {
2179 if (wev->delayed || r->aio) {
2180 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2181 "http writer delayed");
2183 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2184 ngx_http_close_request(r, 0);
2187 return;
2191 rc = ngx_http_output_filter(r, NULL);
2193 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
2194 "http writer output filter: %d, \"%V?%V\"",
2195 rc, &r->uri, &r->args);
2197 if (rc == NGX_ERROR) {
2198 ngx_http_finalize_request(r, rc);
2199 return;
2202 if (r->buffered || r->postponed || (r == r->main && c->buffered)) {
2204 if (!wev->ready && !wev->delayed) {
2205 ngx_add_timer(wev, clcf->send_timeout);
2208 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2209 ngx_http_close_request(r, 0);
2212 return;
2215 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2216 "http writer done: \"%V?%V\"", &r->uri, &r->args);
2218 ngx_http_finalize_request(r, rc);
2222 static void
2223 ngx_http_request_finalizer(ngx_http_request_t *r)
2225 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2226 "http finalizer done: \"%V?%V\"", &r->uri, &r->args);
2228 ngx_http_finalize_request(r, 0);
2232 void
2233 ngx_http_block_reading(ngx_http_request_t *r)
2235 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2236 "http reading blocked");
2238 /* aio does not call this handler */
2240 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
2241 && r->connection->read->active)
2243 if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) != NGX_OK) {
2244 ngx_http_close_request(r, 0);
2250 void
2251 ngx_http_test_reading(ngx_http_request_t *r)
2253 int n;
2254 char buf[1];
2255 ngx_err_t err;
2256 ngx_event_t *rev;
2257 ngx_connection_t *c;
2259 c = r->connection;
2260 rev = c->read;
2262 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading");
2264 #if (NGX_HAVE_KQUEUE)
2266 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2268 if (!rev->pending_eof) {
2269 return;
2272 rev->eof = 1;
2273 c->error = 1;
2274 err = rev->kq_errno;
2276 goto closed;
2279 #endif
2281 n = recv(c->fd, buf, 1, MSG_PEEK);
2283 if (n == 0) {
2284 rev->eof = 1;
2285 c->error = 1;
2286 err = 0;
2288 goto closed;
2290 } else if (n == -1) {
2291 err = ngx_socket_errno;
2293 if (err != NGX_EAGAIN) {
2294 rev->eof = 1;
2295 c->error = 1;
2297 goto closed;
2301 /* aio does not call this handler */
2303 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
2305 if (ngx_del_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
2306 ngx_http_close_request(r, 0);
2310 return;
2312 closed:
2314 if (err) {
2315 rev->error = 1;
2318 ngx_log_error(NGX_LOG_INFO, c->log, err,
2319 "client closed prematurely connection");
2321 ngx_http_finalize_request(r, 0);
2325 static void
2326 ngx_http_set_keepalive(ngx_http_request_t *r)
2328 int tcp_nodelay;
2329 ngx_int_t i;
2330 ngx_buf_t *b, *f;
2331 ngx_event_t *rev, *wev;
2332 ngx_connection_t *c;
2333 ngx_http_connection_t *hc;
2334 ngx_http_core_srv_conf_t *cscf;
2335 ngx_http_core_loc_conf_t *clcf;
2337 c = r->connection;
2338 rev = c->read;
2340 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2342 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
2344 if (r->discard_body) {
2345 r->write_event_handler = ngx_http_request_empty_handler;
2346 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
2347 ngx_add_timer(rev, clcf->lingering_timeout);
2348 return;
2351 c->log->action = "closing request";
2353 hc = r->http_connection;
2354 b = r->header_in;
2356 if (b->pos < b->last) {
2358 /* the pipelined request */
2360 if (b != c->buffer) {
2363 * If the large header buffers were allocated while the previous
2364 * request processing then we do not use c->buffer for
2365 * the pipelined request (see ngx_http_init_request()).
2367 * Now we would move the large header buffers to the free list.
2370 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2372 if (hc->free == NULL) {
2373 hc->free = ngx_palloc(c->pool,
2374 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
2376 if (hc->free == NULL) {
2377 ngx_http_close_request(r, 0);
2378 return;
2382 for (i = 0; i < hc->nbusy - 1; i++) {
2383 f = hc->busy[i];
2384 hc->free[hc->nfree++] = f;
2385 f->pos = f->start;
2386 f->last = f->start;
2389 hc->busy[0] = b;
2390 hc->nbusy = 1;
2394 ngx_http_free_request(r, 0);
2396 c->data = hc;
2398 ngx_add_timer(rev, clcf->keepalive_timeout);
2400 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2401 ngx_http_close_connection(c);
2402 return;
2405 wev = c->write;
2406 wev->handler = ngx_http_empty_handler;
2408 if (b->pos < b->last) {
2410 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
2412 #if (NGX_STAT_STUB)
2413 (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
2414 #endif
2416 hc->pipeline = 1;
2417 c->log->action = "reading client pipelined request line";
2419 rev->handler = ngx_http_init_request;
2420 ngx_post_event(rev, &ngx_posted_events);
2421 return;
2424 hc->pipeline = 0;
2427 * To keep a memory footprint as small as possible for an idle
2428 * keepalive connection we try to free the ngx_http_request_t and
2429 * c->buffer's memory if they were allocated outside the c->pool.
2430 * The large header buffers are always allocated outside the c->pool and
2431 * are freed too.
2434 if (ngx_pfree(c->pool, r) == NGX_OK) {
2435 hc->request = NULL;
2438 b = c->buffer;
2440 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
2443 * the special note for ngx_http_keepalive_handler() that
2444 * c->buffer's memory was freed
2447 b->pos = NULL;
2449 } else {
2450 b->pos = b->start;
2451 b->last = b->start;
2454 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",
2455 hc->free, hc->nfree);
2457 if (hc->free) {
2458 for (i = 0; i < hc->nfree; i++) {
2459 ngx_pfree(c->pool, hc->free[i]->start);
2460 hc->free[i] = NULL;
2463 hc->nfree = 0;
2466 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",
2467 hc->busy, hc->nbusy);
2469 if (hc->busy) {
2470 for (i = 0; i < hc->nbusy; i++) {
2471 ngx_pfree(c->pool, hc->busy[i]->start);
2472 hc->busy[i] = NULL;
2475 hc->nbusy = 0;
2478 #if (NGX_HTTP_SSL)
2479 if (c->ssl) {
2480 ngx_ssl_free_buffer(c);
2482 #endif
2484 rev->handler = ngx_http_keepalive_handler;
2486 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2487 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
2488 ngx_http_close_connection(c);
2489 return;
2493 c->log->action = "keepalive";
2495 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
2496 if (ngx_tcp_push(c->fd) == -1) {
2497 ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
2498 ngx_http_close_connection(c);
2499 return;
2502 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
2503 tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
2505 } else {
2506 tcp_nodelay = 1;
2509 if (tcp_nodelay
2510 && clcf->tcp_nodelay
2511 && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
2513 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
2515 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
2516 (const void *) &tcp_nodelay, sizeof(int))
2517 == -1)
2519 #if (NGX_SOLARIS)
2520 /* Solaris returns EINVAL if a socket has been shut down */
2521 c->log_error = NGX_ERROR_IGNORE_EINVAL;
2522 #endif
2524 ngx_connection_error(c, ngx_socket_errno,
2525 "setsockopt(TCP_NODELAY) failed");
2527 c->log_error = NGX_ERROR_INFO;
2528 ngx_http_close_connection(c);
2529 return;
2532 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
2535 #if 0
2536 /* if ngx_http_request_t was freed then we need some other place */
2537 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
2538 #endif
2540 c->idle = 1;
2542 if (rev->ready) {
2543 ngx_post_event(rev, &ngx_posted_events);
2548 static void
2549 ngx_http_keepalive_handler(ngx_event_t *rev)
2551 size_t size;
2552 ssize_t n;
2553 ngx_buf_t *b;
2554 ngx_connection_t *c;
2556 c = rev->data;
2558 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
2560 if (rev->timedout || c->close) {
2561 ngx_http_close_connection(c);
2562 return;
2565 #if (NGX_HAVE_KQUEUE)
2567 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2568 if (rev->pending_eof) {
2569 c->log->handler = NULL;
2570 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
2571 "kevent() reported that client %V closed "
2572 "keepalive connection", &c->addr_text);
2573 #if (NGX_HTTP_SSL)
2574 if (c->ssl) {
2575 c->ssl->no_send_shutdown = 1;
2577 #endif
2578 ngx_http_close_connection(c);
2579 return;
2583 #endif
2585 b = c->buffer;
2586 size = b->end - b->start;
2588 if (b->pos == NULL) {
2591 * The c->buffer's memory was freed by ngx_http_set_keepalive().
2592 * However, the c->buffer->start and c->buffer->end were not changed
2593 * to keep the buffer size.
2596 b->pos = ngx_palloc(c->pool, size);
2597 if (b->pos == NULL) {
2598 ngx_http_close_connection(c);
2599 return;
2602 b->start = b->pos;
2603 b->last = b->pos;
2604 b->end = b->pos + size;
2608 * MSIE closes a keepalive connection with RST flag
2609 * so we ignore ECONNRESET here.
2612 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
2613 ngx_set_socket_errno(0);
2615 n = c->recv(c, b->last, size);
2616 c->log_error = NGX_ERROR_INFO;
2618 if (n == NGX_AGAIN) {
2619 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2620 ngx_http_close_connection(c);
2623 return;
2626 if (n == NGX_ERROR) {
2627 ngx_http_close_connection(c);
2628 return;
2631 c->log->handler = NULL;
2633 if (n == 0) {
2634 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
2635 "client %V closed keepalive connection", &c->addr_text);
2636 ngx_http_close_connection(c);
2637 return;
2640 b->last += n;
2642 #if (NGX_STAT_STUB)
2643 (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
2644 #endif
2646 c->log->handler = ngx_http_log_error;
2647 c->log->action = "reading client request line";
2649 c->idle = 0;
2651 ngx_http_init_request(rev);
2655 static void
2656 ngx_http_set_lingering_close(ngx_http_request_t *r)
2658 ngx_event_t *rev, *wev;
2659 ngx_connection_t *c;
2660 ngx_http_core_loc_conf_t *clcf;
2662 c = r->connection;
2664 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2666 rev = c->read;
2667 rev->handler = ngx_http_lingering_close_handler;
2669 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
2670 ngx_add_timer(rev, clcf->lingering_timeout);
2672 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2673 ngx_http_close_request(r, 0);
2674 return;
2677 wev = c->write;
2678 wev->handler = ngx_http_empty_handler;
2680 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2681 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
2682 ngx_http_close_request(r, 0);
2683 return;
2687 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
2688 ngx_connection_error(c, ngx_socket_errno,
2689 ngx_shutdown_socket_n " failed");
2690 ngx_http_close_request(r, 0);
2691 return;
2694 if (rev->ready) {
2695 ngx_http_lingering_close_handler(rev);
2700 static void
2701 ngx_http_lingering_close_handler(ngx_event_t *rev)
2703 ssize_t n;
2704 ngx_msec_t timer;
2705 ngx_connection_t *c;
2706 ngx_http_request_t *r;
2707 ngx_http_core_loc_conf_t *clcf;
2708 u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
2710 c = rev->data;
2711 r = c->data;
2713 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2714 "http lingering close handler");
2716 if (rev->timedout) {
2717 c->timedout = 1;
2718 ngx_http_close_request(r, 0);
2719 return;
2722 timer = (ngx_msec_t) (r->lingering_time - ngx_time());
2723 if (timer <= 0) {
2724 ngx_http_close_request(r, 0);
2725 return;
2728 do {
2729 n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
2731 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
2733 if (n == NGX_ERROR || n == 0) {
2734 ngx_http_close_request(r, 0);
2735 return;
2738 } while (rev->ready);
2740 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2741 ngx_http_close_request(r, 0);
2742 return;
2745 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2747 timer *= 1000;
2749 if (timer > clcf->lingering_timeout) {
2750 timer = clcf->lingering_timeout;
2753 ngx_add_timer(rev, timer);
2757 void
2758 ngx_http_empty_handler(ngx_event_t *wev)
2760 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
2762 return;
2766 void
2767 ngx_http_request_empty_handler(ngx_http_request_t *r)
2769 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2770 "http request empty handler");
2772 return;
2776 ngx_int_t
2777 ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
2779 ngx_buf_t *b;
2780 ngx_chain_t out;
2782 b = ngx_calloc_buf(r->pool);
2783 if (b == NULL) {
2784 return NGX_ERROR;
2787 if (flags & NGX_HTTP_LAST) {
2789 if (r == r->main && !r->post_action) {
2790 b->last_buf = 1;
2792 } else {
2793 b->sync = 1;
2794 b->last_in_chain = 1;
2798 if (flags & NGX_HTTP_FLUSH) {
2799 b->flush = 1;
2802 out.buf = b;
2803 out.next = NULL;
2805 return ngx_http_output_filter(r, &out);
2809 static ngx_int_t
2810 ngx_http_post_action(ngx_http_request_t *r)
2812 ngx_http_core_loc_conf_t *clcf;
2814 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2816 if (clcf->post_action.data == NULL) {
2817 return NGX_DECLINED;
2820 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2821 "post action: \"%V\"", &clcf->post_action);
2823 r->main->count--;
2825 r->http_version = NGX_HTTP_VERSION_9;
2826 r->header_only = 1;
2827 r->post_action = 1;
2829 r->read_event_handler = ngx_http_block_reading;
2831 if (clcf->post_action.data[0] == '/') {
2832 ngx_http_internal_redirect(r, &clcf->post_action, NULL);
2834 } else {
2835 ngx_http_named_location(r, &clcf->post_action);
2838 return NGX_OK;
2842 static void
2843 ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc)
2845 ngx_connection_t *c;
2847 r = r->main;
2848 c = r->connection;
2850 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2851 "http request count:%d blk:%d", r->count, r->blocked);
2853 if (r->count == 0) {
2854 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "http request count is zero");
2857 r->count--;
2859 if (r->count || r->blocked) {
2860 return;
2863 ngx_http_free_request(r, rc);
2864 ngx_http_close_connection(c);
2868 static void
2869 ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc)
2871 ngx_log_t *log;
2872 struct linger linger;
2873 ngx_http_cleanup_t *cln;
2874 ngx_http_log_ctx_t *ctx;
2875 ngx_http_core_loc_conf_t *clcf;
2877 log = r->connection->log;
2879 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
2881 if (r->pool == NULL) {
2882 ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
2883 return;
2886 for (cln = r->cleanup; cln; cln = cln->next) {
2887 if (cln->handler) {
2888 cln->handler(cln->data);
2892 #if (NGX_STAT_STUB)
2894 if (r->stat_reading) {
2895 (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
2898 if (r->stat_writing) {
2899 (void) ngx_atomic_fetch_add(ngx_stat_writing, -1);
2902 #endif
2904 if (rc > 0 && (r->headers_out.status == 0 || r->connection->sent == 0)) {
2905 r->headers_out.status = rc;
2908 log->action = "logging request";
2910 ngx_http_log_request(r);
2912 log->action = "closing request";
2914 if (r->connection->timedout) {
2915 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2917 if (clcf->reset_timedout_connection) {
2918 linger.l_onoff = 1;
2919 linger.l_linger = 0;
2921 if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
2922 (const void *) &linger, sizeof(struct linger)) == -1)
2924 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
2925 "setsockopt(SO_LINGER) failed");
2930 /* the various request strings were allocated from r->pool */
2931 ctx = log->data;
2932 ctx->request = NULL;
2934 r->request_line.len = 0;
2936 r->connection->destroyed = 1;
2938 ngx_destroy_pool(r->pool);
2942 static void
2943 ngx_http_log_request(ngx_http_request_t *r)
2945 ngx_uint_t i, n;
2946 ngx_http_handler_pt *log_handler;
2947 ngx_http_core_main_conf_t *cmcf;
2949 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2951 log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
2952 n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
2954 for (i = 0; i < n; i++) {
2955 log_handler[i](r);
2960 static void
2961 ngx_http_close_connection(ngx_connection_t *c)
2963 ngx_pool_t *pool;
2965 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
2966 "close http connection: %d", c->fd);
2968 #if (NGX_HTTP_SSL)
2970 if (c->ssl) {
2971 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
2972 c->ssl->handler = ngx_http_close_connection;
2973 return;
2977 #endif
2979 #if (NGX_STAT_STUB)
2980 (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
2981 #endif
2983 c->destroyed = 1;
2985 pool = c->pool;
2987 ngx_close_connection(c);
2989 ngx_destroy_pool(pool);
2993 static u_char *
2994 ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
2996 u_char *p;
2997 ngx_http_request_t *r;
2998 ngx_http_log_ctx_t *ctx;
3000 if (log->action) {
3001 p = ngx_snprintf(buf, len, " while %s", log->action);
3002 len -= p - buf;
3003 buf = p;
3006 ctx = log->data;
3008 p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text);
3009 len -= p - buf;
3011 r = ctx->request;
3013 if (r) {
3014 return r->log_handler(r, ctx->current_request, p, len);
3016 } else {
3017 p = ngx_snprintf(p, len, ", server: %V",
3018 &ctx->connection->listening->addr_text);
3021 return p;
3025 static u_char *
3026 ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
3027 u_char *buf, size_t len)
3029 char *uri_separator;
3030 u_char *p;
3031 ngx_http_upstream_t *u;
3032 ngx_http_core_srv_conf_t *cscf;
3034 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
3036 p = ngx_snprintf(buf, len, ", server: %V", &cscf->server_name);
3037 len -= p - buf;
3038 buf = p;
3040 if (r->request_line.data == NULL && r->request_start) {
3041 for (p = r->request_start; p < r->header_in->last; p++) {
3042 if (*p == CR || *p == LF) {
3043 break;
3047 r->request_line.len = p - r->request_start;
3048 r->request_line.data = r->request_start;
3051 if (r->request_line.len) {
3052 p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
3053 len -= p - buf;
3054 buf = p;
3057 if (r != sr) {
3058 p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
3059 len -= p - buf;
3060 buf = p;
3063 u = sr->upstream;
3065 if (u && u->peer.name) {
3067 uri_separator = "";
3069 #if (NGX_HAVE_UNIX_DOMAIN)
3070 if (u->peer.sockaddr && u->peer.sockaddr->sa_family == AF_UNIX) {
3071 uri_separator = ":";
3073 #endif
3075 p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
3076 &u->schema, u->peer.name,
3077 uri_separator, &u->uri);
3078 len -= p - buf;
3079 buf = p;
3082 if (r->headers_in.host) {
3083 p = ngx_snprintf(buf, len, ", host: \"%V\"",
3084 &r->headers_in.host->value);
3085 len -= p - buf;
3086 buf = p;
3089 if (r->headers_in.referer) {
3090 p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
3091 &r->headers_in.referer->value);
3092 buf = p;
3095 return buf;