3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.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
,
35 static ngx_int_t
ngx_http_set_virtual_server(ngx_http_request_t
*r
,
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
);
62 static void ngx_http_ssl_handshake(ngx_event_t
*rev
);
63 static void ngx_http_ssl_handshake_handler(ngx_connection_t
*c
);
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
},
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
},
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
},
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
},
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
},
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
},
187 { ngx_string("Cookie"), offsetof(ngx_http_headers_in_t
, cookies
),
188 ngx_http_process_multi_header_lines
},
190 { ngx_null_string
, 0, NULL
}
195 ngx_http_init_connection(ngx_connection_t
*c
)
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
;
205 struct sockaddr_in6
*sin6
;
206 ngx_http_in6_addr_t
*addr6
;
209 hc
= ngx_pcalloc(c
->pool
, sizeof(ngx_http_connection_t
));
211 ngx_http_close_connection(c
);
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
);
234 switch (c
->local_sockaddr
->sa_family
) {
238 sin6
= (struct sockaddr_in6
*) c
->local_sockaddr
;
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) {
250 hc
->addr_conf
= &addr6
[i
].conf
;
255 default: /* AF_INET */
256 sin
= (struct sockaddr_in
*) c
->local_sockaddr
;
260 /* the last address is "*" */
262 for (i
= 0; i
< port
->naddrs
- 1; i
++) {
263 if (addr
[i
].addr
== sin
->sin_addr
.s_addr
) {
268 hc
->addr_conf
= &addr
[i
].conf
;
275 switch (c
->local_sockaddr
->sa_family
) {
280 hc
->addr_conf
= &addr6
[0].conf
;
284 default: /* AF_INET */
286 hc
->addr_conf
= &addr
[0].conf
;
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
));
296 ngx_http_close_connection(c
);
302 ctx
->current_request
= NULL
;
304 c
->log
->connection
= c
->number
;
305 c
->log
->handler
= ngx_http_log_error
;
307 c
->log
->action
= "waiting for request";
309 c
->log_error
= NGX_ERROR_INFO
;
312 rev
->handler
= ngx_http_wait_request_handler
;
313 c
->write
->handler
= ngx_http_empty_handler
;
316 if (hc
->addr_conf
->spdy
) {
317 rev
->handler
= ngx_http_spdy_init
;
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
);
341 rev
->handler
= ngx_http_ssl_handshake
;
347 /* the deferred accept(), rtsig, aio, iocp */
349 if (ngx_use_accept_mutex
) {
350 ngx_post_event(rev
, &ngx_posted_events
);
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
);
369 ngx_http_wait_request_handler(ngx_event_t
*rev
)
375 ngx_http_connection_t
*hc
;
376 ngx_http_core_srv_conf_t
*cscf
;
380 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "http wait request handler");
383 ngx_log_error(NGX_LOG_INFO
, c
->log
, NGX_ETIMEDOUT
, "client timed out");
384 ngx_http_close_connection(c
);
389 ngx_http_close_connection(c
);
394 cscf
= ngx_http_get_module_srv_conf(hc
->conf_ctx
, ngx_http_core_module
);
396 size
= cscf
->client_header_buffer_size
;
401 b
= ngx_create_temp_buf(c
->pool
, size
);
403 ngx_http_close_connection(c
);
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
);
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
433 ngx_log_error(NGX_LOG_INFO
, c
->log
, NGX_ETIMEDOUT
,
434 "client timed out in deferred accept");
435 ngx_http_close_connection(c
);
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
);
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
) {
461 if (n
== NGX_ERROR
) {
462 ngx_http_close_connection(c
);
467 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
468 "client closed connection");
469 ngx_http_close_connection(c
);
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
);
485 rev
->handler
= ngx_http_process_request_line
;
486 ngx_http_process_request_line(rev
);
491 ngx_http_create_request(ngx_connection_t
*c
)
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
;
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
);
513 r
= ngx_pcalloc(pool
, sizeof(ngx_http_request_t
));
515 ngx_destroy_pool(pool
);
521 r
->http_connection
= hc
;
522 r
->signature
= NGX_HTTP_MODULE
;
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
))
541 ngx_destroy_pool(r
->pool
);
545 r
->ctx
= ngx_pcalloc(r
->pool
, sizeof(void *) * ngx_http_max_module
);
546 if (r
->ctx
== NULL
) {
547 ngx_destroy_pool(r
->pool
);
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
);
562 r
->main_filter_need_in_memory
= 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
;
587 ctx
->current_request
= r
;
588 r
->log_handler
= ngx_http_log_error_handler
;
591 (void) ngx_atomic_fetch_add(ngx_stat_reading
, 1);
593 (void) ngx_atomic_fetch_add(ngx_stat_requests
, 1);
603 ngx_http_ssl_handshake(ngx_event_t
*rev
)
610 ngx_http_connection_t
*hc
;
611 ngx_http_ssl_srv_conf_t
*sscf
;
615 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
616 "http check ssl handshake");
619 ngx_log_error(NGX_LOG_INFO
, c
->log
, NGX_ETIMEDOUT
, "client timed out");
620 ngx_http_close_connection(c
);
625 ngx_http_close_connection(c
);
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
);
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
);
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
);
659 ngx_connection_error(c
, err
, "recv() failed");
660 ngx_http_close_connection(c
);
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]);
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
)
677 ngx_http_close_connection(c
);
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
;
695 ngx_http_ssl_handshake_handler(c
);
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
);
710 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0, "client closed connection");
711 ngx_http_close_connection(c
);
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)
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
);
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
);
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
)
770 const char *servername
;
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
);
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
;
802 if (ngx_http_find_virtual_server(c
, hc
->addr_conf
->virtual_names
, &host
,
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
);
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
));
843 SSL_set_options(ssl_conn
, SSL_CTX_get_options(sscf
->ssl
.ctx
));
846 return SSL_TLSEXT_ERR_OK
;
855 ngx_http_process_request_line(ngx_event_t
*rev
)
861 ngx_http_request_t
*r
;
866 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
867 "http process request line");
870 ngx_log_error(NGX_LOG_INFO
, c
->log
, NGX_ETIMEDOUT
, "client timed out");
872 ngx_http_close_request(r
, NGX_HTTP_REQUEST_TIME_OUT
);
880 if (rc
== NGX_AGAIN
) {
881 n
= ngx_http_read_request_header(r
);
883 if (n
== NGX_AGAIN
|| n
== NGX_ERROR
) {
888 rc
= ngx_http_parse_request_line(r
, r
->header_in
);
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
) {
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
);
926 if (rc
== NGX_ERROR
) {
927 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
931 if (ngx_http_set_virtual_server(r
, &host
) == NGX_ERROR
) {
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
)
947 ngx_http_process_request(r
);
952 if (ngx_list_init(&r
->headers_in
.headers
, r
->pool
, 20,
953 sizeof(ngx_table_elt_t
))
956 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
960 c
->log
->action
= "reading client request headers";
962 rev
->handler
= ngx_http_process_request_headers
;
963 ngx_http_process_request_headers(rev
);
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
);
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
);
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
);
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
;
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
);
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
);
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;
1041 if (r
->args_start
) {
1042 r
->exten
.len
= r
->args_start
- 1 - r
->uri_ext
;
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
;
1060 last
= r
->uri
.data
+ r
->uri
.len
;
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
);
1080 p
= r
->uri
.data
+ r
->uri
.len
- 1;
1082 while (p
> r
->uri
.data
) {
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
);
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
);
1119 ngx_http_process_request_headers(ngx_event_t
*rev
)
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
;
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");
1141 ngx_http_close_request(r
, NGX_HTTP_REQUEST_TIME_OUT
);
1145 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
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
);
1162 if (rv
== NGX_DECLINED
) {
1163 p
= r
->header_name_start
;
1165 r
->lingering_close
= 1;
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
);
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
);
1192 n
= ngx_http_read_request_header(r
);
1194 if (n
== NGX_AGAIN
|| n
== NGX_ERROR
) {
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
);
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
);
1220 /* a header line has been parsed successfully */
1222 h
= ngx_list_push(&r
->headers_in
.headers
);
1224 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
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
);
1244 if (h
->key
.len
== r
->lowcase_index
) {
1245 ngx_memcpy(h
->lowcase_key
, r
->lowcase_header
, h
->key
.len
);
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
) {
1258 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1259 "http header: \"%V: %V\"",
1260 &h
->key
, &h
->value
);
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
);
1282 ngx_http_process_request(r
);
1287 if (rc
== NGX_AGAIN
) {
1289 /* a header line parsing is still not complete */
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
);
1307 ngx_http_read_request_header(ngx_http_request_t
*r
)
1311 ngx_connection_t
*c
;
1312 ngx_http_core_srv_conf_t
*cscf
;
1317 n
= r
->header_in
->last
- r
->header_in
->pos
;
1324 n
= c
->recv(c
, r
->header_in
->last
,
1325 r
->header_in
->end
- r
->header_in
->last
);
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
);
1345 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
1346 "client prematurely closed connection");
1349 if (n
== 0 || n
== NGX_ERROR
) {
1351 c
->log
->action
= "reading client request headers";
1353 ngx_http_finalize_request(r
, NGX_HTTP_BAD_REQUEST
);
1357 r
->header_in
->last
+= n
;
1364 ngx_http_alloc_large_header_buffer(ngx_http_request_t
*r
,
1365 ngx_uint_t request_line
)
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
;
1385 old
= request_line
? r
->request_start
: r
->header_name_start
;
1387 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
1390 && (size_t) (r
->header_in
->pos
- old
)
1391 >= cscf
->large_client_header_buffers
.size
)
1393 return NGX_DECLINED
;
1396 hc
= r
->http_connection
;
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
) {
1415 b
= ngx_create_temp_buf(r
->connection
->pool
,
1416 cscf
->large_client_header_buffers
.size
);
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
);
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
1443 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1444 "http large header copy: %d", r
->header_in
->pos
- old
);
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
);
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
);
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
);
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
);
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
);
1508 ngx_http_process_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1511 ngx_table_elt_t
**ph
;
1513 ph
= (ngx_table_elt_t
**) ((char *) &r
->headers_in
+ offset
);
1524 ngx_http_process_unique_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1527 ngx_table_elt_t
**ph
;
1529 ph
= (ngx_table_elt_t
**) ((char *) &r
->headers_in
+ offset
);
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
);
1548 ngx_http_process_host(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1554 if (r
->headers_in
.host
== NULL
) {
1555 r
->headers_in
.host
= h
;
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
);
1569 if (rc
== NGX_ERROR
) {
1570 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
1574 if (r
->headers_in
.server
.len
) {
1578 if (ngx_http_set_virtual_server(r
, &host
) == NGX_ERROR
) {
1582 r
->headers_in
.server
= host
;
1589 ngx_http_process_connection(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
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
;
1604 ngx_http_process_user_agent(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1607 u_char
*user_agent
, *msie
;
1609 if (r
->headers_in
.user_agent
) {
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] == '.') {
1630 r
->headers_in
.msie6
= 1;
1633 if (ngx_strstrn(msie
+ 8, "SV1", 3 - 1) == NULL
) {
1634 r
->headers_in
.msie6
= 1;
1641 /* MSIE ignores the SSL "close notify" alert */
1643 c
->ssl
->no_send_shutdown
= 1;
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;
1677 ngx_http_process_multi_header_lines(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
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
*))
1689 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
1694 ph
= ngx_array_push(headers
);
1696 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
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
)
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
);
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
);
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
);
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
);
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
);
1776 ngx_http_process_request(ngx_http_request_t
*r
)
1778 ngx_connection_t
*c
;
1784 if (r
->http_connection
->ssl
) {
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
);
1796 sscf
= ngx_http_get_module_srv_conf(r
, ngx_http_ssl_module
);
1799 rc
= SSL_get_verify_result(c
->ssl
->connection
);
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
);
1815 if (sscf
->verify
== 1) {
1816 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
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
);
1836 if (c
->read
->timer_set
) {
1837 ngx_del_timer(c
->read
);
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;
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
);
1858 ngx_http_validate_host(ngx_str_t
*host
, ngx_pool_t
*pool
, ngx_uint_t alloc
)
1861 size_t i
, dot_pos
, host_len
;
1869 dot_pos
= host
->len
;
1870 host_len
= host
->len
;
1876 for (i
= 0; i
< host
->len
; i
++) {
1882 if (dot_pos
== i
- 1) {
1883 return NGX_DECLINED
;
1889 if (state
== sw_usual
) {
1902 if (state
== sw_literal
) {
1909 return NGX_DECLINED
;
1913 if (ngx_path_separator(ch
)) {
1914 return NGX_DECLINED
;
1917 if (ch
>= 'A' && ch
<= 'Z') {
1925 if (dot_pos
== host_len
- 1) {
1929 if (host_len
== 0) {
1930 return NGX_DECLINED
;
1934 host
->data
= ngx_pnalloc(pool
, host_len
);
1935 if (host
->data
== NULL
) {
1939 ngx_strlow(host
->data
, h
, host_len
);
1942 host
->len
= host_len
;
1949 ngx_http_set_virtual_server(ngx_http_request_t
*r
, ngx_str_t
*host
)
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)
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
);
1980 rc
= ngx_http_find_virtual_server(r
->connection
,
1981 hc
->addr_conf
->virtual_names
,
1984 if (rc
== NGX_ERROR
) {
1985 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_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
;
1999 sscf
= ngx_http_get_module_srv_conf(cscf
->ctx
, ngx_http_ssl_module
);
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
);
2012 if (rc
== NGX_DECLINED
) {
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
);
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
);
2049 if (host
->len
&& virtual_names
->nregex
) {
2052 ngx_http_server_name_t
*sn
;
2054 sn
= virtual_names
->regex
;
2056 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
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
) {
2071 hc
->ssl_servername_regex
= sn
[i
].regex
;
2073 *cscfp
= sn
[i
].server
;
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
);
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
) {
2099 *cscfp
= sn
[i
].server
;
2107 #endif /* NGX_PCRE */
2109 return NGX_DECLINED
;
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
;
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
);
2130 r
->write_event_handler(r
);
2133 r
->read_event_handler(r
);
2136 ngx_http_run_posted_requests(c
);
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
;
2154 pr
= r
->main
->posted_requests
;
2160 r
->main
->posted_requests
= pr
->next
;
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
);
2176 ngx_http_post_request(ngx_http_request_t
*r
, ngx_http_posted_request_t
*pr
)
2178 ngx_http_posted_request_t
**p
;
2181 pr
= ngx_palloc(r
->pool
, sizeof(ngx_http_posted_request_t
));
2190 for (p
= &r
->main
->posted_requests
; *p
; p
= &(*p
)->next
) { /* 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
;
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
);
2216 if (rc
== NGX_OK
&& r
->filter_finalize
) {
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
);
2227 if (r
!= r
->main
&& r
->post_subrequest
) {
2228 rc
= r
->post_subrequest
->handler(r
, r
->post_subrequest
->data
, rc
);
2232 || rc
== NGX_HTTP_REQUEST_TIME_OUT
2233 || rc
== NGX_HTTP_CLIENT_CLOSED_REQUEST
2236 if (ngx_http_post_action(r
) == NGX_OK
) {
2240 if (r
->main
->blocked
) {
2241 r
->write_event_handler
= ngx_http_request_finalizer
;
2244 ngx_http_terminate_request(r
, rc
);
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
);
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
));
2276 if (r
->buffered
|| r
->postponed
) {
2278 if (ngx_http_set_write_handler(r
) != NGX_OK
) {
2279 ngx_http_terminate_request(r
, 0);
2290 r
->main
->subrequests
++;
2294 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
2296 if (clcf
->log_subrequest
) {
2297 ngx_http_log_request(r
);
2303 ngx_log_error(NGX_LOG_ALERT
, c
->log
, 0,
2304 "subrequest: \"%V?%V\" logged again",
2310 if (pr
->postponed
&& pr
->postponed
->request
== r
) {
2311 pr
->postponed
= pr
->postponed
->next
;
2318 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2319 "http finalize non-active request: \"%V?%V\"",
2322 r
->write_event_handler
= ngx_http_request_finalizer
;
2329 if (ngx_http_post_request(pr
, NULL
) != NGX_OK
) {
2331 ngx_http_terminate_request(r
, 0);
2335 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2336 "http wake parent request: \"%V?%V\"",
2337 &pr
->uri
, &pr
->args
);
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);
2352 ngx_log_error(NGX_LOG_ALERT
, c
->log
, 0,
2353 "http finalize non-active request: \"%V?%V\"",
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
) {
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
);
2379 ngx_http_close_request(r
, 0);
2383 ngx_http_finalize_connection(r
);
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
;
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
;
2408 cln
->handler(cln
->data
);
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
) {
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
);
2431 ngx_http_close_request(mr
, rc
);
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
);
2443 ngx_http_close_request(r
, 0);
2448 ngx_http_finalize_connection(ngx_http_request_t
*r
)
2450 ngx_http_core_loc_conf_t
*clcf
;
2453 if (r
->spdy_stream
) {
2454 ngx_http_close_request(r
, 0);
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);
2480 && clcf
->keepalive_timeout
> 0)
2482 ngx_http_set_keepalive(r
);
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
);
2496 ngx_http_close_request(r
, 0);
2501 ngx_http_set_write_handler(ngx_http_request_t
*r
)
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
;
2514 if (r
->spdy_stream
) {
2519 wev
= r
->connection
->write
;
2521 if (wev
->ready
&& wev
->delayed
) {
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);
2540 ngx_http_writer(ngx_http_request_t
*r
)
2544 ngx_connection_t
*c
;
2545 ngx_http_core_loc_conf_t
*clcf
;
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");
2561 ngx_http_finalize_request(r
, NGX_HTTP_REQUEST_TIME_OUT
);
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);
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);
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
);
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);
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
);
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);
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);
2653 ngx_http_test_reading(ngx_http_request_t
*r
)
2659 ngx_connection_t
*c
;
2664 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "http test reading");
2668 if (r
->spdy_stream
) {
2679 #if (NGX_HAVE_KQUEUE)
2681 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
2683 if (!rev
->pending_eof
) {
2689 err
= rev
->kq_errno
;
2696 n
= recv(c
->fd
, buf
, 1, MSG_PEEK
);
2705 } else if (n
== -1) {
2706 err
= ngx_socket_errno
;
2708 if (err
!= NGX_EAGAIN
) {
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);
2733 ngx_log_error(NGX_LOG_INFO
, c
->log
, err
,
2734 "client prematurely closed connection");
2736 ngx_http_finalize_request(r
, 0);
2741 ngx_http_set_keepalive(ngx_http_request_t
*r
)
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
;
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
);
2766 c
->log
->action
= "closing request";
2768 hc
= r
->http_connection
;
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);
2797 for (i
= 0; i
< hc
->nbusy
- 1; i
++) {
2799 hc
->free
[hc
->nfree
++] = f
;
2809 /* guard against recursive call from ngx_http_finalize_connection() */
2812 ngx_http_free_request(r
, 0);
2816 if (ngx_handle_read_event(rev
, 0) != NGX_OK
) {
2817 ngx_http_close_connection(c
);
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
);
2832 ngx_http_close_connection(c
);
2843 if (rev
->timer_set
) {
2847 rev
->handler
= ngx_http_process_request_line
;
2848 ngx_post_event(rev
, &ngx_posted_events
);
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.
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
2875 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "hc free: %p %d",
2876 hc
->free
, hc
->nfree
);
2879 for (i
= 0; i
< hc
->nfree
; i
++) {
2880 ngx_pfree(c
->pool
, hc
->free
[i
]->start
);
2887 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "hc busy: %p %d",
2888 hc
->busy
, hc
->nbusy
);
2891 for (i
= 0; i
< hc
->nbusy
; i
++) {
2892 ngx_pfree(c
->pool
, hc
->busy
[i
]->start
);
2901 ngx_ssl_free_buffer(c
);
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
);
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
);
2923 c
->tcp_nopush
= NGX_TCP_NOPUSH_UNSET
;
2924 tcp_nodelay
= ngx_tcp_nodelay_and_tcp_nopush
? 1 : 0;
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))
2941 /* Solaris returns EINVAL if a socket has been shut down */
2942 c
->log_error
= NGX_ERROR_IGNORE_EINVAL
;
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
);
2953 c
->tcp_nodelay
= NGX_TCP_NODELAY_SET
;
2957 /* if ngx_http_request_t was freed then we need some other place */
2958 r
->http_state
= NGX_HTTP_KEEPALIVE_STATE
;
2962 ngx_reusable_connection(c
, 1);
2964 ngx_add_timer(rev
, clcf
->keepalive_timeout
);
2967 ngx_post_event(rev
, &ngx_posted_events
);
2973 ngx_http_keepalive_handler(ngx_event_t
*rev
)
2978 ngx_connection_t
*c
;
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
);
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
);
2999 c
->ssl
->no_send_shutdown
= 1;
3002 ngx_http_close_connection(c
);
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
);
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
);
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
3065 if (n
== NGX_ERROR
) {
3066 ngx_http_close_connection(c
);
3070 c
->log
->handler
= NULL
;
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
);
3081 c
->log
->handler
= ngx_http_log_error
;
3082 c
->log
->action
= "reading client request line";
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
);
3098 rev
->handler
= ngx_http_process_request_line
;
3099 ngx_http_process_request_line(rev
);
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
;
3112 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
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);
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);
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);
3143 ngx_http_lingering_close_handler(rev
);
3149 ngx_http_lingering_close_handler(ngx_event_t
*rev
)
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
];
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);
3169 timer
= (ngx_msec_t
) (r
->lingering_time
- ngx_time());
3171 ngx_http_close_request(r
, 0);
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);
3185 } while (rev
->ready
);
3187 if (ngx_handle_read_event(rev
, 0) != NGX_OK
) {
3188 ngx_http_close_request(r
, 0);
3192 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
3196 if (timer
> clcf
->lingering_timeout
) {
3197 timer
= clcf
->lingering_timeout
;
3200 ngx_add_timer(rev
, timer
);
3205 ngx_http_empty_handler(ngx_event_t
*wev
)
3207 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, wev
->log
, 0, "http empty handler");
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");
3224 ngx_http_send_special(ngx_http_request_t
*r
, ngx_uint_t flags
)
3229 b
= ngx_calloc_buf(r
->pool
);
3234 if (flags
& NGX_HTTP_LAST
) {
3236 if (r
== r
->main
&& !r
->post_action
) {
3241 b
->last_in_chain
= 1;
3245 if (flags
& NGX_HTTP_FLUSH
) {
3252 return ngx_http_output_filter(r
, &out
);
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
);
3276 r
->http_version
= NGX_HTTP_VERSION_9
;
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
);
3286 ngx_http_named_location(r
, &clcf
->post_action
);
3294 ngx_http_close_request(ngx_http_request_t
*r
, ngx_int_t rc
)
3296 ngx_connection_t
*c
;
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");
3310 if (r
->count
|| r
->blocked
) {
3315 if (r
->spdy_stream
) {
3316 ngx_http_spdy_close_stream(r
->spdy_stream
, rc
);
3321 ngx_http_free_request(r
, rc
);
3322 ngx_http_close_connection(c
);
3327 ngx_http_free_request(ngx_http_request_t
*r
, ngx_int_t rc
)
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");
3345 for (cln
= r
->cleanup
; cln
; cln
= cln
->next
) {
3347 cln
->handler(cln
->data
);
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);
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
) {
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 */
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.
3405 ngx_destroy_pool(pool
);
3410 ngx_http_log_request(ngx_http_request_t
*r
)
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
++) {
3428 ngx_http_close_connection(ngx_connection_t
*c
)
3432 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
3433 "close http connection: %d", c
->fd
);
3438 if (ngx_ssl_shutdown(c
) == NGX_AGAIN
) {
3439 c
->ssl
->handler
= ngx_http_close_connection
;
3447 (void) ngx_atomic_fetch_add(ngx_stat_active
, -1);
3454 ngx_close_connection(c
);
3456 ngx_destroy_pool(pool
);
3461 ngx_http_log_error(ngx_log_t
*log
, u_char
*buf
, size_t len
)
3464 ngx_http_request_t
*r
;
3465 ngx_http_log_ctx_t
*ctx
;
3468 p
= ngx_snprintf(buf
, len
, " while %s", log
->action
);
3475 p
= ngx_snprintf(buf
, len
, ", client: %V", &ctx
->connection
->addr_text
);
3481 return r
->log_handler(r
, ctx
->current_request
, p
, len
);
3484 p
= ngx_snprintf(p
, len
, ", server: %V",
3485 &ctx
->connection
->listening
->addr_text
);
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
;
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
);
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
) {
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
);
3525 p
= ngx_snprintf(buf
, len
, ", subrequest: \"%V\"", &sr
->uri
);
3532 if (u
&& u
->peer
.name
) {
3536 #if (NGX_HAVE_UNIX_DOMAIN)
3537 if (u
->peer
.sockaddr
&& u
->peer
.sockaddr
->sa_family
== AF_UNIX
) {
3538 uri_separator
= ":";
3542 p
= ngx_snprintf(buf
, len
, ", upstream: \"%V%V%s%V\"",
3543 &u
->schema
, u
->peer
.name
,
3544 uri_separator
, &u
->uri
);
3549 if (r
->headers_in
.host
) {
3550 p
= ngx_snprintf(buf
, len
, ", host: \"%V\"",
3551 &r
->headers_in
.host
->value
);
3556 if (r
->headers_in
.referer
) {
3557 p
= ngx_snprintf(buf
, len
, ", referrer: \"%V\"",
3558 &r
->headers_in
.referer
->value
);