Update and clean Tomato RAF files
[tomato.git] / release / src / router / nginx / src / http / ngx_http_request.c
blob8942deb33ca09329fc833f4c3015021647e3ccd5
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
13 static void ngx_http_wait_request_handler(ngx_event_t *ev);
14 static void ngx_http_process_request_line(ngx_event_t *rev);
15 static void ngx_http_process_request_headers(ngx_event_t *rev);
16 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
17 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
18 ngx_uint_t request_line);
20 static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
21 ngx_table_elt_t *h, ngx_uint_t offset);
22 static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
23 ngx_table_elt_t *h, ngx_uint_t offset);
24 static ngx_int_t ngx_http_process_multi_header_lines(ngx_http_request_t *r,
25 ngx_table_elt_t *h, ngx_uint_t offset);
26 static ngx_int_t ngx_http_process_host(ngx_http_request_t *r,
27 ngx_table_elt_t *h, ngx_uint_t offset);
28 static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
29 ngx_table_elt_t *h, ngx_uint_t offset);
30 static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r,
31 ngx_table_elt_t *h, ngx_uint_t offset);
33 static ngx_int_t ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool,
34 ngx_uint_t alloc);
35 static ngx_int_t ngx_http_set_virtual_server(ngx_http_request_t *r,
36 ngx_str_t *host);
37 static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c,
38 ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
39 ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp);
41 static void ngx_http_request_handler(ngx_event_t *ev);
42 static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc);
43 static void ngx_http_terminate_handler(ngx_http_request_t *r);
44 static void ngx_http_finalize_connection(ngx_http_request_t *r);
45 static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
46 static void ngx_http_writer(ngx_http_request_t *r);
47 static void ngx_http_request_finalizer(ngx_http_request_t *r);
49 static void ngx_http_set_keepalive(ngx_http_request_t *r);
50 static void ngx_http_keepalive_handler(ngx_event_t *ev);
51 static void ngx_http_set_lingering_close(ngx_http_request_t *r);
52 static void ngx_http_lingering_close_handler(ngx_event_t *ev);
53 static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
54 static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
55 static void ngx_http_log_request(ngx_http_request_t *r);
57 static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
58 static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
59 ngx_http_request_t *sr, u_char *buf, size_t len);
61 #if (NGX_HTTP_SSL)
62 static void ngx_http_ssl_handshake(ngx_event_t *rev);
63 static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
64 #endif
67 static char *ngx_http_client_errors[] = {
69 /* NGX_HTTP_PARSE_INVALID_METHOD */
70 "client sent invalid method",
72 /* NGX_HTTP_PARSE_INVALID_REQUEST */
73 "client sent invalid request",
75 /* NGX_HTTP_PARSE_INVALID_09_METHOD */
76 "client sent invalid method in HTTP/0.9 request"
80 ngx_http_header_t ngx_http_headers_in[] = {
81 { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
82 ngx_http_process_host },
84 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
85 ngx_http_process_connection },
87 { ngx_string("If-Modified-Since"),
88 offsetof(ngx_http_headers_in_t, if_modified_since),
89 ngx_http_process_unique_header_line },
91 { ngx_string("If-Unmodified-Since"),
92 offsetof(ngx_http_headers_in_t, if_unmodified_since),
93 ngx_http_process_unique_header_line },
95 { ngx_string("If-Match"),
96 offsetof(ngx_http_headers_in_t, if_match),
97 ngx_http_process_unique_header_line },
99 { ngx_string("If-None-Match"),
100 offsetof(ngx_http_headers_in_t, if_none_match),
101 ngx_http_process_unique_header_line },
103 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
104 ngx_http_process_user_agent },
106 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
107 ngx_http_process_header_line },
109 { ngx_string("Content-Length"),
110 offsetof(ngx_http_headers_in_t, content_length),
111 ngx_http_process_unique_header_line },
113 { ngx_string("Content-Type"),
114 offsetof(ngx_http_headers_in_t, content_type),
115 ngx_http_process_header_line },
117 { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
118 ngx_http_process_header_line },
120 { ngx_string("If-Range"),
121 offsetof(ngx_http_headers_in_t, if_range),
122 ngx_http_process_unique_header_line },
124 { ngx_string("Transfer-Encoding"),
125 offsetof(ngx_http_headers_in_t, transfer_encoding),
126 ngx_http_process_header_line },
128 { ngx_string("Expect"),
129 offsetof(ngx_http_headers_in_t, expect),
130 ngx_http_process_unique_header_line },
132 { ngx_string("Upgrade"),
133 offsetof(ngx_http_headers_in_t, upgrade),
134 ngx_http_process_header_line },
136 #if (NGX_HTTP_GZIP)
137 { ngx_string("Accept-Encoding"),
138 offsetof(ngx_http_headers_in_t, accept_encoding),
139 ngx_http_process_header_line },
141 { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
142 ngx_http_process_header_line },
143 #endif
145 { ngx_string("Authorization"),
146 offsetof(ngx_http_headers_in_t, authorization),
147 ngx_http_process_unique_header_line },
149 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
150 ngx_http_process_header_line },
152 #if (NGX_HTTP_X_FORWARDED_FOR)
153 { ngx_string("X-Forwarded-For"),
154 offsetof(ngx_http_headers_in_t, x_forwarded_for),
155 ngx_http_process_multi_header_lines },
156 #endif
158 #if (NGX_HTTP_REALIP)
159 { ngx_string("X-Real-IP"),
160 offsetof(ngx_http_headers_in_t, x_real_ip),
161 ngx_http_process_header_line },
162 #endif
164 #if (NGX_HTTP_HEADERS)
165 { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
166 ngx_http_process_header_line },
168 { ngx_string("Accept-Language"),
169 offsetof(ngx_http_headers_in_t, accept_language),
170 ngx_http_process_header_line },
171 #endif
173 #if (NGX_HTTP_DAV)
174 { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
175 ngx_http_process_header_line },
177 { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
178 ngx_http_process_header_line },
180 { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),
181 ngx_http_process_header_line },
183 { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
184 ngx_http_process_header_line },
185 #endif
187 { ngx_string("Cookie"), offsetof(ngx_http_headers_in_t, cookies),
188 ngx_http_process_multi_header_lines },
190 { ngx_null_string, 0, NULL }
194 void
195 ngx_http_init_connection(ngx_connection_t *c)
197 ngx_uint_t i;
198 ngx_event_t *rev;
199 struct sockaddr_in *sin;
200 ngx_http_port_t *port;
201 ngx_http_in_addr_t *addr;
202 ngx_http_log_ctx_t *ctx;
203 ngx_http_connection_t *hc;
204 #if (NGX_HAVE_INET6)
205 struct sockaddr_in6 *sin6;
206 ngx_http_in6_addr_t *addr6;
207 #endif
209 hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
210 if (hc == NULL) {
211 ngx_http_close_connection(c);
212 return;
215 c->data = hc;
217 /* find the server configuration for the address:port */
219 port = c->listening->servers;
221 if (port->naddrs > 1) {
224 * there are several addresses on this port and one of them
225 * is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
226 * is required to determine a server address
229 if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
230 ngx_http_close_connection(c);
231 return;
234 switch (c->local_sockaddr->sa_family) {
236 #if (NGX_HAVE_INET6)
237 case AF_INET6:
238 sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
240 addr6 = port->addrs;
242 /* the last address is "*" */
244 for (i = 0; i < port->naddrs - 1; i++) {
245 if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
246 break;
250 hc->addr_conf = &addr6[i].conf;
252 break;
253 #endif
255 default: /* AF_INET */
256 sin = (struct sockaddr_in *) c->local_sockaddr;
258 addr = port->addrs;
260 /* the last address is "*" */
262 for (i = 0; i < port->naddrs - 1; i++) {
263 if (addr[i].addr == sin->sin_addr.s_addr) {
264 break;
268 hc->addr_conf = &addr[i].conf;
270 break;
273 } else {
275 switch (c->local_sockaddr->sa_family) {
277 #if (NGX_HAVE_INET6)
278 case AF_INET6:
279 addr6 = port->addrs;
280 hc->addr_conf = &addr6[0].conf;
281 break;
282 #endif
284 default: /* AF_INET */
285 addr = port->addrs;
286 hc->addr_conf = &addr[0].conf;
287 break;
291 /* the default server configuration for the address:port */
292 hc->conf_ctx = hc->addr_conf->default_server->ctx;
294 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
295 if (ctx == NULL) {
296 ngx_http_close_connection(c);
297 return;
300 ctx->connection = c;
301 ctx->request = NULL;
302 ctx->current_request = NULL;
304 c->log->connection = c->number;
305 c->log->handler = ngx_http_log_error;
306 c->log->data = ctx;
307 c->log->action = "waiting for request";
309 c->log_error = NGX_ERROR_INFO;
311 rev = c->read;
312 rev->handler = ngx_http_wait_request_handler;
313 c->write->handler = ngx_http_empty_handler;
315 #if (NGX_HTTP_SPDY)
316 if (hc->addr_conf->spdy) {
317 rev->handler = ngx_http_spdy_init;
319 #endif
321 #if (NGX_HTTP_SSL)
323 ngx_http_ssl_srv_conf_t *sscf;
325 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
327 if (sscf->enable || hc->addr_conf->ssl) {
329 c->log->action = "SSL handshaking";
331 if (hc->addr_conf->ssl && sscf->ssl.ctx == NULL) {
332 ngx_log_error(NGX_LOG_ERR, c->log, 0,
333 "no \"ssl_certificate\" is defined "
334 "in server listening on SSL port");
335 ngx_http_close_connection(c);
336 return;
339 hc->ssl = 1;
341 rev->handler = ngx_http_ssl_handshake;
344 #endif
346 if (rev->ready) {
347 /* the deferred accept(), rtsig, aio, iocp */
349 if (ngx_use_accept_mutex) {
350 ngx_post_event(rev, &ngx_posted_events);
351 return;
354 rev->handler(rev);
355 return;
358 ngx_add_timer(rev, c->listening->post_accept_timeout);
359 ngx_reusable_connection(c, 1);
361 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
362 ngx_http_close_connection(c);
363 return;
368 static void
369 ngx_http_wait_request_handler(ngx_event_t *rev)
371 size_t size;
372 ssize_t n;
373 ngx_buf_t *b;
374 ngx_connection_t *c;
375 ngx_http_connection_t *hc;
376 ngx_http_core_srv_conf_t *cscf;
378 c = rev->data;
380 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http wait request handler");
382 if (rev->timedout) {
383 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
384 ngx_http_close_connection(c);
385 return;
388 if (c->close) {
389 ngx_http_close_connection(c);
390 return;
393 hc = c->data;
394 cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
396 size = cscf->client_header_buffer_size;
398 b = c->buffer;
400 if (b == NULL) {
401 b = ngx_create_temp_buf(c->pool, size);
402 if (b == NULL) {
403 ngx_http_close_connection(c);
404 return;
407 c->buffer = b;
409 } else if (b->start == NULL) {
411 b->start = ngx_palloc(c->pool, size);
412 if (b->start == NULL) {
413 ngx_http_close_connection(c);
414 return;
417 b->pos = b->start;
418 b->last = b->start;
419 b->end = b->last + size;
422 n = c->recv(c, b->last, size);
424 if (n == NGX_AGAIN) {
426 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
427 if (c->listening->deferred_accept
428 #if (NGX_HTTP_SSL)
429 && c->ssl == NULL
430 #endif
433 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
434 "client timed out in deferred accept");
435 ngx_http_close_connection(c);
436 return;
438 #endif
440 if (!rev->timer_set) {
441 ngx_add_timer(rev, c->listening->post_accept_timeout);
442 ngx_reusable_connection(c, 1);
445 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
446 ngx_http_close_connection(c);
447 return;
451 * We are trying to not hold c->buffer's memory for an idle connection.
454 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
455 b->start = NULL;
458 return;
461 if (n == NGX_ERROR) {
462 ngx_http_close_connection(c);
463 return;
466 if (n == 0) {
467 ngx_log_error(NGX_LOG_INFO, c->log, 0,
468 "client closed connection");
469 ngx_http_close_connection(c);
470 return;
473 b->last += n;
475 c->log->action = "reading client request line";
477 ngx_reusable_connection(c, 0);
479 c->data = ngx_http_create_request(c);
480 if (c->data == NULL) {
481 ngx_http_close_connection(c);
482 return;
485 rev->handler = ngx_http_process_request_line;
486 ngx_http_process_request_line(rev);
490 ngx_http_request_t *
491 ngx_http_create_request(ngx_connection_t *c)
493 ngx_pool_t *pool;
494 ngx_time_t *tp;
495 ngx_http_request_t *r;
496 ngx_http_log_ctx_t *ctx;
497 ngx_http_connection_t *hc;
498 ngx_http_core_srv_conf_t *cscf;
499 ngx_http_core_loc_conf_t *clcf;
500 ngx_http_core_main_conf_t *cmcf;
502 c->requests++;
504 hc = c->data;
506 cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
508 pool = ngx_create_pool(cscf->request_pool_size, c->log);
509 if (pool == NULL) {
510 return NULL;
513 r = ngx_pcalloc(pool, sizeof(ngx_http_request_t));
514 if (r == NULL) {
515 ngx_destroy_pool(pool);
516 return NULL;
519 r->pool = pool;
521 r->http_connection = hc;
522 r->signature = NGX_HTTP_MODULE;
523 r->connection = c;
525 r->main_conf = hc->conf_ctx->main_conf;
526 r->srv_conf = hc->conf_ctx->srv_conf;
527 r->loc_conf = hc->conf_ctx->loc_conf;
529 r->read_event_handler = ngx_http_block_reading;
531 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
533 ngx_http_set_connection_log(r->connection, clcf->error_log);
535 r->header_in = hc->nbusy ? hc->busy[0] : c->buffer;
537 if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
538 sizeof(ngx_table_elt_t))
539 != NGX_OK)
541 ngx_destroy_pool(r->pool);
542 return NULL;
545 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
546 if (r->ctx == NULL) {
547 ngx_destroy_pool(r->pool);
548 return NULL;
551 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
553 r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
554 * sizeof(ngx_http_variable_value_t));
555 if (r->variables == NULL) {
556 ngx_destroy_pool(r->pool);
557 return NULL;
560 #if (NGX_HTTP_SSL)
561 if (c->ssl) {
562 r->main_filter_need_in_memory = 1;
564 #endif
566 r->main = r;
567 r->count = 1;
569 tp = ngx_timeofday();
570 r->start_sec = tp->sec;
571 r->start_msec = tp->msec;
573 r->method = NGX_HTTP_UNKNOWN;
575 r->headers_in.content_length_n = -1;
576 r->headers_in.keep_alive_n = -1;
577 r->headers_out.content_length_n = -1;
578 r->headers_out.last_modified_time = -1;
580 r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
581 r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;
583 r->http_state = NGX_HTTP_READING_REQUEST_STATE;
585 ctx = c->log->data;
586 ctx->request = r;
587 ctx->current_request = r;
588 r->log_handler = ngx_http_log_error_handler;
590 #if (NGX_STAT_STUB)
591 (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
592 r->stat_reading = 1;
593 (void) ngx_atomic_fetch_add(ngx_stat_requests, 1);
594 #endif
596 return r;
600 #if (NGX_HTTP_SSL)
602 static void
603 ngx_http_ssl_handshake(ngx_event_t *rev)
605 u_char buf[1];
606 ssize_t n;
607 ngx_err_t err;
608 ngx_int_t rc;
609 ngx_connection_t *c;
610 ngx_http_connection_t *hc;
611 ngx_http_ssl_srv_conf_t *sscf;
613 c = rev->data;
615 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
616 "http check ssl handshake");
618 if (rev->timedout) {
619 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
620 ngx_http_close_connection(c);
621 return;
624 if (c->close) {
625 ngx_http_close_connection(c);
626 return;
629 n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
631 err = ngx_socket_errno;
633 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %d", n);
635 if (n == -1) {
636 if (err == NGX_EAGAIN) {
638 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
639 if (c->listening->deferred_accept) {
640 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
641 "client timed out in deferred accept");
642 ngx_http_close_connection(c);
643 return;
645 #endif
647 if (!rev->timer_set) {
648 ngx_add_timer(rev, c->listening->post_accept_timeout);
649 ngx_reusable_connection(c, 1);
652 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
653 ngx_http_close_connection(c);
656 return;
659 ngx_connection_error(c, err, "recv() failed");
660 ngx_http_close_connection(c);
662 return;
665 if (n == 1) {
666 if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
667 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
668 "https ssl handshake: 0x%02Xd", buf[0]);
670 hc = c->data;
671 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
672 ngx_http_ssl_module);
674 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
675 != NGX_OK)
677 ngx_http_close_connection(c);
678 return;
681 rc = ngx_ssl_handshake(c);
683 if (rc == NGX_AGAIN) {
685 if (!rev->timer_set) {
686 ngx_add_timer(rev, c->listening->post_accept_timeout);
689 ngx_reusable_connection(c, 0);
691 c->ssl->handler = ngx_http_ssl_handshake_handler;
692 return;
695 ngx_http_ssl_handshake_handler(c);
697 return;
700 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http");
702 c->log->action = "waiting for request";
704 rev->handler = ngx_http_wait_request_handler;
705 ngx_http_wait_request_handler(rev);
707 return;
710 ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection");
711 ngx_http_close_connection(c);
715 static void
716 ngx_http_ssl_handshake_handler(ngx_connection_t *c)
718 if (c->ssl->handshaked) {
721 * The majority of browsers do not send the "close notify" alert.
722 * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
723 * and Links. And what is more, MSIE ignores the server's alert.
725 * Opera and recent Mozilla send the alert.
728 c->ssl->no_wait_shutdown = 1;
730 #if (NGX_HTTP_SPDY && defined TLSEXT_TYPE_next_proto_neg)
732 unsigned int len;
733 const unsigned char *data;
734 static const ngx_str_t spdy = ngx_string(NGX_SPDY_NPN_NEGOTIATED);
736 SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
738 if (len == spdy.len && ngx_strncmp(data, spdy.data, spdy.len) == 0) {
739 ngx_http_spdy_init(c->read);
740 return;
743 #endif
745 c->log->action = "waiting for request";
747 c->read->handler = ngx_http_wait_request_handler;
748 /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
750 ngx_reusable_connection(c, 1);
752 ngx_http_wait_request_handler(c->read);
754 return;
757 if (c->read->timedout) {
758 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
761 ngx_http_close_connection(c);
764 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
767 ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
769 ngx_str_t host;
770 const char *servername;
771 ngx_connection_t *c;
772 ngx_http_connection_t *hc;
773 ngx_http_ssl_srv_conf_t *sscf;
774 ngx_http_core_loc_conf_t *clcf;
775 ngx_http_core_srv_conf_t *cscf;
777 servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
779 if (servername == NULL) {
780 return SSL_TLSEXT_ERR_NOACK;
783 c = ngx_ssl_get_connection(ssl_conn);
785 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
786 "SSL server name: \"%s\"", servername);
788 host.len = ngx_strlen(servername);
790 if (host.len == 0) {
791 return SSL_TLSEXT_ERR_NOACK;
794 host.data = (u_char *) servername;
796 if (ngx_http_validate_host(&host, c->pool, 1) != NGX_OK) {
797 return SSL_TLSEXT_ERR_NOACK;
800 hc = c->data;
802 if (ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host,
803 NULL, &cscf)
804 != NGX_OK)
806 return SSL_TLSEXT_ERR_NOACK;
809 hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t));
810 if (hc->ssl_servername == NULL) {
811 return SSL_TLSEXT_ERR_NOACK;
814 *hc->ssl_servername = host;
816 hc->conf_ctx = cscf->ctx;
818 clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module);
820 ngx_http_set_connection_log(c, clcf->error_log);
822 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
824 if (sscf->ssl.ctx) {
825 SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
828 * SSL_set_SSL_CTX() only changes certs as of 1.0.0d
829 * adjust other things we care about
832 SSL_set_verify(ssl_conn, SSL_CTX_get_verify_mode(sscf->ssl.ctx),
833 SSL_CTX_get_verify_callback(sscf->ssl.ctx));
835 SSL_set_verify_depth(ssl_conn, SSL_CTX_get_verify_depth(sscf->ssl.ctx));
837 #ifdef SSL_CTRL_CLEAR_OPTIONS
838 /* only in 0.9.8m+ */
839 SSL_clear_options(ssl_conn, SSL_get_options(ssl_conn) &
840 ~SSL_CTX_get_options(sscf->ssl.ctx));
841 #endif
843 SSL_set_options(ssl_conn, SSL_CTX_get_options(sscf->ssl.ctx));
846 return SSL_TLSEXT_ERR_OK;
849 #endif
851 #endif
854 static void
855 ngx_http_process_request_line(ngx_event_t *rev)
857 ssize_t n;
858 ngx_int_t rc, rv;
859 ngx_str_t host;
860 ngx_connection_t *c;
861 ngx_http_request_t *r;
863 c = rev->data;
864 r = c->data;
866 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
867 "http process request line");
869 if (rev->timedout) {
870 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
871 c->timedout = 1;
872 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
873 return;
876 rc = NGX_AGAIN;
878 for ( ;; ) {
880 if (rc == NGX_AGAIN) {
881 n = ngx_http_read_request_header(r);
883 if (n == NGX_AGAIN || n == NGX_ERROR) {
884 return;
888 rc = ngx_http_parse_request_line(r, r->header_in);
890 if (rc == NGX_OK) {
892 /* the request line has been parsed successfully */
894 r->request_line.len = r->request_end - r->request_start;
895 r->request_line.data = r->request_start;
896 r->request_length = r->header_in->pos - r->request_start;
898 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
899 "http request line: \"%V\"", &r->request_line);
901 r->method_name.len = r->method_end - r->request_start + 1;
902 r->method_name.data = r->request_line.data;
904 if (r->http_protocol.data) {
905 r->http_protocol.len = r->request_end - r->http_protocol.data;
908 if (ngx_http_process_request_uri(r) != NGX_OK) {
909 return;
912 if (r->host_start && r->host_end) {
914 host.len = r->host_end - r->host_start;
915 host.data = r->host_start;
917 rc = ngx_http_validate_host(&host, r->pool, 0);
919 if (rc == NGX_DECLINED) {
920 ngx_log_error(NGX_LOG_INFO, c->log, 0,
921 "client sent invalid host in request line");
922 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
923 return;
926 if (rc == NGX_ERROR) {
927 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
928 return;
931 if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
932 return;
935 r->headers_in.server = host;
938 if (r->http_version < NGX_HTTP_VERSION_10) {
940 if (r->headers_in.server.len == 0
941 && ngx_http_set_virtual_server(r, &r->headers_in.server)
942 == NGX_ERROR)
944 return;
947 ngx_http_process_request(r);
948 return;
952 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
953 sizeof(ngx_table_elt_t))
954 != NGX_OK)
956 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
957 return;
960 c->log->action = "reading client request headers";
962 rev->handler = ngx_http_process_request_headers;
963 ngx_http_process_request_headers(rev);
965 return;
968 if (rc != NGX_AGAIN) {
970 /* there was error while a request line parsing */
972 ngx_log_error(NGX_LOG_INFO, c->log, 0,
973 ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
974 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
975 return;
978 /* NGX_AGAIN: a request line parsing is still incomplete */
980 if (r->header_in->pos == r->header_in->end) {
982 rv = ngx_http_alloc_large_header_buffer(r, 1);
984 if (rv == NGX_ERROR) {
985 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
986 return;
989 if (rv == NGX_DECLINED) {
990 r->request_line.len = r->header_in->end - r->request_start;
991 r->request_line.data = r->request_start;
993 ngx_log_error(NGX_LOG_INFO, c->log, 0,
994 "client sent too long URI");
995 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
996 return;
1003 ngx_int_t
1004 ngx_http_process_request_uri(ngx_http_request_t *r)
1006 ngx_http_core_srv_conf_t *cscf;
1008 if (r->args_start) {
1009 r->uri.len = r->args_start - 1 - r->uri_start;
1010 } else {
1011 r->uri.len = r->uri_end - r->uri_start;
1014 if (r->complex_uri || r->quoted_uri) {
1016 r->uri.data = ngx_pnalloc(r->pool, r->uri.len + 1);
1017 if (r->uri.data == NULL) {
1018 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1019 return NGX_ERROR;
1022 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1024 if (ngx_http_parse_complex_uri(r, cscf->merge_slashes) != NGX_OK) {
1025 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1026 "client sent invalid request");
1027 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1028 return NGX_ERROR;
1031 } else {
1032 r->uri.data = r->uri_start;
1035 r->unparsed_uri.len = r->uri_end - r->uri_start;
1036 r->unparsed_uri.data = r->uri_start;
1038 r->valid_unparsed_uri = r->space_in_uri ? 0 : 1;
1040 if (r->uri_ext) {
1041 if (r->args_start) {
1042 r->exten.len = r->args_start - 1 - r->uri_ext;
1043 } else {
1044 r->exten.len = r->uri_end - r->uri_ext;
1047 r->exten.data = r->uri_ext;
1050 if (r->args_start && r->uri_end > r->args_start) {
1051 r->args.len = r->uri_end - r->args_start;
1052 r->args.data = r->args_start;
1055 #if (NGX_WIN32)
1057 u_char *p, *last;
1059 p = r->uri.data;
1060 last = r->uri.data + r->uri.len;
1062 while (p < last) {
1064 if (*p++ == ':') {
1067 * this check covers "::$data", "::$index_allocation" and
1068 * ":$i30:$index_allocation"
1071 if (p < last && *p == '$') {
1072 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1073 "client sent unsafe win32 URI");
1074 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1075 return NGX_ERROR;
1080 p = r->uri.data + r->uri.len - 1;
1082 while (p > r->uri.data) {
1084 if (*p == ' ') {
1085 p--;
1086 continue;
1089 if (*p == '.') {
1090 p--;
1091 continue;
1094 break;
1097 if (p != r->uri.data + r->uri.len - 1) {
1098 r->uri.len = p + 1 - r->uri.data;
1099 ngx_http_set_exten(r);
1103 #endif
1105 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1106 "http uri: \"%V\"", &r->uri);
1108 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1109 "http args: \"%V\"", &r->args);
1111 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1112 "http exten: \"%V\"", &r->exten);
1114 return NGX_OK;
1118 static void
1119 ngx_http_process_request_headers(ngx_event_t *rev)
1121 u_char *p;
1122 size_t len;
1123 ssize_t n;
1124 ngx_int_t rc, rv;
1125 ngx_table_elt_t *h;
1126 ngx_connection_t *c;
1127 ngx_http_header_t *hh;
1128 ngx_http_request_t *r;
1129 ngx_http_core_srv_conf_t *cscf;
1130 ngx_http_core_main_conf_t *cmcf;
1132 c = rev->data;
1133 r = c->data;
1135 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
1136 "http process request header line");
1138 if (rev->timedout) {
1139 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
1140 c->timedout = 1;
1141 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
1142 return;
1145 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1147 rc = NGX_AGAIN;
1149 for ( ;; ) {
1151 if (rc == NGX_AGAIN) {
1153 if (r->header_in->pos == r->header_in->end) {
1155 rv = ngx_http_alloc_large_header_buffer(r, 0);
1157 if (rv == NGX_ERROR) {
1158 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1159 return;
1162 if (rv == NGX_DECLINED) {
1163 p = r->header_name_start;
1165 r->lingering_close = 1;
1167 if (p == NULL) {
1168 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1169 "client sent too large request");
1170 ngx_http_finalize_request(r,
1171 NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
1172 return;
1175 len = r->header_in->end - p;
1177 if (len > NGX_MAX_ERROR_STR - 300) {
1178 len = NGX_MAX_ERROR_STR - 300;
1179 p[len++] = '.'; p[len++] = '.'; p[len++] = '.';
1182 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1183 "client sent too long header line: \"%*s\"",
1184 len, r->header_name_start);
1186 ngx_http_finalize_request(r,
1187 NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
1188 return;
1192 n = ngx_http_read_request_header(r);
1194 if (n == NGX_AGAIN || n == NGX_ERROR) {
1195 return;
1199 /* the host header could change the server configuration context */
1200 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1202 rc = ngx_http_parse_header_line(r, r->header_in,
1203 cscf->underscores_in_headers);
1205 if (rc == NGX_OK) {
1207 r->request_length += r->header_in->pos - r->header_name_start;
1209 if (r->invalid_header && cscf->ignore_invalid_headers) {
1211 /* there was error while a header line parsing */
1213 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1214 "client sent invalid header line: \"%*s\"",
1215 r->header_end - r->header_name_start,
1216 r->header_name_start);
1217 continue;
1220 /* a header line has been parsed successfully */
1222 h = ngx_list_push(&r->headers_in.headers);
1223 if (h == NULL) {
1224 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1225 return;
1228 h->hash = r->header_hash;
1230 h->key.len = r->header_name_end - r->header_name_start;
1231 h->key.data = r->header_name_start;
1232 h->key.data[h->key.len] = '\0';
1234 h->value.len = r->header_end - r->header_start;
1235 h->value.data = r->header_start;
1236 h->value.data[h->value.len] = '\0';
1238 h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
1239 if (h->lowcase_key == NULL) {
1240 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1241 return;
1244 if (h->key.len == r->lowcase_index) {
1245 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
1247 } else {
1248 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
1251 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
1252 h->lowcase_key, h->key.len);
1254 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
1255 return;
1258 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1259 "http header: \"%V: %V\"",
1260 &h->key, &h->value);
1262 continue;
1265 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1267 /* a whole header has been parsed successfully */
1269 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1270 "http header done");
1272 r->request_length += r->header_in->pos - r->header_name_start;
1274 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
1276 rc = ngx_http_process_request_header(r);
1278 if (rc != NGX_OK) {
1279 return;
1282 ngx_http_process_request(r);
1284 return;
1287 if (rc == NGX_AGAIN) {
1289 /* a header line parsing is still not complete */
1291 continue;
1294 /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
1296 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1297 "client sent invalid header line: \"%*s\\r...\"",
1298 r->header_end - r->header_name_start,
1299 r->header_name_start);
1300 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1301 return;
1306 static ssize_t
1307 ngx_http_read_request_header(ngx_http_request_t *r)
1309 ssize_t n;
1310 ngx_event_t *rev;
1311 ngx_connection_t *c;
1312 ngx_http_core_srv_conf_t *cscf;
1314 c = r->connection;
1315 rev = c->read;
1317 n = r->header_in->last - r->header_in->pos;
1319 if (n > 0) {
1320 return n;
1323 if (rev->ready) {
1324 n = c->recv(c, r->header_in->last,
1325 r->header_in->end - r->header_in->last);
1326 } else {
1327 n = NGX_AGAIN;
1330 if (n == NGX_AGAIN) {
1331 if (!rev->timer_set) {
1332 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1333 ngx_add_timer(rev, cscf->client_header_timeout);
1336 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1337 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1338 return NGX_ERROR;
1341 return NGX_AGAIN;
1344 if (n == 0) {
1345 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1346 "client prematurely closed connection");
1349 if (n == 0 || n == NGX_ERROR) {
1350 c->error = 1;
1351 c->log->action = "reading client request headers";
1353 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1354 return NGX_ERROR;
1357 r->header_in->last += n;
1359 return n;
1363 static ngx_int_t
1364 ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
1365 ngx_uint_t request_line)
1367 u_char *old, *new;
1368 ngx_buf_t *b;
1369 ngx_http_connection_t *hc;
1370 ngx_http_core_srv_conf_t *cscf;
1372 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1373 "http alloc large header buffer");
1375 if (request_line && r->state == 0) {
1377 /* the client fills up the buffer with "\r\n" */
1379 r->header_in->pos = r->header_in->start;
1380 r->header_in->last = r->header_in->start;
1382 return NGX_OK;
1385 old = request_line ? r->request_start : r->header_name_start;
1387 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1389 if (r->state != 0
1390 && (size_t) (r->header_in->pos - old)
1391 >= cscf->large_client_header_buffers.size)
1393 return NGX_DECLINED;
1396 hc = r->http_connection;
1398 if (hc->nfree) {
1399 b = hc->free[--hc->nfree];
1401 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1402 "http large header free: %p %uz",
1403 b->pos, b->end - b->last);
1405 } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
1407 if (hc->busy == NULL) {
1408 hc->busy = ngx_palloc(r->connection->pool,
1409 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
1410 if (hc->busy == NULL) {
1411 return NGX_ERROR;
1415 b = ngx_create_temp_buf(r->connection->pool,
1416 cscf->large_client_header_buffers.size);
1417 if (b == NULL) {
1418 return NGX_ERROR;
1421 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1422 "http large header alloc: %p %uz",
1423 b->pos, b->end - b->last);
1425 } else {
1426 return NGX_DECLINED;
1429 hc->busy[hc->nbusy++] = b;
1431 if (r->state == 0) {
1433 * r->state == 0 means that a header line was parsed successfully
1434 * and we do not need to copy incomplete header line and
1435 * to relocate the parser header pointers
1438 r->header_in = b;
1440 return NGX_OK;
1443 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1444 "http large header copy: %d", r->header_in->pos - old);
1446 new = b->start;
1448 ngx_memcpy(new, old, r->header_in->pos - old);
1450 b->pos = new + (r->header_in->pos - old);
1451 b->last = new + (r->header_in->pos - old);
1453 if (request_line) {
1454 r->request_start = new;
1456 if (r->request_end) {
1457 r->request_end = new + (r->request_end - old);
1460 r->method_end = new + (r->method_end - old);
1462 r->uri_start = new + (r->uri_start - old);
1463 r->uri_end = new + (r->uri_end - old);
1465 if (r->schema_start) {
1466 r->schema_start = new + (r->schema_start - old);
1467 r->schema_end = new + (r->schema_end - old);
1470 if (r->host_start) {
1471 r->host_start = new + (r->host_start - old);
1472 if (r->host_end) {
1473 r->host_end = new + (r->host_end - old);
1477 if (r->port_start) {
1478 r->port_start = new + (r->port_start - old);
1479 r->port_end = new + (r->port_end - old);
1482 if (r->uri_ext) {
1483 r->uri_ext = new + (r->uri_ext - old);
1486 if (r->args_start) {
1487 r->args_start = new + (r->args_start - old);
1490 if (r->http_protocol.data) {
1491 r->http_protocol.data = new + (r->http_protocol.data - old);
1494 } else {
1495 r->header_name_start = new;
1496 r->header_name_end = new + (r->header_name_end - old);
1497 r->header_start = new + (r->header_start - old);
1498 r->header_end = new + (r->header_end - old);
1501 r->header_in = b;
1503 return NGX_OK;
1507 static ngx_int_t
1508 ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1509 ngx_uint_t offset)
1511 ngx_table_elt_t **ph;
1513 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1515 if (*ph == NULL) {
1516 *ph = h;
1519 return NGX_OK;
1523 static ngx_int_t
1524 ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1525 ngx_uint_t offset)
1527 ngx_table_elt_t **ph;
1529 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1531 if (*ph == NULL) {
1532 *ph = h;
1533 return NGX_OK;
1536 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1537 "client sent duplicate header line: \"%V: %V\", "
1538 "previous value: \"%V: %V\"",
1539 &h->key, &h->value, &(*ph)->key, &(*ph)->value);
1541 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1543 return NGX_ERROR;
1547 static ngx_int_t
1548 ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
1549 ngx_uint_t offset)
1551 ngx_int_t rc;
1552 ngx_str_t host;
1554 if (r->headers_in.host == NULL) {
1555 r->headers_in.host = h;
1558 host = h->value;
1560 rc = ngx_http_validate_host(&host, r->pool, 0);
1562 if (rc == NGX_DECLINED) {
1563 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1564 "client sent invalid host header");
1565 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1566 return NGX_ERROR;
1569 if (rc == NGX_ERROR) {
1570 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1571 return NGX_ERROR;
1574 if (r->headers_in.server.len) {
1575 return NGX_OK;
1578 if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
1579 return NGX_ERROR;
1582 r->headers_in.server = host;
1584 return NGX_OK;
1588 static ngx_int_t
1589 ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
1590 ngx_uint_t offset)
1592 if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
1593 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1595 } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {
1596 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1599 return NGX_OK;
1603 static ngx_int_t
1604 ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
1605 ngx_uint_t offset)
1607 u_char *user_agent, *msie;
1609 if (r->headers_in.user_agent) {
1610 return NGX_OK;
1613 r->headers_in.user_agent = h;
1615 /* check some widespread browsers while the header is in CPU cache */
1617 user_agent = h->value.data;
1619 msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
1621 if (msie && msie + 7 < user_agent + h->value.len) {
1623 r->headers_in.msie = 1;
1625 if (msie[6] == '.') {
1627 switch (msie[5]) {
1628 case '4':
1629 case '5':
1630 r->headers_in.msie6 = 1;
1631 break;
1632 case '6':
1633 if (ngx_strstrn(msie + 8, "SV1", 3 - 1) == NULL) {
1634 r->headers_in.msie6 = 1;
1636 break;
1640 #if 0
1641 /* MSIE ignores the SSL "close notify" alert */
1642 if (c->ssl) {
1643 c->ssl->no_send_shutdown = 1;
1645 #endif
1648 if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
1649 r->headers_in.opera = 1;
1650 r->headers_in.msie = 0;
1651 r->headers_in.msie6 = 0;
1654 if (!r->headers_in.msie && !r->headers_in.opera) {
1656 if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
1657 r->headers_in.gecko = 1;
1659 } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
1660 r->headers_in.chrome = 1;
1662 } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)
1663 && ngx_strstrn(user_agent, "Mac OS X", 8 - 1))
1665 r->headers_in.safari = 1;
1667 } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
1668 r->headers_in.konqueror = 1;
1672 return NGX_OK;
1676 static ngx_int_t
1677 ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h,
1678 ngx_uint_t offset)
1680 ngx_array_t *headers;
1681 ngx_table_elt_t **ph;
1683 headers = (ngx_array_t *) ((char *) &r->headers_in + offset);
1685 if (headers->elts == NULL) {
1686 if (ngx_array_init(headers, r->pool, 1, sizeof(ngx_table_elt_t *))
1687 != NGX_OK)
1689 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1690 return NGX_ERROR;
1694 ph = ngx_array_push(headers);
1695 if (ph == NULL) {
1696 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1697 return NGX_ERROR;
1700 *ph = h;
1701 return NGX_OK;
1705 ngx_int_t
1706 ngx_http_process_request_header(ngx_http_request_t *r)
1708 if (r->headers_in.server.len == 0
1709 && ngx_http_set_virtual_server(r, &r->headers_in.server)
1710 == NGX_ERROR)
1712 return NGX_ERROR;
1715 if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) {
1716 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1717 "client sent HTTP/1.1 request without \"Host\" header");
1718 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1719 return NGX_ERROR;
1722 if (r->headers_in.content_length) {
1723 r->headers_in.content_length_n =
1724 ngx_atoof(r->headers_in.content_length->value.data,
1725 r->headers_in.content_length->value.len);
1727 if (r->headers_in.content_length_n == NGX_ERROR) {
1728 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1729 "client sent invalid \"Content-Length\" header");
1730 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1731 return NGX_ERROR;
1735 if (r->method & NGX_HTTP_TRACE) {
1736 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1737 "client sent TRACE method");
1738 ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
1739 return NGX_ERROR;
1742 if (r->headers_in.transfer_encoding) {
1743 if (r->headers_in.transfer_encoding->value.len == 7
1744 && ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
1745 (u_char *) "chunked", 7) == 0)
1747 r->headers_in.content_length = NULL;
1748 r->headers_in.content_length_n = -1;
1749 r->headers_in.chunked = 1;
1751 } else if (r->headers_in.transfer_encoding->value.len != 8
1752 || ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
1753 (u_char *) "identity", 8) != 0)
1755 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1756 "client sent unknown \"Transfer-Encoding\": \"%V\"",
1757 &r->headers_in.transfer_encoding->value);
1758 ngx_http_finalize_request(r, NGX_HTTP_NOT_IMPLEMENTED);
1759 return NGX_ERROR;
1763 if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
1764 if (r->headers_in.keep_alive) {
1765 r->headers_in.keep_alive_n =
1766 ngx_atotm(r->headers_in.keep_alive->value.data,
1767 r->headers_in.keep_alive->value.len);
1771 return NGX_OK;
1775 void
1776 ngx_http_process_request(ngx_http_request_t *r)
1778 ngx_connection_t *c;
1780 c = r->connection;
1782 #if (NGX_HTTP_SSL)
1784 if (r->http_connection->ssl) {
1785 long rc;
1786 X509 *cert;
1787 ngx_http_ssl_srv_conf_t *sscf;
1789 if (c->ssl == NULL) {
1790 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1791 "client sent plain HTTP request to HTTPS port");
1792 ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1793 return;
1796 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
1798 if (sscf->verify) {
1799 rc = SSL_get_verify_result(c->ssl->connection);
1801 if (rc != X509_V_OK
1802 && (sscf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
1804 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1805 "client SSL certificate verify error: (%l:%s)",
1806 rc, X509_verify_cert_error_string(rc));
1808 ngx_ssl_remove_cached_session(sscf->ssl.ctx,
1809 (SSL_get0_session(c->ssl->connection)));
1811 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
1812 return;
1815 if (sscf->verify == 1) {
1816 cert = SSL_get_peer_certificate(c->ssl->connection);
1818 if (cert == NULL) {
1819 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1820 "client sent no required SSL certificate");
1822 ngx_ssl_remove_cached_session(sscf->ssl.ctx,
1823 (SSL_get0_session(c->ssl->connection)));
1825 ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
1826 return;
1829 X509_free(cert);
1834 #endif
1836 if (c->read->timer_set) {
1837 ngx_del_timer(c->read);
1840 #if (NGX_STAT_STUB)
1841 (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
1842 r->stat_reading = 0;
1843 (void) ngx_atomic_fetch_add(ngx_stat_writing, 1);
1844 r->stat_writing = 1;
1845 #endif
1847 c->read->handler = ngx_http_request_handler;
1848 c->write->handler = ngx_http_request_handler;
1849 r->read_event_handler = ngx_http_block_reading;
1851 ngx_http_handler(r);
1853 ngx_http_run_posted_requests(c);
1857 static ngx_int_t
1858 ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
1860 u_char *h, ch;
1861 size_t i, dot_pos, host_len;
1863 enum {
1864 sw_usual = 0,
1865 sw_literal,
1866 sw_rest
1867 } state;
1869 dot_pos = host->len;
1870 host_len = host->len;
1872 h = host->data;
1874 state = sw_usual;
1876 for (i = 0; i < host->len; i++) {
1877 ch = h[i];
1879 switch (ch) {
1881 case '.':
1882 if (dot_pos == i - 1) {
1883 return NGX_DECLINED;
1885 dot_pos = i;
1886 break;
1888 case ':':
1889 if (state == sw_usual) {
1890 host_len = i;
1891 state = sw_rest;
1893 break;
1895 case '[':
1896 if (i == 0) {
1897 state = sw_literal;
1899 break;
1901 case ']':
1902 if (state == sw_literal) {
1903 host_len = i + 1;
1904 state = sw_rest;
1906 break;
1908 case '\0':
1909 return NGX_DECLINED;
1911 default:
1913 if (ngx_path_separator(ch)) {
1914 return NGX_DECLINED;
1917 if (ch >= 'A' && ch <= 'Z') {
1918 alloc = 1;
1921 break;
1925 if (dot_pos == host_len - 1) {
1926 host_len--;
1929 if (host_len == 0) {
1930 return NGX_DECLINED;
1933 if (alloc) {
1934 host->data = ngx_pnalloc(pool, host_len);
1935 if (host->data == NULL) {
1936 return NGX_ERROR;
1939 ngx_strlow(host->data, h, host_len);
1942 host->len = host_len;
1944 return NGX_OK;
1948 static ngx_int_t
1949 ngx_http_set_virtual_server(ngx_http_request_t *r, ngx_str_t *host)
1951 ngx_int_t rc;
1952 ngx_http_connection_t *hc;
1953 ngx_http_core_loc_conf_t *clcf;
1954 ngx_http_core_srv_conf_t *cscf;
1956 hc = r->http_connection;
1958 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1960 if (hc->ssl_servername) {
1961 if (hc->ssl_servername->len == host->len
1962 && ngx_strncmp(hc->ssl_servername->data,
1963 host->data, host->len) == 0)
1965 #if (NGX_PCRE)
1966 if (hc->ssl_servername_regex
1967 && ngx_http_regex_exec(r, hc->ssl_servername_regex,
1968 hc->ssl_servername) != NGX_OK)
1970 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1971 return NGX_ERROR;
1973 #endif
1974 return NGX_OK;
1978 #endif
1980 rc = ngx_http_find_virtual_server(r->connection,
1981 hc->addr_conf->virtual_names,
1982 host, r, &cscf);
1984 if (rc == NGX_ERROR) {
1985 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1986 return NGX_ERROR;
1989 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1991 if (hc->ssl_servername) {
1992 ngx_http_ssl_srv_conf_t *sscf;
1994 if (rc == NGX_DECLINED) {
1995 cscf = hc->addr_conf->default_server;
1996 rc = NGX_OK;
1999 sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module);
2001 if (sscf->verify) {
2002 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2003 "client attempted to request the server name "
2004 "different from that one was negotiated");
2005 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
2006 return NGX_ERROR;
2010 #endif
2012 if (rc == NGX_DECLINED) {
2013 return NGX_OK;
2016 r->srv_conf = cscf->ctx->srv_conf;
2017 r->loc_conf = cscf->ctx->loc_conf;
2019 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2021 ngx_http_set_connection_log(r->connection, clcf->error_log);
2023 return NGX_OK;
2027 static ngx_int_t
2028 ngx_http_find_virtual_server(ngx_connection_t *c,
2029 ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
2030 ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp)
2032 ngx_http_core_srv_conf_t *cscf;
2034 if (virtual_names == NULL) {
2035 return NGX_DECLINED;
2038 cscf = ngx_hash_find_combined(&virtual_names->names,
2039 ngx_hash_key(host->data, host->len),
2040 host->data, host->len);
2042 if (cscf) {
2043 *cscfp = cscf;
2044 return NGX_OK;
2047 #if (NGX_PCRE)
2049 if (host->len && virtual_names->nregex) {
2050 ngx_int_t n;
2051 ngx_uint_t i;
2052 ngx_http_server_name_t *sn;
2054 sn = virtual_names->regex;
2056 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2058 if (r == NULL) {
2059 ngx_http_connection_t *hc;
2061 for (i = 0; i < virtual_names->nregex; i++) {
2063 n = ngx_regex_exec(sn[i].regex->regex, host, NULL, 0);
2065 if (n == NGX_REGEX_NO_MATCHED) {
2066 continue;
2069 if (n >= 0) {
2070 hc = c->data;
2071 hc->ssl_servername_regex = sn[i].regex;
2073 *cscfp = sn[i].server;
2074 return NGX_OK;
2077 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2078 ngx_regex_exec_n " failed: %i "
2079 "on \"%V\" using \"%V\"",
2080 n, host, &sn[i].regex->name);
2082 return NGX_ERROR;
2085 return NGX_DECLINED;
2088 #endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2090 for (i = 0; i < virtual_names->nregex; i++) {
2092 n = ngx_http_regex_exec(r, sn[i].regex, host);
2094 if (n == NGX_DECLINED) {
2095 continue;
2098 if (n == NGX_OK) {
2099 *cscfp = sn[i].server;
2100 return NGX_OK;
2103 return NGX_ERROR;
2107 #endif /* NGX_PCRE */
2109 return NGX_DECLINED;
2113 static void
2114 ngx_http_request_handler(ngx_event_t *ev)
2116 ngx_connection_t *c;
2117 ngx_http_request_t *r;
2118 ngx_http_log_ctx_t *ctx;
2120 c = ev->data;
2121 r = c->data;
2123 ctx = c->log->data;
2124 ctx->current_request = r;
2126 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2127 "http run request: \"%V?%V\"", &r->uri, &r->args);
2129 if (ev->write) {
2130 r->write_event_handler(r);
2132 } else {
2133 r->read_event_handler(r);
2136 ngx_http_run_posted_requests(c);
2140 void
2141 ngx_http_run_posted_requests(ngx_connection_t *c)
2143 ngx_http_request_t *r;
2144 ngx_http_log_ctx_t *ctx;
2145 ngx_http_posted_request_t *pr;
2147 for ( ;; ) {
2149 if (c->destroyed) {
2150 return;
2153 r = c->data;
2154 pr = r->main->posted_requests;
2156 if (pr == NULL) {
2157 return;
2160 r->main->posted_requests = pr->next;
2162 r = pr->request;
2164 ctx = c->log->data;
2165 ctx->current_request = r;
2167 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2168 "http posted request: \"%V?%V\"", &r->uri, &r->args);
2170 r->write_event_handler(r);
2175 ngx_int_t
2176 ngx_http_post_request(ngx_http_request_t *r, ngx_http_posted_request_t *pr)
2178 ngx_http_posted_request_t **p;
2180 if (pr == NULL) {
2181 pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
2182 if (pr == NULL) {
2183 return NGX_ERROR;
2187 pr->request = r;
2188 pr->next = NULL;
2190 for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ }
2192 *p = pr;
2194 return NGX_OK;
2198 void
2199 ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
2201 ngx_connection_t *c;
2202 ngx_http_request_t *pr;
2203 ngx_http_core_loc_conf_t *clcf;
2205 c = r->connection;
2207 ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
2208 "http finalize request: %d, \"%V?%V\" a:%d, c:%d",
2209 rc, &r->uri, &r->args, r == c->data, r->main->count);
2211 if (rc == NGX_DONE) {
2212 ngx_http_finalize_connection(r);
2213 return;
2216 if (rc == NGX_OK && r->filter_finalize) {
2217 c->error = 1;
2220 if (rc == NGX_DECLINED) {
2221 r->content_handler = NULL;
2222 r->write_event_handler = ngx_http_core_run_phases;
2223 ngx_http_core_run_phases(r);
2224 return;
2227 if (r != r->main && r->post_subrequest) {
2228 rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
2231 if (rc == NGX_ERROR
2232 || rc == NGX_HTTP_REQUEST_TIME_OUT
2233 || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
2234 || c->error)
2236 if (ngx_http_post_action(r) == NGX_OK) {
2237 return;
2240 if (r->main->blocked) {
2241 r->write_event_handler = ngx_http_request_finalizer;
2244 ngx_http_terminate_request(r, rc);
2245 return;
2248 if (rc >= NGX_HTTP_SPECIAL_RESPONSE
2249 || rc == NGX_HTTP_CREATED
2250 || rc == NGX_HTTP_NO_CONTENT)
2252 if (rc == NGX_HTTP_CLOSE) {
2253 ngx_http_terminate_request(r, rc);
2254 return;
2257 if (r == r->main) {
2258 if (c->read->timer_set) {
2259 ngx_del_timer(c->read);
2262 if (c->write->timer_set) {
2263 ngx_del_timer(c->write);
2267 c->read->handler = ngx_http_request_handler;
2268 c->write->handler = ngx_http_request_handler;
2270 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
2271 return;
2274 if (r != r->main) {
2276 if (r->buffered || r->postponed) {
2278 if (ngx_http_set_write_handler(r) != NGX_OK) {
2279 ngx_http_terminate_request(r, 0);
2282 return;
2285 pr = r->parent;
2287 if (r == c->data) {
2289 r->main->count--;
2290 r->main->subrequests++;
2292 if (!r->logged) {
2294 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2296 if (clcf->log_subrequest) {
2297 ngx_http_log_request(r);
2300 r->logged = 1;
2302 } else {
2303 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2304 "subrequest: \"%V?%V\" logged again",
2305 &r->uri, &r->args);
2308 r->done = 1;
2310 if (pr->postponed && pr->postponed->request == r) {
2311 pr->postponed = pr->postponed->next;
2314 c->data = pr;
2316 } else {
2318 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2319 "http finalize non-active request: \"%V?%V\"",
2320 &r->uri, &r->args);
2322 r->write_event_handler = ngx_http_request_finalizer;
2324 if (r->waited) {
2325 r->done = 1;
2329 if (ngx_http_post_request(pr, NULL) != NGX_OK) {
2330 r->main->count++;
2331 ngx_http_terminate_request(r, 0);
2332 return;
2335 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2336 "http wake parent request: \"%V?%V\"",
2337 &pr->uri, &pr->args);
2339 return;
2342 if (r->buffered || c->buffered || r->postponed || r->blocked) {
2344 if (ngx_http_set_write_handler(r) != NGX_OK) {
2345 ngx_http_terminate_request(r, 0);
2348 return;
2351 if (r != c->data) {
2352 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2353 "http finalize non-active request: \"%V?%V\"",
2354 &r->uri, &r->args);
2355 return;
2358 r->done = 1;
2359 r->write_event_handler = ngx_http_request_empty_handler;
2361 if (!r->post_action) {
2362 r->request_complete = 1;
2365 if (ngx_http_post_action(r) == NGX_OK) {
2366 return;
2369 if (c->read->timer_set) {
2370 ngx_del_timer(c->read);
2373 if (c->write->timer_set) {
2374 c->write->delayed = 0;
2375 ngx_del_timer(c->write);
2378 if (c->read->eof) {
2379 ngx_http_close_request(r, 0);
2380 return;
2383 ngx_http_finalize_connection(r);
2387 static void
2388 ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc)
2390 ngx_http_cleanup_t *cln;
2391 ngx_http_request_t *mr;
2392 ngx_http_ephemeral_t *e;
2394 mr = r->main;
2396 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2397 "http terminate request count:%d", mr->count);
2399 if (rc > 0 && (mr->headers_out.status == 0 || mr->connection->sent == 0)) {
2400 mr->headers_out.status = rc;
2403 cln = mr->cleanup;
2404 mr->cleanup = NULL;
2406 while (cln) {
2407 if (cln->handler) {
2408 cln->handler(cln->data);
2411 cln = cln->next;
2414 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2415 "http terminate cleanup count:%d blk:%d",
2416 mr->count, mr->blocked);
2418 if (mr->write_event_handler) {
2420 if (mr->blocked) {
2421 return;
2424 e = ngx_http_ephemeral(mr);
2425 mr->posted_requests = NULL;
2426 mr->write_event_handler = ngx_http_terminate_handler;
2427 (void) ngx_http_post_request(mr, &e->terminal_posted_request);
2428 return;
2431 ngx_http_close_request(mr, rc);
2435 static void
2436 ngx_http_terminate_handler(ngx_http_request_t *r)
2438 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2439 "http terminate handler count:%d", r->count);
2441 r->count = 1;
2443 ngx_http_close_request(r, 0);
2447 static void
2448 ngx_http_finalize_connection(ngx_http_request_t *r)
2450 ngx_http_core_loc_conf_t *clcf;
2452 #if (NGX_HTTP_SPDY)
2453 if (r->spdy_stream) {
2454 ngx_http_close_request(r, 0);
2455 return;
2457 #endif
2459 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2461 if (r->main->count != 1) {
2463 if (r->discard_body) {
2464 r->read_event_handler = ngx_http_discarded_request_body_handler;
2465 ngx_add_timer(r->connection->read, clcf->lingering_timeout);
2467 if (r->lingering_time == 0) {
2468 r->lingering_time = ngx_time()
2469 + (time_t) (clcf->lingering_time / 1000);
2473 ngx_http_close_request(r, 0);
2474 return;
2477 if (!ngx_terminate
2478 && !ngx_exiting
2479 && r->keepalive
2480 && clcf->keepalive_timeout > 0)
2482 ngx_http_set_keepalive(r);
2483 return;
2486 if (clcf->lingering_close == NGX_HTTP_LINGERING_ALWAYS
2487 || (clcf->lingering_close == NGX_HTTP_LINGERING_ON
2488 && (r->lingering_close
2489 || r->header_in->pos < r->header_in->last
2490 || r->connection->read->ready)))
2492 ngx_http_set_lingering_close(r);
2493 return;
2496 ngx_http_close_request(r, 0);
2500 static ngx_int_t
2501 ngx_http_set_write_handler(ngx_http_request_t *r)
2503 ngx_event_t *wev;
2504 ngx_http_core_loc_conf_t *clcf;
2506 r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
2508 r->read_event_handler = r->discard_body ?
2509 ngx_http_discarded_request_body_handler:
2510 ngx_http_test_reading;
2511 r->write_event_handler = ngx_http_writer;
2513 #if (NGX_HTTP_SPDY)
2514 if (r->spdy_stream) {
2515 return NGX_OK;
2517 #endif
2519 wev = r->connection->write;
2521 if (wev->ready && wev->delayed) {
2522 return NGX_OK;
2525 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2526 if (!wev->delayed) {
2527 ngx_add_timer(wev, clcf->send_timeout);
2530 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2531 ngx_http_close_request(r, 0);
2532 return NGX_ERROR;
2535 return NGX_OK;
2539 static void
2540 ngx_http_writer(ngx_http_request_t *r)
2542 int rc;
2543 ngx_event_t *wev;
2544 ngx_connection_t *c;
2545 ngx_http_core_loc_conf_t *clcf;
2547 c = r->connection;
2548 wev = c->write;
2550 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2551 "http writer handler: \"%V?%V\"", &r->uri, &r->args);
2553 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
2555 if (wev->timedout) {
2556 if (!wev->delayed) {
2557 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
2558 "client timed out");
2559 c->timedout = 1;
2561 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
2562 return;
2565 wev->timedout = 0;
2566 wev->delayed = 0;
2568 if (!wev->ready) {
2569 ngx_add_timer(wev, clcf->send_timeout);
2571 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2572 ngx_http_close_request(r, 0);
2575 return;
2580 if (wev->delayed || r->aio) {
2581 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2582 "http writer delayed");
2584 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2585 ngx_http_close_request(r, 0);
2588 return;
2591 rc = ngx_http_output_filter(r, NULL);
2593 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
2594 "http writer output filter: %d, \"%V?%V\"",
2595 rc, &r->uri, &r->args);
2597 if (rc == NGX_ERROR) {
2598 ngx_http_finalize_request(r, rc);
2599 return;
2602 if (r->buffered || r->postponed || (r == r->main && c->buffered)) {
2604 if (!wev->delayed) {
2605 ngx_add_timer(wev, clcf->send_timeout);
2608 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2609 ngx_http_close_request(r, 0);
2612 return;
2615 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2616 "http writer done: \"%V?%V\"", &r->uri, &r->args);
2618 r->write_event_handler = ngx_http_request_empty_handler;
2620 ngx_http_finalize_request(r, rc);
2624 static void
2625 ngx_http_request_finalizer(ngx_http_request_t *r)
2627 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2628 "http finalizer done: \"%V?%V\"", &r->uri, &r->args);
2630 ngx_http_finalize_request(r, 0);
2634 void
2635 ngx_http_block_reading(ngx_http_request_t *r)
2637 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2638 "http reading blocked");
2640 /* aio does not call this handler */
2642 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
2643 && r->connection->read->active)
2645 if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) != NGX_OK) {
2646 ngx_http_close_request(r, 0);
2652 void
2653 ngx_http_test_reading(ngx_http_request_t *r)
2655 int n;
2656 char buf[1];
2657 ngx_err_t err;
2658 ngx_event_t *rev;
2659 ngx_connection_t *c;
2661 c = r->connection;
2662 rev = c->read;
2664 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading");
2666 #if (NGX_HTTP_SPDY)
2668 if (r->spdy_stream) {
2669 if (c->error) {
2670 err = 0;
2671 goto closed;
2674 return;
2677 #endif
2679 #if (NGX_HAVE_KQUEUE)
2681 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2683 if (!rev->pending_eof) {
2684 return;
2687 rev->eof = 1;
2688 c->error = 1;
2689 err = rev->kq_errno;
2691 goto closed;
2694 #endif
2696 n = recv(c->fd, buf, 1, MSG_PEEK);
2698 if (n == 0) {
2699 rev->eof = 1;
2700 c->error = 1;
2701 err = 0;
2703 goto closed;
2705 } else if (n == -1) {
2706 err = ngx_socket_errno;
2708 if (err != NGX_EAGAIN) {
2709 rev->eof = 1;
2710 c->error = 1;
2712 goto closed;
2716 /* aio does not call this handler */
2718 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
2720 if (ngx_del_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
2721 ngx_http_close_request(r, 0);
2725 return;
2727 closed:
2729 if (err) {
2730 rev->error = 1;
2733 ngx_log_error(NGX_LOG_INFO, c->log, err,
2734 "client prematurely closed connection");
2736 ngx_http_finalize_request(r, 0);
2740 static void
2741 ngx_http_set_keepalive(ngx_http_request_t *r)
2743 int tcp_nodelay;
2744 ngx_int_t i;
2745 ngx_buf_t *b, *f;
2746 ngx_event_t *rev, *wev;
2747 ngx_connection_t *c;
2748 ngx_http_connection_t *hc;
2749 ngx_http_core_srv_conf_t *cscf;
2750 ngx_http_core_loc_conf_t *clcf;
2752 c = r->connection;
2753 rev = c->read;
2755 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2757 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
2759 if (r->discard_body) {
2760 r->write_event_handler = ngx_http_request_empty_handler;
2761 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
2762 ngx_add_timer(rev, clcf->lingering_timeout);
2763 return;
2766 c->log->action = "closing request";
2768 hc = r->http_connection;
2769 b = r->header_in;
2771 if (b->pos < b->last) {
2773 /* the pipelined request */
2775 if (b != c->buffer) {
2778 * If the large header buffers were allocated while the previous
2779 * request processing then we do not use c->buffer for
2780 * the pipelined request (see ngx_http_create_request()).
2782 * Now we would move the large header buffers to the free list.
2785 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2787 if (hc->free == NULL) {
2788 hc->free = ngx_palloc(c->pool,
2789 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
2791 if (hc->free == NULL) {
2792 ngx_http_close_request(r, 0);
2793 return;
2797 for (i = 0; i < hc->nbusy - 1; i++) {
2798 f = hc->busy[i];
2799 hc->free[hc->nfree++] = f;
2800 f->pos = f->start;
2801 f->last = f->start;
2804 hc->busy[0] = b;
2805 hc->nbusy = 1;
2809 /* guard against recursive call from ngx_http_finalize_connection() */
2810 r->keepalive = 0;
2812 ngx_http_free_request(r, 0);
2814 c->data = hc;
2816 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2817 ngx_http_close_connection(c);
2818 return;
2821 wev = c->write;
2822 wev->handler = ngx_http_empty_handler;
2824 if (b->pos < b->last) {
2826 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
2828 c->log->action = "reading client pipelined request line";
2830 r = ngx_http_create_request(c);
2831 if (r == NULL) {
2832 ngx_http_close_connection(c);
2833 return;
2836 r->pipeline = 1;
2838 c->data = r;
2840 c->sent = 0;
2841 c->destroyed = 0;
2843 if (rev->timer_set) {
2844 ngx_del_timer(rev);
2847 rev->handler = ngx_http_process_request_line;
2848 ngx_post_event(rev, &ngx_posted_events);
2849 return;
2853 * To keep a memory footprint as small as possible for an idle keepalive
2854 * connection we try to free c->buffer's memory if it was allocated outside
2855 * the c->pool. The large header buffers are always allocated outside the
2856 * c->pool and are freed too.
2859 b = c->buffer;
2861 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
2864 * the special note for ngx_http_keepalive_handler() that
2865 * c->buffer's memory was freed
2868 b->pos = NULL;
2870 } else {
2871 b->pos = b->start;
2872 b->last = b->start;
2875 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",
2876 hc->free, hc->nfree);
2878 if (hc->free) {
2879 for (i = 0; i < hc->nfree; i++) {
2880 ngx_pfree(c->pool, hc->free[i]->start);
2881 hc->free[i] = NULL;
2884 hc->nfree = 0;
2887 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",
2888 hc->busy, hc->nbusy);
2890 if (hc->busy) {
2891 for (i = 0; i < hc->nbusy; i++) {
2892 ngx_pfree(c->pool, hc->busy[i]->start);
2893 hc->busy[i] = NULL;
2896 hc->nbusy = 0;
2899 #if (NGX_HTTP_SSL)
2900 if (c->ssl) {
2901 ngx_ssl_free_buffer(c);
2903 #endif
2905 rev->handler = ngx_http_keepalive_handler;
2907 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2908 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
2909 ngx_http_close_connection(c);
2910 return;
2914 c->log->action = "keepalive";
2916 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
2917 if (ngx_tcp_push(c->fd) == -1) {
2918 ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
2919 ngx_http_close_connection(c);
2920 return;
2923 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
2924 tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
2926 } else {
2927 tcp_nodelay = 1;
2930 if (tcp_nodelay
2931 && clcf->tcp_nodelay
2932 && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
2934 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
2936 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
2937 (const void *) &tcp_nodelay, sizeof(int))
2938 == -1)
2940 #if (NGX_SOLARIS)
2941 /* Solaris returns EINVAL if a socket has been shut down */
2942 c->log_error = NGX_ERROR_IGNORE_EINVAL;
2943 #endif
2945 ngx_connection_error(c, ngx_socket_errno,
2946 "setsockopt(TCP_NODELAY) failed");
2948 c->log_error = NGX_ERROR_INFO;
2949 ngx_http_close_connection(c);
2950 return;
2953 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
2956 #if 0
2957 /* if ngx_http_request_t was freed then we need some other place */
2958 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
2959 #endif
2961 c->idle = 1;
2962 ngx_reusable_connection(c, 1);
2964 ngx_add_timer(rev, clcf->keepalive_timeout);
2966 if (rev->ready) {
2967 ngx_post_event(rev, &ngx_posted_events);
2972 static void
2973 ngx_http_keepalive_handler(ngx_event_t *rev)
2975 size_t size;
2976 ssize_t n;
2977 ngx_buf_t *b;
2978 ngx_connection_t *c;
2980 c = rev->data;
2982 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
2984 if (rev->timedout || c->close) {
2985 ngx_http_close_connection(c);
2986 return;
2989 #if (NGX_HAVE_KQUEUE)
2991 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2992 if (rev->pending_eof) {
2993 c->log->handler = NULL;
2994 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
2995 "kevent() reported that client %V closed "
2996 "keepalive connection", &c->addr_text);
2997 #if (NGX_HTTP_SSL)
2998 if (c->ssl) {
2999 c->ssl->no_send_shutdown = 1;
3001 #endif
3002 ngx_http_close_connection(c);
3003 return;
3007 #endif
3009 b = c->buffer;
3010 size = b->end - b->start;
3012 if (b->pos == NULL) {
3015 * The c->buffer's memory was freed by ngx_http_set_keepalive().
3016 * However, the c->buffer->start and c->buffer->end were not changed
3017 * to keep the buffer size.
3020 b->pos = ngx_palloc(c->pool, size);
3021 if (b->pos == NULL) {
3022 ngx_http_close_connection(c);
3023 return;
3026 b->start = b->pos;
3027 b->last = b->pos;
3028 b->end = b->pos + size;
3032 * MSIE closes a keepalive connection with RST flag
3033 * so we ignore ECONNRESET here.
3036 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
3037 ngx_set_socket_errno(0);
3039 n = c->recv(c, b->last, size);
3040 c->log_error = NGX_ERROR_INFO;
3042 if (n == NGX_AGAIN) {
3043 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3044 ngx_http_close_connection(c);
3045 return;
3049 * Like ngx_http_set_keepalive() we are trying to not hold
3050 * c->buffer's memory for a keepalive connection.
3053 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
3056 * the special note that c->buffer's memory was freed
3059 b->pos = NULL;
3062 return;
3065 if (n == NGX_ERROR) {
3066 ngx_http_close_connection(c);
3067 return;
3070 c->log->handler = NULL;
3072 if (n == 0) {
3073 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
3074 "client %V closed keepalive connection", &c->addr_text);
3075 ngx_http_close_connection(c);
3076 return;
3079 b->last += n;
3081 c->log->handler = ngx_http_log_error;
3082 c->log->action = "reading client request line";
3084 c->idle = 0;
3085 ngx_reusable_connection(c, 0);
3087 c->data = ngx_http_create_request(c);
3088 if (c->data == NULL) {
3089 ngx_http_close_connection(c);
3090 return;
3093 c->sent = 0;
3094 c->destroyed = 0;
3096 ngx_del_timer(rev);
3098 rev->handler = ngx_http_process_request_line;
3099 ngx_http_process_request_line(rev);
3103 static void
3104 ngx_http_set_lingering_close(ngx_http_request_t *r)
3106 ngx_event_t *rev, *wev;
3107 ngx_connection_t *c;
3108 ngx_http_core_loc_conf_t *clcf;
3110 c = r->connection;
3112 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3114 rev = c->read;
3115 rev->handler = ngx_http_lingering_close_handler;
3117 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
3118 ngx_add_timer(rev, clcf->lingering_timeout);
3120 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3121 ngx_http_close_request(r, 0);
3122 return;
3125 wev = c->write;
3126 wev->handler = ngx_http_empty_handler;
3128 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
3129 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
3130 ngx_http_close_request(r, 0);
3131 return;
3135 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
3136 ngx_connection_error(c, ngx_socket_errno,
3137 ngx_shutdown_socket_n " failed");
3138 ngx_http_close_request(r, 0);
3139 return;
3142 if (rev->ready) {
3143 ngx_http_lingering_close_handler(rev);
3148 static void
3149 ngx_http_lingering_close_handler(ngx_event_t *rev)
3151 ssize_t n;
3152 ngx_msec_t timer;
3153 ngx_connection_t *c;
3154 ngx_http_request_t *r;
3155 ngx_http_core_loc_conf_t *clcf;
3156 u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
3158 c = rev->data;
3159 r = c->data;
3161 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3162 "http lingering close handler");
3164 if (rev->timedout) {
3165 ngx_http_close_request(r, 0);
3166 return;
3169 timer = (ngx_msec_t) (r->lingering_time - ngx_time());
3170 if (timer <= 0) {
3171 ngx_http_close_request(r, 0);
3172 return;
3175 do {
3176 n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
3178 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
3180 if (n == NGX_ERROR || n == 0) {
3181 ngx_http_close_request(r, 0);
3182 return;
3185 } while (rev->ready);
3187 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3188 ngx_http_close_request(r, 0);
3189 return;
3192 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3194 timer *= 1000;
3196 if (timer > clcf->lingering_timeout) {
3197 timer = clcf->lingering_timeout;
3200 ngx_add_timer(rev, timer);
3204 void
3205 ngx_http_empty_handler(ngx_event_t *wev)
3207 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
3209 return;
3213 void
3214 ngx_http_request_empty_handler(ngx_http_request_t *r)
3216 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3217 "http request empty handler");
3219 return;
3223 ngx_int_t
3224 ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
3226 ngx_buf_t *b;
3227 ngx_chain_t out;
3229 b = ngx_calloc_buf(r->pool);
3230 if (b == NULL) {
3231 return NGX_ERROR;
3234 if (flags & NGX_HTTP_LAST) {
3236 if (r == r->main && !r->post_action) {
3237 b->last_buf = 1;
3239 } else {
3240 b->sync = 1;
3241 b->last_in_chain = 1;
3245 if (flags & NGX_HTTP_FLUSH) {
3246 b->flush = 1;
3249 out.buf = b;
3250 out.next = NULL;
3252 return ngx_http_output_filter(r, &out);
3256 static ngx_int_t
3257 ngx_http_post_action(ngx_http_request_t *r)
3259 ngx_http_core_loc_conf_t *clcf;
3261 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3263 if (clcf->post_action.data == NULL) {
3264 return NGX_DECLINED;
3267 if (r->post_action && r->uri_changes == 0) {
3268 return NGX_DECLINED;
3271 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3272 "post action: \"%V\"", &clcf->post_action);
3274 r->main->count--;
3276 r->http_version = NGX_HTTP_VERSION_9;
3277 r->header_only = 1;
3278 r->post_action = 1;
3280 r->read_event_handler = ngx_http_block_reading;
3282 if (clcf->post_action.data[0] == '/') {
3283 ngx_http_internal_redirect(r, &clcf->post_action, NULL);
3285 } else {
3286 ngx_http_named_location(r, &clcf->post_action);
3289 return NGX_OK;
3293 static void
3294 ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc)
3296 ngx_connection_t *c;
3298 r = r->main;
3299 c = r->connection;
3301 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
3302 "http request count:%d blk:%d", r->count, r->blocked);
3304 if (r->count == 0) {
3305 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "http request count is zero");
3308 r->count--;
3310 if (r->count || r->blocked) {
3311 return;
3314 #if (NGX_HTTP_SPDY)
3315 if (r->spdy_stream) {
3316 ngx_http_spdy_close_stream(r->spdy_stream, rc);
3317 return;
3319 #endif
3321 ngx_http_free_request(r, rc);
3322 ngx_http_close_connection(c);
3326 void
3327 ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc)
3329 ngx_log_t *log;
3330 ngx_pool_t *pool;
3331 struct linger linger;
3332 ngx_http_cleanup_t *cln;
3333 ngx_http_log_ctx_t *ctx;
3334 ngx_http_core_loc_conf_t *clcf;
3336 log = r->connection->log;
3338 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
3340 if (r->pool == NULL) {
3341 ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
3342 return;
3345 for (cln = r->cleanup; cln; cln = cln->next) {
3346 if (cln->handler) {
3347 cln->handler(cln->data);
3351 #if (NGX_STAT_STUB)
3353 if (r->stat_reading) {
3354 (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
3357 if (r->stat_writing) {
3358 (void) ngx_atomic_fetch_add(ngx_stat_writing, -1);
3361 #endif
3363 if (rc > 0 && (r->headers_out.status == 0 || r->connection->sent == 0)) {
3364 r->headers_out.status = rc;
3367 log->action = "logging request";
3369 ngx_http_log_request(r);
3371 log->action = "closing request";
3373 if (r->connection->timedout) {
3374 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3376 if (clcf->reset_timedout_connection) {
3377 linger.l_onoff = 1;
3378 linger.l_linger = 0;
3380 if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
3381 (const void *) &linger, sizeof(struct linger)) == -1)
3383 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
3384 "setsockopt(SO_LINGER) failed");
3389 /* the various request strings were allocated from r->pool */
3390 ctx = log->data;
3391 ctx->request = NULL;
3393 r->request_line.len = 0;
3395 r->connection->destroyed = 1;
3398 * Setting r->pool to NULL will increase probability to catch double close
3399 * of request since the request object is allocated from its own pool.
3402 pool = r->pool;
3403 r->pool = NULL;
3405 ngx_destroy_pool(pool);
3409 static void
3410 ngx_http_log_request(ngx_http_request_t *r)
3412 ngx_uint_t i, n;
3413 ngx_http_handler_pt *log_handler;
3414 ngx_http_core_main_conf_t *cmcf;
3416 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
3418 log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
3419 n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
3421 for (i = 0; i < n; i++) {
3422 log_handler[i](r);
3427 void
3428 ngx_http_close_connection(ngx_connection_t *c)
3430 ngx_pool_t *pool;
3432 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
3433 "close http connection: %d", c->fd);
3435 #if (NGX_HTTP_SSL)
3437 if (c->ssl) {
3438 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
3439 c->ssl->handler = ngx_http_close_connection;
3440 return;
3444 #endif
3446 #if (NGX_STAT_STUB)
3447 (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
3448 #endif
3450 c->destroyed = 1;
3452 pool = c->pool;
3454 ngx_close_connection(c);
3456 ngx_destroy_pool(pool);
3460 static u_char *
3461 ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
3463 u_char *p;
3464 ngx_http_request_t *r;
3465 ngx_http_log_ctx_t *ctx;
3467 if (log->action) {
3468 p = ngx_snprintf(buf, len, " while %s", log->action);
3469 len -= p - buf;
3470 buf = p;
3473 ctx = log->data;
3475 p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text);
3476 len -= p - buf;
3478 r = ctx->request;
3480 if (r) {
3481 return r->log_handler(r, ctx->current_request, p, len);
3483 } else {
3484 p = ngx_snprintf(p, len, ", server: %V",
3485 &ctx->connection->listening->addr_text);
3488 return p;
3492 static u_char *
3493 ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
3494 u_char *buf, size_t len)
3496 char *uri_separator;
3497 u_char *p;
3498 ngx_http_upstream_t *u;
3499 ngx_http_core_srv_conf_t *cscf;
3501 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
3503 p = ngx_snprintf(buf, len, ", server: %V", &cscf->server_name);
3504 len -= p - buf;
3505 buf = p;
3507 if (r->request_line.data == NULL && r->request_start) {
3508 for (p = r->request_start; p < r->header_in->last; p++) {
3509 if (*p == CR || *p == LF) {
3510 break;
3514 r->request_line.len = p - r->request_start;
3515 r->request_line.data = r->request_start;
3518 if (r->request_line.len) {
3519 p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
3520 len -= p - buf;
3521 buf = p;
3524 if (r != sr) {
3525 p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
3526 len -= p - buf;
3527 buf = p;
3530 u = sr->upstream;
3532 if (u && u->peer.name) {
3534 uri_separator = "";
3536 #if (NGX_HAVE_UNIX_DOMAIN)
3537 if (u->peer.sockaddr && u->peer.sockaddr->sa_family == AF_UNIX) {
3538 uri_separator = ":";
3540 #endif
3542 p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
3543 &u->schema, u->peer.name,
3544 uri_separator, &u->uri);
3545 len -= p - buf;
3546 buf = p;
3549 if (r->headers_in.host) {
3550 p = ngx_snprintf(buf, len, ", host: \"%V\"",
3551 &r->headers_in.host->value);
3552 len -= p - buf;
3553 buf = p;
3556 if (r->headers_in.referer) {
3557 p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
3558 &r->headers_in.referer->value);
3559 buf = p;
3562 return buf;