3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
13 static void ngx_http_init_request(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_host(ngx_http_request_t
*r
,
25 ngx_table_elt_t
*h
, ngx_uint_t offset
);
26 static ngx_int_t
ngx_http_process_connection(ngx_http_request_t
*r
,
27 ngx_table_elt_t
*h
, ngx_uint_t offset
);
28 static ngx_int_t
ngx_http_process_user_agent(ngx_http_request_t
*r
,
29 ngx_table_elt_t
*h
, ngx_uint_t offset
);
30 static ngx_int_t
ngx_http_process_cookie(ngx_http_request_t
*r
,
31 ngx_table_elt_t
*h
, ngx_uint_t offset
);
33 static ngx_int_t
ngx_http_process_request_header(ngx_http_request_t
*r
);
34 static void ngx_http_process_request(ngx_http_request_t
*r
);
35 static ssize_t
ngx_http_validate_host(u_char
*host
, size_t len
);
36 static ngx_int_t
ngx_http_find_virtual_server(ngx_http_request_t
*r
,
37 u_char
*host
, size_t len
);
39 static void ngx_http_request_handler(ngx_event_t
*ev
);
40 static ngx_int_t
ngx_http_set_write_handler(ngx_http_request_t
*r
);
41 static void ngx_http_writer(ngx_http_request_t
*r
);
43 static void ngx_http_test_reading(ngx_http_request_t
*r
);
44 static void ngx_http_set_keepalive(ngx_http_request_t
*r
);
45 static void ngx_http_keepalive_handler(ngx_event_t
*ev
);
46 static void ngx_http_set_lingering_close(ngx_http_request_t
*r
);
47 static void ngx_http_lingering_close_handler(ngx_event_t
*ev
);
48 static ngx_int_t
ngx_http_post_action(ngx_http_request_t
*r
);
49 static void ngx_http_close_request(ngx_http_request_t
*r
, ngx_int_t error
);
50 static void ngx_http_request_done(ngx_http_request_t
*r
, ngx_int_t error
);
51 static void ngx_http_close_connection(ngx_connection_t
*c
);
53 static u_char
*ngx_http_log_error(ngx_log_t
*log
, u_char
*buf
, size_t len
);
54 static u_char
*ngx_http_log_error_handler(ngx_http_request_t
*r
,
55 ngx_http_request_t
*sr
, u_char
*buf
, size_t len
);
58 static void ngx_http_ssl_handshake(ngx_event_t
*rev
);
59 static void ngx_http_ssl_handshake_handler(ngx_connection_t
*c
);
63 static char *ngx_http_client_errors
[] = {
65 /* NGX_HTTP_PARSE_INVALID_METHOD */
66 "client sent invalid method",
68 /* NGX_HTTP_PARSE_INVALID_REQUEST */
69 "client sent invalid request",
71 /* NGX_HTTP_PARSE_INVALID_09_METHOD */
72 "client sent invalid method in HTTP/0.9 request"
76 ngx_http_header_t ngx_http_headers_in
[] = {
77 { ngx_string("Host"), 0, ngx_http_process_host
},
79 { ngx_string("Connection"), 0, ngx_http_process_connection
},
81 { ngx_string("If-Modified-Since"),
82 offsetof(ngx_http_headers_in_t
, if_modified_since
),
83 ngx_http_process_unique_header_line
},
85 { ngx_string("User-Agent"), 0, ngx_http_process_user_agent
},
87 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t
, referer
),
88 ngx_http_process_header_line
},
90 { ngx_string("Content-Length"),
91 offsetof(ngx_http_headers_in_t
, content_length
),
92 ngx_http_process_unique_header_line
},
94 { ngx_string("Content-Type"),
95 offsetof(ngx_http_headers_in_t
, content_type
),
96 ngx_http_process_header_line
},
98 { ngx_string("Range"), offsetof(ngx_http_headers_in_t
, range
),
99 ngx_http_process_header_line
},
101 { ngx_string("If-Range"),
102 offsetof(ngx_http_headers_in_t
, if_range
),
103 ngx_http_process_unique_header_line
},
105 { ngx_string("Transfer-Encoding"),
106 offsetof(ngx_http_headers_in_t
, transfer_encoding
),
107 ngx_http_process_header_line
},
109 { ngx_string("Expect"),
110 offsetof(ngx_http_headers_in_t
, expect
),
111 ngx_http_process_unique_header_line
},
114 { ngx_string("Accept-Encoding"),
115 offsetof(ngx_http_headers_in_t
, accept_encoding
),
116 ngx_http_process_header_line
},
118 { ngx_string("Via"), offsetof(ngx_http_headers_in_t
, via
),
119 ngx_http_process_header_line
},
122 { ngx_string("Authorization"),
123 offsetof(ngx_http_headers_in_t
, authorization
),
124 ngx_http_process_unique_header_line
},
126 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t
, keep_alive
),
127 ngx_http_process_header_line
},
129 #if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)
130 { ngx_string("X-Forwarded-For"),
131 offsetof(ngx_http_headers_in_t
, x_forwarded_for
),
132 ngx_http_process_header_line
},
135 #if (NGX_HTTP_REALIP)
136 { ngx_string("X-Real-IP"),
137 offsetof(ngx_http_headers_in_t
, x_real_ip
),
138 ngx_http_process_header_line
},
141 #if (NGX_HTTP_HEADERS)
142 { ngx_string("Accept"), offsetof(ngx_http_headers_in_t
, accept
),
143 ngx_http_process_header_line
},
145 { ngx_string("Accept-Language"),
146 offsetof(ngx_http_headers_in_t
, accept_language
),
147 ngx_http_process_header_line
},
151 { ngx_string("Depth"), offsetof(ngx_http_headers_in_t
, depth
),
152 ngx_http_process_header_line
},
154 { ngx_string("Destination"), offsetof(ngx_http_headers_in_t
, destination
),
155 ngx_http_process_header_line
},
157 { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t
, overwrite
),
158 ngx_http_process_header_line
},
160 { ngx_string("Date"), offsetof(ngx_http_headers_in_t
, date
),
161 ngx_http_process_header_line
},
164 { ngx_string("Cookie"), 0, ngx_http_process_cookie
},
166 { ngx_null_string
, 0, NULL
}
171 ngx_http_init_connection(ngx_connection_t
*c
)
174 ngx_http_log_ctx_t
*ctx
;
176 ctx
= ngx_palloc(c
->pool
, sizeof(ngx_http_log_ctx_t
));
178 ngx_http_close_connection(c
);
184 ctx
->current_request
= NULL
;
186 c
->log
->connection
= c
->number
;
187 c
->log
->handler
= ngx_http_log_error
;
189 c
->log
->action
= "reading client request line";
191 c
->log_error
= NGX_ERROR_INFO
;
194 rev
->handler
= ngx_http_init_request
;
195 c
->write
->handler
= ngx_http_empty_handler
;
198 ngx_atomic_fetch_add(ngx_stat_reading
, 1);
202 /* the deferred accept(), rtsig, aio, iocp */
204 if (ngx_use_accept_mutex
) {
205 ngx_post_event(rev
, &ngx_posted_events
);
209 ngx_http_init_request(rev
);
213 ngx_add_timer(rev
, c
->listening
->post_accept_timeout
);
215 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
217 ngx_atomic_fetch_add(ngx_stat_reading
, -1);
219 ngx_http_close_connection(c
);
226 ngx_http_init_request(ngx_event_t
*rev
)
231 ngx_http_request_t
*r
;
232 ngx_http_in_port_t
*hip
;
233 ngx_http_in_addr_t
*hia
;
234 ngx_http_log_ctx_t
*ctx
;
235 ngx_http_connection_t
*hc
;
236 ngx_http_core_srv_conf_t
*cscf
;
237 ngx_http_core_loc_conf_t
*clcf
;
238 ngx_http_core_main_conf_t
*cmcf
;
241 ngx_atomic_fetch_add(ngx_stat_reading
, -1);
247 ngx_log_error(NGX_LOG_INFO
, c
->log
, NGX_ETIMEDOUT
, "client timed out");
249 ngx_http_close_connection(c
);
256 hc
= ngx_pcalloc(c
->pool
, sizeof(ngx_http_connection_t
));
258 ngx_http_close_connection(c
);
266 ngx_memzero(r
, sizeof(ngx_http_request_t
));
268 r
->pipeline
= hc
->pipeline
;
271 r
->header_in
= hc
->busy
[0];
275 r
= ngx_pcalloc(c
->pool
, sizeof(ngx_http_request_t
));
277 ngx_http_close_connection(c
);
285 r
->http_connection
= hc
;
288 r
->signature
= NGX_HTTP_MODULE
;
290 /* find the server configuration for the address:port */
294 hip
= c
->listening
->servers
;
298 r
->port_text
= &hip
->port_text
;
304 if (hip
->naddrs
> 1) {
307 * There are several addresses on this port and one of them
308 * is the "*:port" wildcard so getsockname() is needed to determine
309 * the server address.
311 * AcceptEx() already has given this address.
315 if (c
->local_sockaddr
) {
317 ((struct sockaddr_in
*) c
->local_sockaddr
)->sin_addr
.s_addr
;
322 if (ngx_http_server_addr(r
, NULL
) != NGX_OK
) {
323 ngx_http_close_connection(c
);
328 /* the last address is "*" */
330 for ( /* void */ ; i
< hip
->naddrs
- 1; i
++) {
331 if (hia
[i
].addr
== r
->in_addr
) {
337 r
->in_addr
= hia
[0].addr
;
340 r
->virtual_names
= hia
[i
].virtual_names
;
342 /* the default server configuration for the address:port */
343 cscf
= hia
[i
].core_srv_conf
;
345 r
->main_conf
= cscf
->ctx
->main_conf
;
346 r
->srv_conf
= cscf
->ctx
->srv_conf
;
347 r
->loc_conf
= cscf
->ctx
->loc_conf
;
349 rev
->handler
= ngx_http_process_request_line
;
354 ngx_http_ssl_srv_conf_t
*sscf
;
356 sscf
= ngx_http_get_module_srv_conf(r
, ngx_http_ssl_module
);
359 if (c
->ssl
== NULL
) {
360 if (ngx_ssl_create_connection(&sscf
->ssl
, c
, NGX_SSL_BUFFER
)
363 ngx_http_close_connection(c
);
367 rev
->handler
= ngx_http_ssl_handshake
;
370 r
->main_filter_need_in_memory
= 1;
376 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
377 c
->log
->file
= clcf
->err_log
->file
;
378 if (!(c
->log
->log_level
& NGX_LOG_DEBUG_CONNECTION
)) {
379 c
->log
->log_level
= clcf
->err_log
->log_level
;
382 if (c
->buffer
== NULL
) {
383 c
->buffer
= ngx_create_temp_buf(c
->pool
,
384 cscf
->client_header_buffer_size
);
385 if (c
->buffer
== NULL
) {
386 ngx_http_close_connection(c
);
391 if (r
->header_in
== NULL
) {
392 r
->header_in
= c
->buffer
;
395 r
->pool
= ngx_create_pool(cscf
->request_pool_size
, c
->log
);
396 if (r
->pool
== NULL
) {
397 ngx_http_close_connection(c
);
402 if (ngx_list_init(&r
->headers_out
.headers
, r
->pool
, 20,
403 sizeof(ngx_table_elt_t
))
406 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
410 r
->ctx
= ngx_pcalloc(r
->pool
, sizeof(void *) * ngx_http_max_module
);
411 if (r
->ctx
== NULL
) {
412 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
416 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
418 r
->variables
= ngx_pcalloc(r
->pool
, cmcf
->variables
.nelts
419 * sizeof(ngx_http_variable_value_t
));
420 if (r
->variables
== NULL
) {
421 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
425 c
->single_connection
= 1;
430 tp
= ngx_timeofday();
431 r
->start_sec
= tp
->sec
;
432 r
->start_msec
= tp
->msec
;
434 r
->method
= NGX_HTTP_UNKNOWN
;
436 r
->headers_in
.content_length_n
= -1;
437 r
->headers_in
.keep_alive_n
= -1;
438 r
->headers_out
.content_length_n
= -1;
439 r
->headers_out
.last_modified_time
= -1;
441 r
->uri_changes
= NGX_HTTP_MAX_URI_CHANGES
+ 1;
442 r
->subrequests
= NGX_HTTP_MAX_SUBREQUESTS
+ 1;
444 r
->http_state
= NGX_HTTP_READING_REQUEST_STATE
;
448 ctx
->current_request
= r
;
449 r
->log_handler
= ngx_http_log_error_handler
;
452 ngx_atomic_fetch_add(ngx_stat_reading
, 1);
454 ngx_atomic_fetch_add(ngx_stat_requests
, 1);
464 ngx_http_ssl_handshake(ngx_event_t
*rev
)
470 ngx_http_request_t
*r
;
475 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
476 "http check ssl handshake");
479 ngx_log_error(NGX_LOG_INFO
, c
->log
, NGX_ETIMEDOUT
, "client timed out");
481 ngx_http_close_request(r
, NGX_HTTP_REQUEST_TIME_OUT
);
485 n
= recv(c
->fd
, (char *) buf
, 1, MSG_PEEK
);
487 if (n
== -1 && ngx_socket_errno
== NGX_EAGAIN
) {
489 if (!rev
->timer_set
) {
490 ngx_add_timer(rev
, c
->listening
->post_accept_timeout
);
493 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
494 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
501 if (buf
[0] == 0x80 /* SSLv2 */ || buf
[0] == 0x16 /* SSLv3/TLSv1 */) {
502 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
503 "https ssl handshake: 0x%02Xd", buf
[0]);
505 rc
= ngx_ssl_handshake(c
);
507 if (rc
== NGX_AGAIN
) {
509 if (!rev
->timer_set
) {
510 ngx_add_timer(rev
, c
->listening
->post_accept_timeout
);
513 c
->ssl
->handler
= ngx_http_ssl_handshake_handler
;
517 ngx_http_ssl_handshake_handler(c
);
522 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
529 rev
->handler
= ngx_http_process_request_line
;
530 ngx_http_process_request_line(rev
);
535 ngx_http_ssl_handshake_handler(ngx_connection_t
*c
)
537 ngx_http_request_t
*r
;
539 if (c
->ssl
->handshaked
) {
542 * The majority of browsers do not send the "close notify" alert.
543 * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
544 * and Links. And what is more, MSIE ignores the server's alert.
546 * Opera and recent Mozilla send the alert.
549 c
->ssl
->no_wait_shutdown
= 1;
551 c
->read
->handler
= ngx_http_process_request_line
;
552 /* STUB: epoll edge */ c
->write
->handler
= ngx_http_empty_handler
;
554 ngx_http_process_request_line(c
->read
);
561 ngx_http_close_request(r
, NGX_HTTP_BAD_REQUEST
);
566 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
569 ngx_http_ssl_servername(ngx_ssl_conn_t
*ssl_conn
, int *ad
, void *arg
)
571 const char *servername
;
573 ngx_http_request_t
*r
;
574 ngx_http_ssl_srv_conf_t
*sscf
;
576 servername
= SSL_get_servername(ssl_conn
, TLSEXT_NAMETYPE_host_name
);
578 if (servername
== NULL
) {
579 return SSL_TLSEXT_ERR_NOACK
;
582 c
= ngx_ssl_get_connection(ssl_conn
);
584 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
585 "SSL server name: \"%s\"", servername
);
589 if (ngx_http_find_virtual_server(r
, (u_char
*) servername
,
590 ngx_strlen(servername
))
593 return SSL_TLSEXT_ERR_NOACK
;
596 sscf
= ngx_http_get_module_srv_conf(r
, ngx_http_ssl_module
);
598 SSL_set_SSL_CTX(ssl_conn
, sscf
->ssl
.ctx
);
600 return SSL_TLSEXT_ERR_OK
;
609 ngx_http_process_request_line(ngx_event_t
*rev
)
614 ngx_http_request_t
*r
;
615 ngx_http_core_srv_conf_t
*cscf
;
620 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
621 "http process request line");
624 ngx_log_error(NGX_LOG_INFO
, c
->log
, NGX_ETIMEDOUT
, "client timed out");
626 ngx_http_close_request(r
, NGX_HTTP_REQUEST_TIME_OUT
);
634 if (rc
== NGX_AGAIN
) {
635 n
= ngx_http_read_request_header(r
);
637 if (n
== NGX_AGAIN
|| n
== NGX_ERROR
) {
642 rc
= ngx_http_parse_request_line(r
, r
->header_in
);
646 /* the request line has been parsed successfully */
648 r
->request_line
.len
= r
->request_end
- r
->request_start
;
649 r
->request_line
.data
= r
->request_start
;
650 *r
->request_end
= '\0';
654 r
->uri
.len
= r
->args_start
- 1 - r
->uri_start
;
656 r
->uri
.len
= r
->uri_end
- r
->uri_start
;
660 if (r
->complex_uri
|| r
->quoted_uri
) {
662 r
->uri
.data
= ngx_pnalloc(r
->pool
, r
->uri
.len
+ 1);
663 if (r
->uri
.data
== NULL
) {
664 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
668 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
670 rc
= ngx_http_parse_complex_uri(r
, cscf
->merge_slashes
);
672 if (rc
== NGX_HTTP_PARSE_INVALID_REQUEST
) {
673 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
674 "client sent invalid request");
675 ngx_http_finalize_request(r
, NGX_HTTP_BAD_REQUEST
);
680 r
->uri
.data
= r
->uri_start
;
684 r
->unparsed_uri
.len
= r
->uri_end
- r
->uri_start
;
685 r
->unparsed_uri
.data
= r
->uri_start
;
688 r
->method_name
.len
= r
->method_end
- r
->request_start
+ 1;
689 r
->method_name
.data
= r
->request_line
.data
;
692 if (r
->http_protocol
.data
) {
693 r
->http_protocol
.len
= r
->request_end
- r
->http_protocol
.data
;
699 r
->exten
.len
= r
->args_start
- 1 - r
->uri_ext
;
701 r
->exten
.len
= r
->uri_end
- r
->uri_ext
;
704 r
->exten
.data
= r
->uri_ext
;
708 if (r
->args_start
&& r
->uri_end
> r
->args_start
) {
709 r
->args
.len
= r
->uri_end
- r
->args_start
;
710 r
->args
.data
= r
->args_start
;
714 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
715 "http request line: \"%V\"", &r
->request_line
);
717 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
718 "http uri: \"%V\"", &r
->uri
);
720 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
721 "http args: \"%V\"", &r
->args
);
723 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
724 "http exten: \"%V\"", &r
->exten
);
726 if (r
->host_start
&& r
->host_end
) {
727 n
= ngx_http_validate_host(r
->host_start
,
728 r
->host_end
- r
->host_start
);
731 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
732 "client sent invalid host in request line");
733 ngx_http_finalize_request(r
, NGX_HTTP_BAD_REQUEST
);
737 r
->headers_in
.server
.len
= n
;
738 r
->headers_in
.server
.data
= r
->host_start
;
741 if (r
->http_version
< NGX_HTTP_VERSION_10
) {
743 if (ngx_http_find_virtual_server(r
, r
->headers_in
.server
.data
,
744 r
->headers_in
.server
.len
)
747 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
751 ngx_http_process_request(r
);
756 if (ngx_list_init(&r
->headers_in
.headers
, r
->pool
, 20,
757 sizeof(ngx_table_elt_t
))
760 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
765 if (ngx_array_init(&r
->headers_in
.cookies
, r
->pool
, 2,
766 sizeof(ngx_table_elt_t
*))
769 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
773 c
->log
->action
= "reading client request headers";
775 rev
->handler
= ngx_http_process_request_headers
;
776 ngx_http_process_request_headers(rev
);
781 if (rc
!= NGX_AGAIN
) {
783 /* there was error while a request line parsing */
785 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
786 ngx_http_client_errors
[rc
- NGX_HTTP_CLIENT_ERROR
]);
787 ngx_http_finalize_request(r
, NGX_HTTP_BAD_REQUEST
);
791 /* NGX_AGAIN: a request line parsing is still incomplete */
793 if (r
->header_in
->pos
== r
->header_in
->end
) {
795 rv
= ngx_http_alloc_large_header_buffer(r
, 1);
797 if (rv
== NGX_ERROR
) {
798 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
802 if (rv
== NGX_DECLINED
) {
803 r
->request_line
.len
= r
->header_in
->end
- r
->request_start
;
804 r
->request_line
.data
= r
->request_start
;
806 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
807 "client sent too long URI");
808 ngx_http_finalize_request(r
, NGX_HTTP_REQUEST_URI_TOO_LARGE
);
817 ngx_http_process_request_headers(ngx_event_t
*rev
)
824 ngx_http_header_t
*hh
;
825 ngx_http_request_t
*r
;
826 ngx_http_core_srv_conf_t
*cscf
;
827 ngx_http_core_main_conf_t
*cmcf
;
832 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
833 "http process request header line");
836 ngx_log_error(NGX_LOG_INFO
, c
->log
, NGX_ETIMEDOUT
, "client timed out");
838 ngx_http_close_request(r
, NGX_HTTP_REQUEST_TIME_OUT
);
842 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
843 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
849 if (rc
== NGX_AGAIN
) {
851 if (r
->header_in
->pos
== r
->header_in
->end
) {
853 rv
= ngx_http_alloc_large_header_buffer(r
, 0);
855 if (rv
== NGX_ERROR
) {
856 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
860 if (rv
== NGX_DECLINED
) {
861 header
.len
= r
->header_in
->end
- r
->header_name_start
;
862 header
.data
= r
->header_name_start
;
864 if (header
.len
> NGX_MAX_ERROR_STR
- 300) {
865 header
.len
= NGX_MAX_ERROR_STR
- 300;
866 header
.data
[header
.len
++] = '.';
867 header
.data
[header
.len
++] = '.';
868 header
.data
[header
.len
++] = '.';
871 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
872 "client sent too long header line: \"%V\"",
874 ngx_http_finalize_request(r
, NGX_HTTP_BAD_REQUEST
);
879 n
= ngx_http_read_request_header(r
);
881 if (n
== NGX_AGAIN
|| n
== NGX_ERROR
) {
886 rc
= ngx_http_parse_header_line(r
, r
->header_in
);
890 if (r
->invalid_header
&& cscf
->ignore_invalid_headers
) {
892 /* there was error while a header line parsing */
894 header
.len
= r
->header_end
- r
->header_name_start
;
895 header
.data
= r
->header_name_start
;
897 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
898 "client sent invalid header line: \"%V\"",
903 /* a header line has been parsed successfully */
905 h
= ngx_list_push(&r
->headers_in
.headers
);
907 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
911 h
->hash
= r
->header_hash
;
913 h
->key
.len
= r
->header_name_end
- r
->header_name_start
;
914 h
->key
.data
= r
->header_name_start
;
915 h
->key
.data
[h
->key
.len
] = '\0';
917 h
->value
.len
= r
->header_end
- r
->header_start
;
918 h
->value
.data
= r
->header_start
;
919 h
->value
.data
[h
->value
.len
] = '\0';
921 h
->lowcase_key
= ngx_pnalloc(r
->pool
, h
->key
.len
);
922 if (h
->lowcase_key
== NULL
) {
923 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
927 if (h
->key
.len
== r
->lowcase_index
) {
928 ngx_memcpy(h
->lowcase_key
, r
->lowcase_header
, h
->key
.len
);
931 ngx_strlow(h
->lowcase_key
, h
->key
.data
, h
->key
.len
);
934 hh
= ngx_hash_find(&cmcf
->headers_in_hash
, h
->hash
,
935 h
->lowcase_key
, h
->key
.len
);
937 if (hh
&& hh
->handler(r
, h
, hh
->offset
) != NGX_OK
) {
941 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
942 "http header: \"%V: %V\"",
948 if (rc
== NGX_HTTP_PARSE_HEADER_DONE
) {
950 /* a whole header has been parsed successfully */
952 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
955 r
->request_length
+= r
->header_in
->pos
- r
->header_in
->start
;
957 r
->http_state
= NGX_HTTP_PROCESS_REQUEST_STATE
;
959 rc
= ngx_http_process_request_header(r
);
965 ngx_http_process_request(r
);
970 if (rc
== NGX_AGAIN
) {
972 /* a header line parsing is still not complete */
977 /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
979 header
.len
= r
->header_end
- r
->header_name_start
;
980 header
.data
= r
->header_name_start
;
981 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
982 "client sent invalid header line: \"%V\\r...\"",
984 ngx_http_finalize_request(r
, NGX_HTTP_BAD_REQUEST
);
991 ngx_http_read_request_header(ngx_http_request_t
*r
)
996 ngx_http_core_srv_conf_t
*cscf
;
1001 n
= r
->header_in
->last
- r
->header_in
->pos
;
1008 n
= c
->recv(c
, r
->header_in
->last
,
1009 r
->header_in
->end
- r
->header_in
->last
);
1014 if (n
== NGX_AGAIN
) {
1015 if (!rev
->timer_set
) {
1016 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
1017 ngx_add_timer(rev
, cscf
->client_header_timeout
);
1020 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
1021 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
1029 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
1030 "client closed prematurely connection");
1033 if (n
== 0 || n
== NGX_ERROR
) {
1035 c
->log
->action
= "reading client request headers";
1037 ngx_http_finalize_request(r
, NGX_HTTP_BAD_REQUEST
);
1041 r
->header_in
->last
+= n
;
1048 ngx_http_alloc_large_header_buffer(ngx_http_request_t
*r
,
1049 ngx_uint_t request_line
)
1053 ngx_http_connection_t
*hc
;
1054 ngx_http_core_srv_conf_t
*cscf
;
1056 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1057 "http alloc large header buffer");
1059 if (request_line
&& r
->state
== 0) {
1061 /* the client fills up the buffer with "\r\n" */
1063 r
->request_length
+= r
->header_in
->end
- r
->header_in
->start
;
1065 r
->header_in
->pos
= r
->header_in
->start
;
1066 r
->header_in
->last
= r
->header_in
->start
;
1071 old
= request_line
? r
->request_start
: r
->header_name_start
;
1073 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
1076 && (size_t) (r
->header_in
->pos
- old
)
1077 >= cscf
->large_client_header_buffers
.size
)
1079 return NGX_DECLINED
;
1082 hc
= r
->http_connection
;
1085 b
= hc
->free
[--hc
->nfree
];
1087 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1088 "http large header free: %p %uz",
1089 b
->pos
, b
->end
- b
->last
);
1091 } else if (hc
->nbusy
< cscf
->large_client_header_buffers
.num
) {
1093 if (hc
->busy
== NULL
) {
1094 hc
->busy
= ngx_palloc(r
->connection
->pool
,
1095 cscf
->large_client_header_buffers
.num
* sizeof(ngx_buf_t
*));
1096 if (hc
->busy
== NULL
) {
1101 b
= ngx_create_temp_buf(r
->connection
->pool
,
1102 cscf
->large_client_header_buffers
.size
);
1107 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1108 "http large header alloc: %p %uz",
1109 b
->pos
, b
->end
- b
->last
);
1112 return NGX_DECLINED
;
1115 hc
->busy
[hc
->nbusy
++] = b
;
1117 if (r
->state
== 0) {
1119 * r->state == 0 means that a header line was parsed successfully
1120 * and we do not need to copy incomplete header line and
1121 * to relocate the parser header pointers
1124 r
->request_length
+= r
->header_in
->end
- r
->header_in
->start
;
1131 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1132 "http large header copy: %d", r
->header_in
->pos
- old
);
1134 r
->request_length
+= old
- r
->header_in
->start
;
1138 ngx_memcpy(new, old
, r
->header_in
->pos
- old
);
1140 b
->pos
= new + (r
->header_in
->pos
- old
);
1141 b
->last
= new + (r
->header_in
->pos
- old
);
1144 r
->request_start
= new;
1146 if (r
->request_end
) {
1147 r
->request_end
= new + (r
->request_end
- old
);
1150 r
->method_end
= new + (r
->method_end
- old
);
1152 r
->uri_start
= new + (r
->uri_start
- old
);
1153 r
->uri_end
= new + (r
->uri_end
- old
);
1155 if (r
->schema_start
) {
1156 r
->schema_start
= new + (r
->schema_start
- old
);
1157 r
->schema_end
= new + (r
->schema_end
- old
);
1160 if (r
->host_start
) {
1161 r
->host_start
= new + (r
->host_start
- old
);
1163 r
->host_end
= new + (r
->host_end
- old
);
1167 if (r
->port_start
) {
1168 r
->port_start
= new + (r
->port_start
- old
);
1169 r
->port_end
= new + (r
->port_end
- old
);
1173 r
->uri_ext
= new + (r
->uri_ext
- old
);
1176 if (r
->args_start
) {
1177 r
->args_start
= new + (r
->args_start
- old
);
1180 if (r
->http_protocol
.data
) {
1181 r
->http_protocol
.data
= new + (r
->http_protocol
.data
- old
);
1185 r
->header_name_start
= new;
1186 r
->header_name_end
= new + (r
->header_name_end
- old
);
1187 r
->header_start
= new + (r
->header_start
- old
);
1188 r
->header_end
= new + (r
->header_end
- old
);
1198 ngx_http_process_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1201 ngx_table_elt_t
**ph
;
1203 ph
= (ngx_table_elt_t
**) ((char *) &r
->headers_in
+ offset
);
1214 ngx_http_process_unique_header_line(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1217 ngx_table_elt_t
**ph
;
1219 ph
= (ngx_table_elt_t
**) ((char *) &r
->headers_in
+ offset
);
1226 ngx_log_error(NGX_LOG_INFO
, r
->connection
->log
, 0,
1227 "client sent duplicate header line: \"%V: %V\", "
1228 "previous value: \"%V: %V\"",
1229 &h
->key
, &h
->value
, &(*ph
)->key
, &(*ph
)->value
);
1231 ngx_http_finalize_request(r
, NGX_HTTP_BAD_REQUEST
);
1238 ngx_http_process_host(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1243 if (r
->headers_in
.host
== NULL
) {
1244 r
->headers_in
.host
= h
;
1247 len
= ngx_http_validate_host(h
->value
.data
, h
->value
.len
);
1250 ngx_log_error(NGX_LOG_INFO
, r
->connection
->log
, 0,
1251 "client sent invalid host header");
1252 ngx_http_finalize_request(r
, NGX_HTTP_BAD_REQUEST
);
1256 if (r
->headers_in
.server
.len
) {
1260 r
->headers_in
.server
.len
= len
;
1261 r
->headers_in
.server
.data
= h
->value
.data
;
1268 ngx_http_process_connection(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1271 if (ngx_strcasestrn(h
->value
.data
, "close", 5 - 1)) {
1272 r
->headers_in
.connection_type
= NGX_HTTP_CONNECTION_CLOSE
;
1274 } else if (ngx_strcasestrn(h
->value
.data
, "keep-alive", 10 - 1)) {
1275 r
->headers_in
.connection_type
= NGX_HTTP_CONNECTION_KEEP_ALIVE
;
1283 ngx_http_process_user_agent(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1286 u_char
*ua
, *user_agent
;
1288 if (r
->headers_in
.user_agent
) {
1292 r
->headers_in
.user_agent
= h
;
1294 /* check some widespread browsers while the header is in CPU cache */
1296 user_agent
= h
->value
.data
;
1298 ua
= ngx_strstrn(user_agent
, "MSIE", 4 - 1);
1300 if (ua
&& ua
+ 8 < user_agent
+ h
->value
.len
) {
1302 r
->headers_in
.msie
= 1;
1304 if (ua
[4] == ' ' && ua
[5] == '4' && ua
[6] == '.') {
1305 r
->headers_in
.msie4
= 1;
1309 /* MSIE ignores the SSL "close notify" alert */
1311 c
->ssl
->no_send_shutdown
= 1;
1316 if (ngx_strstrn(user_agent
, "Opera", 5 - 1)) {
1317 r
->headers_in
.opera
= 1;
1318 r
->headers_in
.msie
= 0;
1319 r
->headers_in
.msie4
= 0;
1322 if (!r
->headers_in
.msie
&& !r
->headers_in
.opera
) {
1324 if (ngx_strstrn(user_agent
, "Gecko/", 6 - 1)) {
1325 r
->headers_in
.gecko
= 1;
1327 } else if (ngx_strstrn(user_agent
, "Konqueror", 9 - 1)) {
1328 r
->headers_in
.konqueror
= 1;
1337 ngx_http_process_cookie(ngx_http_request_t
*r
, ngx_table_elt_t
*h
,
1340 ngx_table_elt_t
**cookie
;
1342 cookie
= ngx_array_push(&r
->headers_in
.cookies
);
1348 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
1355 ngx_http_process_request_header(ngx_http_request_t
*r
)
1357 if (ngx_http_find_virtual_server(r
, r
->headers_in
.server
.data
,
1358 r
->headers_in
.server
.len
)
1361 ngx_http_finalize_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
1365 if (r
->headers_in
.host
== NULL
&& r
->http_version
> NGX_HTTP_VERSION_10
) {
1366 ngx_log_error(NGX_LOG_INFO
, r
->connection
->log
, 0,
1367 "client sent HTTP/1.1 request without \"Host\" header");
1368 ngx_http_finalize_request(r
, NGX_HTTP_BAD_REQUEST
);
1372 if (r
->headers_in
.content_length
) {
1373 r
->headers_in
.content_length_n
=
1374 ngx_atoof(r
->headers_in
.content_length
->value
.data
,
1375 r
->headers_in
.content_length
->value
.len
);
1377 if (r
->headers_in
.content_length_n
== NGX_ERROR
) {
1378 ngx_log_error(NGX_LOG_INFO
, r
->connection
->log
, 0,
1379 "client sent invalid \"Content-Length\" header");
1380 ngx_http_finalize_request(r
, NGX_HTTP_LENGTH_REQUIRED
);
1385 if (r
->method
& (NGX_HTTP_POST
|NGX_HTTP_PUT
)
1386 && r
->headers_in
.content_length_n
== -1)
1388 ngx_log_error(NGX_LOG_INFO
, r
->connection
->log
, 0,
1389 "client sent %V method without \"Content-Length\" header",
1391 ngx_http_finalize_request(r
, NGX_HTTP_LENGTH_REQUIRED
);
1395 if (r
->method
& NGX_HTTP_TRACE
) {
1396 ngx_log_error(NGX_LOG_INFO
, r
->connection
->log
, 0,
1397 "client sent TRACE method");
1398 ngx_http_finalize_request(r
, NGX_HTTP_NOT_ALLOWED
);
1402 if (r
->headers_in
.transfer_encoding
1403 && ngx_strcasestrn(r
->headers_in
.transfer_encoding
->value
.data
,
1406 ngx_log_error(NGX_LOG_INFO
, r
->connection
->log
, 0,
1407 "client sent \"Transfer-Encoding: chunked\" header");
1408 ngx_http_finalize_request(r
, NGX_HTTP_LENGTH_REQUIRED
);
1412 if (r
->headers_in
.connection_type
== NGX_HTTP_CONNECTION_KEEP_ALIVE
) {
1413 if (r
->headers_in
.keep_alive
) {
1414 r
->headers_in
.keep_alive_n
=
1415 ngx_atotm(r
->headers_in
.keep_alive
->value
.data
,
1416 r
->headers_in
.keep_alive
->value
.len
);
1425 ngx_http_process_request(ngx_http_request_t
*r
)
1427 ngx_connection_t
*c
;
1431 if (r
->plain_http
) {
1432 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
1433 "client sent plain HTTP request to HTTPS port");
1434 ngx_http_finalize_request(r
, NGX_HTTP_TO_HTTPS
);
1443 ngx_http_ssl_srv_conf_t
*sscf
;
1445 sscf
= ngx_http_get_module_srv_conf(r
, ngx_http_ssl_module
);
1447 if (sscf
->verify
== 1) {
1448 rc
= SSL_get_verify_result(c
->ssl
->connection
);
1450 if (rc
!= X509_V_OK
) {
1451 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
1452 "client SSL certificate verify error: (%l:%s)",
1453 rc
, X509_verify_cert_error_string(rc
));
1455 ngx_ssl_remove_cached_session(sscf
->ssl
.ctx
,
1456 (SSL_get0_session(c
->ssl
->connection
)));
1458 ngx_http_finalize_request(r
, NGX_HTTPS_CERT_ERROR
);
1462 cert
= SSL_get_peer_certificate(c
->ssl
->connection
);
1465 ngx_log_error(NGX_LOG_INFO
, c
->log
, 0,
1466 "client sent no required SSL certificate");
1468 ngx_ssl_remove_cached_session(sscf
->ssl
.ctx
,
1469 (SSL_get0_session(c
->ssl
->connection
)));
1471 ngx_http_finalize_request(r
, NGX_HTTPS_NO_CERT
);
1481 if (c
->read
->timer_set
) {
1482 ngx_del_timer(c
->read
);
1486 ngx_atomic_fetch_add(ngx_stat_reading
, -1);
1487 r
->stat_reading
= 0;
1488 ngx_atomic_fetch_add(ngx_stat_writing
, 1);
1489 r
->stat_writing
= 1;
1492 c
->read
->handler
= ngx_http_request_handler
;
1493 c
->write
->handler
= ngx_http_request_handler
;
1494 r
->read_event_handler
= ngx_http_block_reading
;
1496 ngx_http_handler(r
);
1503 ngx_http_validate_host(u_char
*host
, size_t len
)
1512 for (i
= 0; i
< len
; i
++) {
1531 if (ch
== '/' || ch
== '\0') {
1551 ngx_http_find_virtual_server(ngx_http_request_t
*r
, u_char
*host
, size_t len
)
1555 ngx_http_core_loc_conf_t
*clcf
;
1556 ngx_http_core_srv_conf_t
*cscf
;
1559 if (len
== 0 || r
->virtual_names
== NULL
) {
1560 return NGX_DECLINED
;
1567 server
= ngx_pnalloc(r
->pool
, len
);
1568 if (server
== NULL
) {
1573 hash
= ngx_hash_strlow(server
, host
, len
);
1575 cscf
= ngx_hash_find_combined(&r
->virtual_names
->names
, hash
, server
, len
);
1583 if (r
->virtual_names
->nregex
) {
1587 ngx_http_server_name_t
*sn
;
1592 sn
= r
->virtual_names
->regex
;
1594 for (i
= 0; i
< r
->virtual_names
->nregex
; i
++) {
1596 n
= ngx_regex_exec(sn
[i
].regex
, &name
, NULL
, 0);
1598 if (n
== NGX_REGEX_NO_MATCHED
) {
1603 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
1605 " failed: %d on \"%V\" using \"%V\"",
1606 n
, &name
, &sn
[i
].name
);
1612 cscf
= sn
[i
].core_srv_conf
;
1624 r
->srv_conf
= cscf
->ctx
->srv_conf
;
1625 r
->loc_conf
= cscf
->ctx
->loc_conf
;
1627 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1628 r
->connection
->log
->file
= clcf
->err_log
->file
;
1630 if (!(r
->connection
->log
->log_level
& NGX_LOG_DEBUG_CONNECTION
)) {
1631 r
->connection
->log
->log_level
= clcf
->err_log
->log_level
;
1639 ngx_http_request_handler(ngx_event_t
*ev
)
1641 ngx_connection_t
*c
;
1642 ngx_http_request_t
*r
;
1643 ngx_http_log_ctx_t
*ctx
;
1649 ctx
->current_request
= r
;
1652 r
->write_event_handler(r
);
1655 r
->read_event_handler(r
);
1661 ngx_http_finalize_request(ngx_http_request_t
*r
, ngx_int_t rc
)
1663 ngx_connection_t
*c
;
1664 ngx_http_request_t
*pr
;
1665 ngx_http_log_ctx_t
*ctx
;
1666 ngx_http_core_loc_conf_t
*clcf
;
1668 if (rc
== NGX_DONE
) {
1669 /* the request pool may be already destroyed */
1675 ngx_log_debug3(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1676 "http finalize request: %d, \"%V?%V\"",
1677 rc
, &r
->uri
, &r
->args
);
1679 if (rc
== NGX_DECLINED
) {
1680 r
->content_handler
= NULL
;
1681 r
->write_event_handler
= ngx_http_core_run_phases
;
1682 ngx_http_core_run_phases(r
);
1686 if (r
!= r
->main
&& r
->post_subrequest
) {
1687 rc
= r
->post_subrequest
->handler(r
, r
->post_subrequest
->data
, rc
);
1691 || rc
== NGX_HTTP_REQUEST_TIME_OUT
1692 || rc
== NGX_HTTP_CLIENT_CLOSED_REQUEST
1695 if (rc
> 0 && r
->headers_out
.status
== 0) {
1696 r
->headers_out
.status
= rc
;
1699 if (ngx_http_post_action(r
) == NGX_OK
) {
1703 ngx_http_close_request(r
, 0);
1707 if (rc
>= NGX_HTTP_SPECIAL_RESPONSE
1708 || rc
== NGX_HTTP_CREATED
1709 || rc
== NGX_HTTP_NO_CONTENT
)
1711 if (rc
== NGX_HTTP_CLOSE
) {
1712 ngx_http_close_request(r
, rc
);
1717 if (c
->read
->timer_set
) {
1718 ngx_del_timer(c
->read
);
1721 if (c
->write
->timer_set
) {
1722 ngx_del_timer(c
->write
);
1726 ngx_http_finalize_request(r
, ngx_http_special_response_handler(r
, rc
));
1730 if (r
!= r
->main
|| rc
== NGX_AGAIN
) {
1731 if (ngx_http_set_write_handler(r
) != NGX_OK
) {
1739 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1740 "http finalize non-active request: \"%V?%V\"",
1749 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1750 "http parent request: \"%V?%V\"", &pr
->uri
, &pr
->args
);
1752 if (rc
!= NGX_AGAIN
) {
1757 ctx
->current_request
= pr
;
1759 if (pr
->postponed
) {
1761 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1762 "http request: \"%V?%V\" has postponed",
1763 &pr
->uri
, &pr
->args
);
1765 if (rc
!= NGX_AGAIN
&& pr
->postponed
->request
== r
) {
1766 pr
->postponed
= pr
->postponed
->next
;
1769 if (r
->fast_subrequest
) {
1771 if (rc
== NGX_AGAIN
) {
1772 r
->fast_subrequest
= 0;
1775 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1776 "http fast subrequest: \"%V?%V\" done",
1781 if (rc
!= NGX_AGAIN
) {
1782 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1783 "http wake parent request: \"%V?%V\"",
1784 &pr
->uri
, &pr
->args
);
1786 pr
->write_event_handler(pr
);
1793 if (rc
== NGX_AGAIN
) {
1798 (void) ngx_http_set_write_handler(r
);
1802 if (!r
->post_action
) {
1803 r
->request_complete
= 1;
1806 if (ngx_http_post_action(r
) == NGX_OK
) {
1810 if (c
->read
->timer_set
) {
1811 ngx_del_timer(c
->read
);
1814 if (c
->write
->timer_set
) {
1815 c
->write
->delayed
= 0;
1816 ngx_del_timer(c
->write
);
1824 ngx_http_close_request(r
, 0);
1828 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1833 && clcf
->keepalive_timeout
> 0)
1835 ngx_http_set_keepalive(r
);
1838 } else if (r
->lingering_close
&& clcf
->lingering_timeout
> 0) {
1839 ngx_http_set_lingering_close(r
);
1843 ngx_http_close_request(r
, 0);
1848 ngx_http_set_write_handler(ngx_http_request_t
*r
)
1851 ngx_http_core_loc_conf_t
*clcf
;
1853 r
->http_state
= NGX_HTTP_WRITING_REQUEST_STATE
;
1855 r
->read_event_handler
= ngx_http_test_reading
;
1856 r
->write_event_handler
= ngx_http_writer
;
1858 wev
= r
->connection
->write
;
1860 if (wev
->ready
&& wev
->delayed
) {
1864 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1865 if (!wev
->delayed
) {
1866 ngx_add_timer(wev
, clcf
->send_timeout
);
1869 if (ngx_handle_write_event(wev
, clcf
->send_lowat
) == NGX_ERROR
) {
1870 ngx_http_close_request(r
, 0);
1879 ngx_http_writer(ngx_http_request_t
*r
)
1883 ngx_connection_t
*c
;
1884 ngx_http_core_loc_conf_t
*clcf
;
1889 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, wev
->log
, 0,
1890 "http writer handler: \"%V?%V\"", &r
->uri
, &r
->args
);
1892 if (wev
->timedout
) {
1893 if (!wev
->delayed
) {
1894 ngx_log_error(NGX_LOG_INFO
, c
->log
, NGX_ETIMEDOUT
,
1895 "client timed out");
1898 ngx_http_finalize_request(r
, NGX_HTTP_REQUEST_TIME_OUT
);
1906 clcf
= ngx_http_get_module_loc_conf(r
->main
, ngx_http_core_module
);
1907 ngx_add_timer(wev
, clcf
->send_timeout
);
1909 if (ngx_handle_write_event(wev
, clcf
->send_lowat
) == NGX_ERROR
) {
1910 ngx_http_close_request(r
, 0);
1918 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, wev
->log
, 0,
1919 "http writer delayed");
1921 clcf
= ngx_http_get_module_loc_conf(r
->main
, ngx_http_core_module
);
1923 if (ngx_handle_write_event(wev
, clcf
->send_lowat
) == NGX_ERROR
) {
1924 ngx_http_close_request(r
, 0);
1931 rc
= ngx_http_output_filter(r
, NULL
);
1937 ngx_log_debug3(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1938 "http writer output filter: %d, \"%V?%V\"",
1939 rc
, &r
->uri
, &r
->args
);
1941 if (rc
== NGX_AGAIN
) {
1942 clcf
= ngx_http_get_module_loc_conf(r
->main
, ngx_http_core_module
);
1943 if (!wev
->ready
&& !wev
->delayed
) {
1944 ngx_add_timer(wev
, clcf
->send_timeout
);
1947 if (ngx_handle_write_event(wev
, clcf
->send_lowat
) == NGX_ERROR
) {
1948 ngx_http_close_request(r
, 0);
1951 if (r
== r
->main
|| r
->buffered
) {
1958 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, wev
->log
, 0,
1959 "http writer done: \"%V?%V\"", &r
->uri
, &r
->args
);
1961 ngx_http_finalize_request(r
, rc
);
1966 ngx_http_block_reading(ngx_http_request_t
*r
)
1968 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1969 "http reading blocked");
1971 /* aio does not call this handler */
1973 if ((ngx_event_flags
& NGX_USE_LEVEL_EVENT
)
1974 && r
->connection
->read
->active
)
1976 if (ngx_del_event(r
->connection
->read
, NGX_READ_EVENT
, 0)
1979 ngx_http_close_request(r
, 0);
1986 ngx_http_test_reading(ngx_http_request_t
*r
)
1992 ngx_connection_t
*c
;
1997 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "http test reading");
1999 #if (NGX_HAVE_KQUEUE)
2001 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
2003 if (!rev
->pending_eof
) {
2009 err
= rev
->kq_errno
;
2016 n
= recv(c
->fd
, buf
, 1, MSG_PEEK
);
2025 } else if (n
== -1) {
2026 err
= ngx_socket_errno
;
2028 if (err
!= NGX_EAGAIN
) {
2036 /* aio does not call this handler */
2038 if ((ngx_event_flags
& NGX_USE_LEVEL_EVENT
) && rev
->active
) {
2040 if (ngx_del_event(rev
, NGX_READ_EVENT
, 0) == NGX_ERROR
) {
2041 ngx_http_close_request(r
, 0);
2053 ngx_log_error(NGX_LOG_INFO
, c
->log
, err
,
2054 "client closed prematurely connection");
2056 ngx_http_finalize_request(r
, 0);
2061 ngx_http_set_keepalive(ngx_http_request_t
*r
)
2066 ngx_event_t
*rev
, *wev
;
2067 ngx_connection_t
*c
;
2068 ngx_http_connection_t
*hc
;
2069 ngx_http_core_srv_conf_t
*cscf
;
2070 ngx_http_core_loc_conf_t
*clcf
;
2075 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
2077 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "set http keepalive handler");
2079 if (r
->discard_body
) {
2080 r
->lingering_time
= ngx_time() + (time_t) (clcf
->lingering_time
/ 1000);
2081 ngx_add_timer(rev
, clcf
->lingering_timeout
);
2085 c
->log
->action
= "closing request";
2087 hc
= r
->http_connection
;
2090 if (b
->pos
< b
->last
) {
2092 /* the pipelined request */
2094 if (b
!= c
->buffer
) {
2097 * If the large header buffers were allocated while the previous
2098 * request processing then we do not use c->buffer for
2099 * the pipelined request (see ngx_http_init_request()).
2101 * Now we would move the large header buffers to the free list.
2104 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
2106 if (hc
->free
== NULL
) {
2107 hc
->free
= ngx_palloc(c
->pool
,
2108 cscf
->large_client_header_buffers
.num
* sizeof(ngx_buf_t
*));
2110 if (hc
->free
== NULL
) {
2111 ngx_http_close_request(r
, 0);
2116 for (i
= 0; i
< hc
->nbusy
- 1; i
++) {
2118 hc
->free
[hc
->nfree
++] = f
;
2128 ngx_http_request_done(r
, 0);
2132 ngx_add_timer(rev
, clcf
->keepalive_timeout
);
2134 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
2135 ngx_http_close_connection(c
);
2140 wev
->handler
= ngx_http_empty_handler
;
2142 if (b
->pos
< b
->last
) {
2144 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "pipelined request");
2147 ngx_atomic_fetch_add(ngx_stat_reading
, 1);
2151 c
->log
->action
= "reading client pipelined request line";
2153 rev
->handler
= ngx_http_init_request
;
2154 ngx_post_event(rev
, &ngx_posted_events
);
2161 * To keep a memory footprint as small as possible for an idle
2162 * keepalive connection we try to free the ngx_http_request_t and
2163 * c->buffer's memory if they were allocated outside the c->pool.
2164 * The large header buffers are always allocated outside the c->pool and
2168 if (ngx_pfree(c
->pool
, r
) == NGX_OK
) {
2174 if (ngx_pfree(c
->pool
, b
->start
) == NGX_OK
) {
2177 * the special note for ngx_http_keepalive_handler() that
2178 * c->buffer's memory was freed
2188 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "hc free: %p %d",
2189 hc
->free
, hc
->nfree
);
2192 for (i
= 0; i
< hc
->nfree
; i
++) {
2193 ngx_pfree(c
->pool
, hc
->free
[i
]->start
);
2200 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "hc busy: %p %d",
2201 hc
->busy
, hc
->nbusy
);
2204 for (i
= 0; i
< hc
->nbusy
; i
++) {
2205 ngx_pfree(c
->pool
, hc
->busy
[i
]->start
);
2214 ngx_ssl_free_buffer(c
);
2218 rev
->handler
= ngx_http_keepalive_handler
;
2220 if (wev
->active
&& (ngx_event_flags
& NGX_USE_LEVEL_EVENT
)) {
2221 if (ngx_del_event(wev
, NGX_WRITE_EVENT
, 0) == NGX_ERROR
) {
2222 ngx_http_close_connection(c
);
2227 c
->log
->action
= "keepalive";
2229 if (c
->tcp_nopush
== NGX_TCP_NOPUSH_SET
) {
2230 if (ngx_tcp_push(c
->fd
) == -1) {
2231 ngx_connection_error(c
, ngx_socket_errno
, ngx_tcp_push_n
" failed");
2232 ngx_http_close_connection(c
);
2236 c
->tcp_nopush
= NGX_TCP_NOPUSH_UNSET
;
2237 tcp_nodelay
= ngx_tcp_nodelay_and_tcp_nopush
? 1 : 0;
2244 && clcf
->tcp_nodelay
2245 && c
->tcp_nodelay
== NGX_TCP_NODELAY_UNSET
)
2247 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "tcp_nodelay");
2249 if (setsockopt(c
->fd
, IPPROTO_TCP
, TCP_NODELAY
,
2250 (const void *) &tcp_nodelay
, sizeof(int))
2253 ngx_connection_error(c
, ngx_socket_errno
,
2254 "setsockopt(TCP_NODELAY) failed");
2255 ngx_http_close_connection(c
);
2259 c
->tcp_nodelay
= NGX_TCP_NODELAY_SET
;
2263 /* if ngx_http_request_t was freed then we need some other place */
2264 r
->http_state
= NGX_HTTP_KEEPALIVE_STATE
;
2270 ngx_post_event(rev
, &ngx_posted_events
);
2276 ngx_http_keepalive_handler(ngx_event_t
*rev
)
2281 ngx_connection_t
*c
;
2285 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "http keepalive handler");
2287 if (rev
->timedout
|| c
->close
) {
2288 ngx_http_close_connection(c
);
2292 #if (NGX_HAVE_KQUEUE)
2294 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
2295 if (rev
->pending_eof
) {
2296 c
->log
->handler
= NULL
;
2297 ngx_log_error(NGX_LOG_INFO
, c
->log
, rev
->kq_errno
,
2298 "kevent() reported that client %V closed "
2299 "keepalive connection", &c
->addr_text
);
2302 c
->ssl
->no_send_shutdown
= 1;
2305 ngx_http_close_connection(c
);
2313 size
= b
->end
- b
->start
;
2315 if (b
->pos
== NULL
) {
2318 * The c->buffer's memory was freed by ngx_http_set_keepalive().
2319 * However, the c->buffer->start and c->buffer->end were not changed
2320 * to keep the buffer size.
2323 b
->pos
= ngx_palloc(c
->pool
, size
);
2324 if (b
->pos
== NULL
) {
2325 ngx_http_close_connection(c
);
2331 b
->end
= b
->pos
+ size
;
2335 * MSIE closes a keepalive connection with RST flag
2336 * so we ignore ECONNRESET here.
2339 c
->log_error
= NGX_ERROR_IGNORE_ECONNRESET
;
2340 ngx_set_socket_errno(0);
2342 n
= c
->recv(c
, b
->last
, size
);
2343 c
->log_error
= NGX_ERROR_INFO
;
2345 if (n
== NGX_AGAIN
) {
2346 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
2347 ngx_http_close_connection(c
);
2353 if (n
== NGX_ERROR
) {
2354 ngx_http_close_connection(c
);
2358 c
->log
->handler
= NULL
;
2361 ngx_log_error(NGX_LOG_INFO
, c
->log
, ngx_socket_errno
,
2362 "client %V closed keepalive connection", &c
->addr_text
);
2363 ngx_http_close_connection(c
);
2370 ngx_atomic_fetch_add(ngx_stat_reading
, 1);
2373 c
->log
->handler
= ngx_http_log_error
;
2374 c
->log
->action
= "reading client request line";
2378 ngx_http_init_request(rev
);
2383 ngx_http_set_lingering_close(ngx_http_request_t
*r
)
2385 ngx_event_t
*rev
, *wev
;
2386 ngx_connection_t
*c
;
2387 ngx_http_core_loc_conf_t
*clcf
;
2391 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
2394 rev
->handler
= ngx_http_lingering_close_handler
;
2396 r
->lingering_time
= ngx_time() + (time_t) (clcf
->lingering_time
/ 1000);
2397 ngx_add_timer(rev
, clcf
->lingering_timeout
);
2399 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
2400 ngx_http_close_request(r
, 0);
2405 wev
->handler
= ngx_http_empty_handler
;
2407 if (wev
->active
&& (ngx_event_flags
& NGX_USE_LEVEL_EVENT
)) {
2408 if (ngx_del_event(wev
, NGX_WRITE_EVENT
, 0) == NGX_ERROR
) {
2409 ngx_http_close_request(r
, 0);
2414 if (ngx_shutdown_socket(c
->fd
, NGX_WRITE_SHUTDOWN
) == -1) {
2415 ngx_connection_error(c
, ngx_socket_errno
,
2416 ngx_shutdown_socket_n
" failed");
2417 ngx_http_close_request(r
, 0);
2422 ngx_http_lingering_close_handler(rev
);
2428 ngx_http_lingering_close_handler(ngx_event_t
*rev
)
2432 ngx_connection_t
*c
;
2433 ngx_http_request_t
*r
;
2434 ngx_http_core_loc_conf_t
*clcf
;
2435 u_char buffer
[NGX_HTTP_LINGERING_BUFFER_SIZE
];
2440 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2441 "http lingering close handler");
2443 if (rev
->timedout
) {
2445 ngx_http_close_request(r
, 0);
2449 timer
= (ngx_msec_t
) (r
->lingering_time
- ngx_time());
2451 ngx_http_close_request(r
, 0);
2456 n
= c
->recv(c
, buffer
, NGX_HTTP_LINGERING_BUFFER_SIZE
);
2458 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "lingering read: %d", n
);
2460 if (n
== NGX_ERROR
|| n
== 0) {
2461 ngx_http_close_request(r
, 0);
2465 } while (rev
->ready
);
2467 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
2468 ngx_http_close_request(r
, 0);
2472 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
2476 if (timer
> clcf
->lingering_timeout
) {
2477 timer
= clcf
->lingering_timeout
;
2480 ngx_add_timer(rev
, timer
);
2485 ngx_http_empty_handler(ngx_event_t
*wev
)
2487 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, wev
->log
, 0, "http empty handler");
2494 ngx_http_request_empty_handler(ngx_http_request_t
*r
)
2496 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2497 "http request empty handler");
2504 ngx_http_send_special(ngx_http_request_t
*r
, ngx_uint_t flags
)
2509 b
= ngx_calloc_buf(r
->pool
);
2514 if (flags
& NGX_HTTP_LAST
) {
2518 if (flags
& NGX_HTTP_FLUSH
) {
2525 return ngx_http_output_filter(r
, &out
);
2530 ngx_http_post_action(ngx_http_request_t
*r
)
2532 ngx_http_core_loc_conf_t
*clcf
;
2534 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
2536 if (clcf
->post_action
.data
== NULL
) {
2537 return NGX_DECLINED
;
2540 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2541 "post action: \"%V\"", &clcf
->post_action
);
2543 r
->http_version
= NGX_HTTP_VERSION_9
;
2547 r
->read_event_handler
= ngx_http_block_reading
;
2549 if (clcf
->post_action
.data
[0] == '/') {
2550 ngx_http_internal_redirect(r
, &clcf
->post_action
, NULL
);
2553 ngx_http_named_location(r
, &clcf
->post_action
);
2561 ngx_http_close_request(ngx_http_request_t
*r
, ngx_int_t error
)
2563 ngx_connection_t
*c
;
2567 ngx_http_request_done(r
->main
, error
);
2568 ngx_http_close_connection(c
);
2573 ngx_http_request_done(ngx_http_request_t
*r
, ngx_int_t error
)
2577 struct linger linger
;
2578 ngx_http_cleanup_t
*cln
;
2579 ngx_http_log_ctx_t
*ctx
;
2580 ngx_http_handler_pt
*log_handler
;
2581 ngx_http_core_loc_conf_t
*clcf
;
2582 ngx_http_core_main_conf_t
*cmcf
;
2584 log
= r
->connection
->log
;
2586 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, log
, 0, "http close request");
2588 if (r
->pool
== NULL
) {
2589 ngx_log_error(NGX_LOG_ALERT
, log
, 0, "http request already closed");
2593 for (cln
= r
->cleanup
; cln
; cln
= cln
->next
) {
2595 cln
->handler(cln
->data
);
2601 if (r
->stat_reading
) {
2602 ngx_atomic_fetch_add(ngx_stat_reading
, -1);
2605 if (r
->stat_writing
) {
2606 ngx_atomic_fetch_add(ngx_stat_writing
, -1);
2611 if (error
&& r
->headers_out
.status
== 0) {
2612 r
->headers_out
.status
= error
;
2615 log
->action
= "logging request";
2617 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
2619 log_handler
= cmcf
->phases
[NGX_HTTP_LOG_PHASE
].handlers
.elts
;
2620 n
= cmcf
->phases
[NGX_HTTP_LOG_PHASE
].handlers
.nelts
;
2621 for (i
= 0; i
< n
; i
++) {
2625 log
->action
= "closing request";
2627 if (r
->connection
->timedout
) {
2628 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
2630 if (clcf
->reset_timedout_connection
) {
2632 linger
.l_linger
= 0;
2634 if (setsockopt(r
->connection
->fd
, SOL_SOCKET
, SO_LINGER
,
2635 (const void *) &linger
, sizeof(struct linger
)) == -1)
2637 ngx_log_error(NGX_LOG_ALERT
, log
, ngx_socket_errno
,
2638 "setsockopt(SO_LINGER) failed");
2643 /* the various request strings were allocated from r->pool */
2645 ctx
->request
= NULL
;
2647 r
->request_line
.len
= 0;
2649 r
->connection
->destroyed
= 1;
2651 ngx_destroy_pool(r
->pool
);
2656 ngx_http_close_connection(ngx_connection_t
*c
)
2660 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2661 "close http connection: %d", c
->fd
);
2666 if (ngx_ssl_shutdown(c
) == NGX_AGAIN
) {
2667 c
->ssl
->handler
= ngx_http_close_connection
;
2675 ngx_atomic_fetch_add(ngx_stat_active
, -1);
2682 ngx_close_connection(c
);
2684 ngx_destroy_pool(pool
);
2689 ngx_http_log_error(ngx_log_t
*log
, u_char
*buf
, size_t len
)
2692 ngx_http_request_t
*r
;
2693 ngx_http_log_ctx_t
*ctx
;
2696 p
= ngx_snprintf(buf
, len
, " while %s", log
->action
);
2703 p
= ngx_snprintf(buf
, len
, ", client: %V", &ctx
->connection
->addr_text
);
2709 return r
->log_handler(r
, ctx
->current_request
, p
, len
);
2712 p
= ngx_snprintf(p
, len
, ", server: %V",
2713 &ctx
->connection
->listening
->addr_text
);
2721 ngx_http_log_error_handler(ngx_http_request_t
*r
, ngx_http_request_t
*sr
,
2722 u_char
*buf
, size_t len
)
2724 char *uri_separator
;
2726 ngx_http_upstream_t
*u
;
2727 ngx_http_core_srv_conf_t
*cscf
;
2729 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
2731 p
= ngx_snprintf(buf
, len
, ", server: %V", &cscf
->server_name
);
2735 if (r
->request_line
.data
== NULL
&& r
->request_start
) {
2736 for (p
= r
->request_start
; p
< r
->header_in
->last
; p
++) {
2737 if (*p
== CR
|| *p
== LF
) {
2742 r
->request_line
.len
= p
- r
->request_start
;
2743 r
->request_line
.data
= r
->request_start
;
2746 if (r
->request_line
.len
) {
2747 p
= ngx_snprintf(buf
, len
, ", request: \"%V\"", &r
->request_line
);
2753 p
= ngx_snprintf(buf
, len
, ", subrequest: \"%V\"", &sr
->uri
);
2760 if (u
&& u
->peer
.name
) {
2764 #if (NGX_HAVE_UNIX_DOMAIN)
2765 if (u
->peer
.sockaddr
&& u
->peer
.sockaddr
->sa_family
== AF_UNIX
) {
2766 uri_separator
= ":";
2770 p
= ngx_snprintf(buf
, len
, ", upstream: \"%V%V%s%V\"",
2771 &u
->schema
, u
->peer
.name
,
2772 uri_separator
, &u
->uri
);
2777 if (r
->headers_in
.host
) {
2778 p
= ngx_snprintf(buf
, len
, ", host: \"%V\"",
2779 &r
->headers_in
.host
->value
);
2784 if (r
->headers_in
.referer
) {
2785 p
= ngx_snprintf(buf
, len
, ", referrer: \"%V\"",
2786 &r
->headers_in
.referer
->value
);