3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
13 static void ngx_http_init_request(ngx_event_t
*ev
);
15 static void ngx_http_ssl_handshake(ngx_event_t
*rev
);
17 static void ngx_http_process_request_line(ngx_event_t
*rev
);
18 static void ngx_http_process_request_headers(ngx_event_t
*rev
);
19 static ssize_t
ngx_http_read_request_header(ngx_http_request_t
*r
);
20 static ngx_int_t
ngx_http_alloc_large_header_buffer(ngx_http_request_t
*r
,
21 ngx_uint_t request_line
);
22 static ngx_int_t
ngx_http_process_request_header(ngx_http_request_t
*r
);
23 static ngx_int_t
ngx_http_find_virtual_server(ngx_http_request_t
*r
);
25 static void ngx_http_set_write_handler(ngx_http_request_t
*r
);
27 static void ngx_http_block_read(ngx_event_t
*ev
);
28 static void ngx_http_read_discarded_body_event(ngx_event_t
*rev
);
29 static ngx_int_t
ngx_http_read_discarded_body(ngx_http_request_t
*r
);
31 static void ngx_http_set_keepalive(ngx_http_request_t
*r
);
32 static void ngx_http_keepalive_handler(ngx_event_t
*ev
);
33 static void ngx_http_set_lingering_close(ngx_http_request_t
*r
);
34 static void ngx_http_lingering_close_handler(ngx_event_t
*ev
);
36 static void ngx_http_client_error(ngx_http_request_t
*r
,
37 int client_error
, int error
);
38 static u_char
*ngx_http_log_error(ngx_log_t
*log
, u_char
*buf
, size_t len
);
41 /* NGX_HTTP_PARSE_... errors */
43 static char *client_header_errors
[] = {
44 "client %V sent invalid method \"%V\"",
45 "client %V sent invalid request \"%V\"",
46 "client %V sent too long URI in request \"%V\"",
47 "client %V sent invalid method in HTTP/0.9 request \"%V\"",
49 "client %V sent invalid header, URL: \"%V\"",
50 "client %V sent too long header line, URL: \"%V\"",
51 "client %V sent HTTP/1.1 request without \"Host\" header, URL: \"%V\"",
52 "client %V sent invalid \"Content-Length\" header, URL: \"%V\"",
53 "client %V sent POST method without \"Content-Length\" header, URL: \"%V\"",
57 ngx_http_header_t ngx_http_headers_in
[] = {
58 { ngx_string("Host"), offsetof(ngx_http_headers_in_t
, host
) },
59 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t
, connection
) },
60 { ngx_string("If-Modified-Since"),
61 offsetof(ngx_http_headers_in_t
, if_modified_since
) },
62 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t
, user_agent
) },
63 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t
, referer
) },
64 { ngx_string("Content-Length"),
65 offsetof(ngx_http_headers_in_t
, content_length
) },
66 { ngx_string("Content-Type"),
67 offsetof(ngx_http_headers_in_t
, content_type
) },
69 { ngx_string("Range"), offsetof(ngx_http_headers_in_t
, range
) },
71 { ngx_string("If-Range"), offsetof(ngx_http_headers_in_t
, if_range
) },
75 { ngx_string("Accept-Encoding"),
76 offsetof(ngx_http_headers_in_t
, accept_encoding
) },
77 { ngx_string("Via"), offsetof(ngx_http_headers_in_t
, via
) },
80 { ngx_string("Authorization"),
81 offsetof(ngx_http_headers_in_t
, authorization
) },
83 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t
, keep_alive
) },
86 { ngx_string("X-Forwarded-For"),
87 offsetof(ngx_http_headers_in_t
, x_forwarded_for
) },
88 { ngx_string("X-Real-IP"), offsetof(ngx_http_headers_in_t
, x_real_ip
) },
89 { ngx_string("X-URL"), offsetof(ngx_http_headers_in_t
, x_url
) },
92 #if (NGX_HTTP_HEADERS)
93 { ngx_string("Accept"), offsetof(ngx_http_headers_in_t
, accept
) },
94 { ngx_string("Accept-Language"),
95 offsetof(ngx_http_headers_in_t
, accept_language
) },
96 { ngx_string("Via"), offsetof(ngx_http_headers_in_t
, via
) },
99 { ngx_null_string
, 0 }
104 static void ngx_http_dummy(ngx_event_t
*wev
)
111 void ngx_http_init_connection(ngx_connection_t
*c
)
114 ngx_http_log_ctx_t
*ctx
;
116 if (!(ctx
= ngx_palloc(c
->pool
, sizeof(ngx_http_log_ctx_t
)))) {
117 ngx_http_close_connection(c
);
121 ctx
->client
= &c
->addr_text
;
124 c
->log
->connection
= c
->number
;
125 c
->log
->handler
= ngx_http_log_error
;
127 c
->log
->action
= "reading client request line";
129 c
->log_error
= NGX_ERROR_INFO
;
132 rev
->event_handler
= ngx_http_init_request
;
134 /* STUB: epoll edge */ c
->write
->event_handler
= ngx_http_empty_handler
;
137 /* the deferred accept(), rtsig, aio, iocp */
139 if (ngx_accept_mutex
) {
140 if (ngx_mutex_lock(ngx_posted_events_mutex
) == NGX_ERROR
) {
141 ngx_http_close_connection(c
);
147 ngx_mutex_unlock(ngx_posted_events_mutex
);
152 (*ngx_stat_reading
)++;
155 ngx_http_init_request(rev
);
159 ngx_add_timer(rev
, c
->listening
->post_accept_timeout
);
161 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
162 ngx_http_close_connection(c
);
167 /* TODO: learn SO_SNDBUF (to use in zerocopy) via kqueue's EV_CLEAR event */
170 c
->write
->event_handler
= ngx_http_dummy
;
172 if (ngx_handle_write_event(c
->write
, 0) == NGX_ERROR
) {
173 ngx_http_close_connection(c
);
179 (*ngx_stat_reading
)++;
185 static void ngx_http_init_request(ngx_event_t
*rev
)
189 struct sockaddr_in sin
;
191 ngx_http_request_t
*r
;
192 ngx_http_in_port_t
*in_port
;
193 ngx_http_in_addr_t
*in_addr
;
194 ngx_http_connection_t
*hc
;
195 ngx_http_server_name_t
*server_name
;
196 ngx_http_core_srv_conf_t
*cscf
;
197 ngx_http_core_loc_conf_t
*clcf
;
199 ngx_http_ssl_srv_conf_t
*sscf
;
205 ngx_log_error(NGX_LOG_INFO
, c
->log
, NGX_ETIMEDOUT
, "client timed out");
208 (*ngx_stat_reading
)--;
211 ngx_http_close_connection(c
);
220 (*ngx_stat_reading
)++;
224 if (!(hc
= ngx_pcalloc(c
->pool
, sizeof(ngx_http_connection_t
)))) {
227 (*ngx_stat_reading
)--;
230 ngx_http_close_connection(c
);
238 ngx_memzero(r
, sizeof(ngx_http_request_t
));
240 r
->pipeline
= hc
->pipeline
;
243 r
->header_in
= hc
->busy
[0];
247 if (!(r
= ngx_pcalloc(c
->pool
, sizeof(ngx_http_request_t
)))) {
250 (*ngx_stat_reading
)--;
253 ngx_http_close_connection(c
);
261 (*ngx_stat_reading
)--;
265 r
->http_connection
= hc
;
268 r
->signature
= NGX_HTTP_MODULE
;
270 /* find the server configuration for the address:port */
274 in_port
= c
->servers
;
275 in_addr
= in_port
->addrs
.elts
;
277 r
->port
= in_port
->port
;
278 r
->port_text
= &in_port
->port_text
;
282 if (in_port
->addrs
.nelts
> 1) {
285 * There are several addresses on this port and one of them
286 * is the "*:port" wildcard so getsockname() is needed to determine
287 * the server address.
289 * AcceptEx() already gave this address.
293 if (c
->local_sockaddr
) {
295 ((struct sockaddr_in
*) c
->local_sockaddr
)->sin_addr
.s_addr
;
300 len
= sizeof(struct sockaddr_in
);
301 if (getsockname(c
->fd
, (struct sockaddr
*) &sin
, &len
) == -1) {
302 ngx_connection_error(c
, ngx_socket_errno
,
303 "getsockname() failed");
304 ngx_http_close_connection(c
);
308 r
->in_addr
= sin
.sin_addr
.s_addr
;
311 /* the last in_port->addrs address is "*" */
313 for ( /* void */ ; i
< in_port
->addrs
.nelts
- 1; i
++) {
314 if (in_addr
[i
].addr
== r
->in_addr
) {
320 r
->in_addr
= in_addr
[0].addr
;
323 r
->virtual_names
= &in_addr
[i
];
325 /* the default server configuration for the address:port */
326 cscf
= in_addr
[i
].core_srv_conf
;
328 r
->main_conf
= cscf
->ctx
->main_conf
;
329 r
->srv_conf
= cscf
->ctx
->srv_conf
;
330 r
->loc_conf
= cscf
->ctx
->loc_conf
;
332 rev
->event_handler
= ngx_http_process_request_line
;
336 sscf
= ngx_http_get_module_srv_conf(r
, ngx_http_ssl_module
);
339 if (c
->ssl
== NULL
) {
340 if (ngx_ssl_create_session(sscf
->ssl_ctx
, c
, NGX_SSL_BUFFER
)
343 ngx_http_close_connection(c
);
347 rev
->event_handler
= ngx_http_ssl_handshake
;
350 * The majority of browsers do not send the "close notify" alert.
351 * Among them are MSIE, Mozilla, Netscape 4, Konqueror, and Links.
352 * And what is more MSIE ignores the server's alert.
354 * Opera always sends the alert.
357 c
->ssl
->no_rcv_shut
= 1;
360 r
->filter_need_in_memory
= 1;
365 server_name
= cscf
->server_names
.elts
;
366 r
->server_name
= server_name
->name
;
368 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
369 c
->log
->file
= clcf
->err_log
->file
;
370 if (!(c
->log
->log_level
& NGX_LOG_DEBUG_CONNECTION
)) {
371 c
->log
->log_level
= clcf
->err_log
->log_level
;
374 if (c
->buffer
== NULL
) {
375 c
->buffer
= ngx_create_temp_buf(c
->pool
,
376 cscf
->client_header_buffer_size
);
377 if (c
->buffer
== NULL
) {
378 ngx_http_close_connection(c
);
383 if (r
->header_in
== NULL
) {
384 r
->header_in
= c
->buffer
;
387 if (!(r
->pool
= ngx_create_pool(cscf
->request_pool_size
, c
->log
))) {
388 ngx_http_close_connection(c
);
392 if (ngx_array_init(&r
->cleanup
, r
->pool
, 5, sizeof(ngx_http_cleanup_t
))
395 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
396 ngx_http_close_connection(c
);
401 if (ngx_list_init(&r
->headers_out
.headers
, r
->pool
, 20,
402 sizeof(ngx_table_elt_t
)) == NGX_ERROR
)
404 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
405 ngx_http_close_connection(c
);
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
);
413 ngx_http_close_connection(c
);
417 c
->single_connection
= 1;
420 r
->file
.fd
= NGX_INVALID_FILE
;
422 r
->headers_in
.content_length_n
= -1;
423 r
->headers_in
.keep_alive_n
= -1;
424 r
->headers_out
.content_length_n
= -1;
425 r
->headers_out
.last_modified_time
= -1;
427 r
->http_state
= NGX_HTTP_READING_REQUEST_STATE
;
430 (*ngx_stat_reading
)++;
432 (*ngx_stat_requests
)++;
435 rev
->event_handler(rev
);
441 static void ngx_http_ssl_handshake(ngx_event_t
*rev
)
447 ngx_http_request_t
*r
;
452 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
453 "http check ssl handshake");
456 ngx_http_client_error(r
, 0, NGX_HTTP_REQUEST_TIME_OUT
);
460 n
= recv(c
->fd
, buf
, 1, MSG_PEEK
);
462 if (n
== -1 && ngx_socket_errno
== NGX_EAGAIN
) {
467 if (buf
[0] == 0x80 /* SSLv2 */ || buf
[0] == 0x16 /* SSLv3/TLSv1 */) {
468 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
469 "https ssl handshake: 0x%02Xd", buf
[0]);
471 c
->recv
= ngx_ssl_recv
;
472 c
->send_chain
= ngx_ssl_send_chain
;
474 rc
= ngx_ssl_handshake(c
);
476 if (rc
== NGX_ERROR
) {
477 ngx_http_close_request(r
, NGX_HTTP_BAD_REQUEST
);
478 ngx_http_close_connection(r
->connection
);
487 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
494 rev
->event_handler
= ngx_http_process_request_line
;
495 ngx_http_process_request_line(rev
);
501 static void ngx_http_process_request_line(ngx_event_t
*rev
)
506 ngx_http_request_t
*r
;
507 ngx_http_log_ctx_t
*ctx
;
512 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
513 "http process request line");
516 ngx_http_client_error(r
, 0, NGX_HTTP_REQUEST_TIME_OUT
);
524 if (rc
== NGX_AGAIN
) {
525 n
= ngx_http_read_request_header(r
);
527 if (n
== NGX_AGAIN
|| n
== NGX_ERROR
) {
532 rc
= ngx_http_parse_request_line(r
, r
->header_in
);
536 /* the request line has been parsed successfully */
538 r
->request_line
.len
= r
->request_end
- r
->request_start
;
539 r
->request_line
.data
= r
->request_start
;
543 r
->uri
.len
= r
->args_start
- 1 - r
->uri_start
;
545 r
->uri
.len
= r
->uri_end
- r
->uri_start
;
549 if (r
->complex_uri
|| r
->quoted_uri
) {
551 if (!(r
->uri
.data
= ngx_palloc(r
->pool
, r
->uri
.len
+ 1))) {
552 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
553 ngx_http_close_connection(c
);
557 rc
= ngx_http_parse_complex_uri(r
);
559 if (rc
== NGX_HTTP_INTERNAL_SERVER_ERROR
) {
560 ngx_http_close_request(r
, rc
);
561 ngx_http_close_connection(c
);
566 ngx_http_client_error(r
, rc
, NGX_HTTP_BAD_REQUEST
);
571 r
->uri
.data
= r
->uri_start
;
575 r
->unparsed_uri
.len
= r
->uri_end
- r
->uri_start
;
576 r
->unparsed_uri
.data
= r
->uri_start
;
579 if (r
->method
== 0) {
580 r
->method_name
.len
= r
->method_end
- r
->request_start
+ 1;
581 r
->method_name
.data
= r
->request_line
.data
;
585 if (r
->http_protocol
.data
) {
586 r
->http_protocol
.len
= r
->request_end
- r
->http_protocol
.data
;
592 r
->exten
.len
= r
->args_start
- 1 - r
->uri_ext
;
594 r
->exten
.len
= r
->uri_end
- r
->uri_ext
;
597 r
->exten
.data
= r
->uri_ext
;
601 if (r
->args_start
&& r
->uri_end
> r
->args_start
) {
602 r
->args
.len
= r
->uri_end
- r
->args_start
;
603 r
->args
.data
= r
->args_start
;
607 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
608 "http request line: \"%V\"", &r
->request_line
);
610 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
611 "http uri: \"%V\"", &r
->uri
);
613 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
614 "http args: \"%V\"", &r
->args
);
616 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
617 "http exten: \"%V\"", &r
->exten
);
622 if (r
->http_version
< NGX_HTTP_VERSION_10
) {
623 rev
->event_handler
= ngx_http_block_read
;
629 if (ngx_list_init(&r
->headers_in
.headers
, r
->pool
, 20,
630 sizeof(ngx_table_elt_t
)) == NGX_ERROR
)
632 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
633 ngx_http_close_connection(c
);
638 if (ngx_array_init(&r
->headers_in
.cookies
, r
->pool
, 5,
639 sizeof(ngx_table_elt_t
*)) == NGX_ERROR
)
641 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
642 ngx_http_close_connection(c
);
646 c
->log
->action
= "reading client request headers";
648 rev
->event_handler
= ngx_http_process_request_headers
;
649 ngx_http_process_request_headers(rev
);
653 } else if (rc
!= NGX_AGAIN
) {
655 /* there was error while a request line parsing */
657 ngx_http_client_error(r
, rc
, NGX_HTTP_BAD_REQUEST
);
660 for (p
= r
->request_start
; p
< r
->header_in
->last
; p
++) {
661 if (*p
== CR
|| *p
== LF
) {
666 r
->request_line
.len
= p
- r
->request_start
;
667 r
->request_line
.data
= r
->request_start
;
669 if (rc
== NGX_HTTP_PARSE_INVALID_METHOD
) {
670 r
->http_version
= NGX_HTTP_VERSION_10
;
673 ngx_http_client_error(r
, rc
,
674 (rc
== NGX_HTTP_PARSE_INVALID_METHOD
) ?
675 NGX_HTTP_NOT_IMPLEMENTED
:
676 NGX_HTTP_BAD_REQUEST
);
682 /* NGX_AGAIN: a request line parsing is still incomplete */
684 if (r
->header_in
->pos
== r
->header_in
->end
) {
686 rv
= ngx_http_alloc_large_header_buffer(r
, 1);
688 if (rv
== NGX_ERROR
) {
689 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
690 ngx_http_close_connection(c
);
694 if (rv
== NGX_DECLINED
) {
695 ngx_http_client_error(r
, NGX_HTTP_PARSE_TOO_LONG_URI
,
696 NGX_HTTP_REQUEST_URI_TOO_LARGE
);
704 static void ngx_http_process_request_headers(ngx_event_t
*rev
)
708 ngx_table_elt_t
*h
, **cookie
;
710 ngx_http_request_t
*r
;
715 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
716 "http process request header line");
719 ngx_http_client_error(r
, 0, NGX_HTTP_REQUEST_TIME_OUT
);
727 if (rc
== NGX_AGAIN
) {
729 if (r
->header_in
->pos
== r
->header_in
->end
) {
731 rv
= ngx_http_alloc_large_header_buffer(r
, 0);
733 if (rv
== NGX_ERROR
) {
734 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
735 ngx_http_close_connection(c
);
739 if (rv
== NGX_DECLINED
) {
740 ngx_http_client_error(r
, NGX_HTTP_PARSE_TOO_LONG_HEADER
,
741 NGX_HTTP_BAD_REQUEST
);
746 n
= ngx_http_read_request_header(r
);
748 if (n
== NGX_AGAIN
|| n
== NGX_ERROR
) {
753 rc
= ngx_http_parse_header_line(r
, r
->header_in
);
757 /* a header line has been parsed successfully */
761 if (!(h
= ngx_list_push(&r
->headers_in
.headers
))) {
762 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
763 ngx_http_close_connection(c
);
767 h
->key
.len
= r
->header_name_end
- r
->header_name_start
;
768 h
->key
.data
= r
->header_name_start
;
769 h
->key
.data
[h
->key
.len
] = '\0';
771 h
->value
.len
= r
->header_end
- r
->header_start
;
772 h
->value
.data
= r
->header_start
;
773 h
->value
.data
[h
->value
.len
] = '\0';
775 if (h
->key
.len
== sizeof("Cookie") - 1
776 && ngx_strcasecmp(h
->key
.data
, "Cookie") == 0)
778 if (!(cookie
= ngx_array_push(&r
->headers_in
.cookies
))) {
779 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
780 ngx_http_close_connection(c
);
788 for (i
= 0; ngx_http_headers_in
[i
].name
.len
!= 0; i
++) {
789 if (ngx_http_headers_in
[i
].name
.len
!= h
->key
.len
) {
793 if (ngx_strcasecmp(ngx_http_headers_in
[i
].name
.data
,
796 *((ngx_table_elt_t
**) ((char *) &r
->headers_in
797 + ngx_http_headers_in
[i
].offset
)) = h
;
803 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
804 "http header: \"%V: %V\"",
809 } else if (rc
== NGX_HTTP_PARSE_HEADER_DONE
) {
811 /* a whole header has been parsed successfully */
813 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
816 r
->request_length
+= r
->header_in
->pos
- r
->header_in
->start
;
818 r
->http_state
= NGX_HTTP_PROCESS_REQUEST_STATE
;
820 rc
= ngx_http_process_request_header(r
);
823 ngx_http_client_error(r
, rc
, NGX_HTTP_BAD_REQUEST
);
827 if (rev
->timer_set
) {
832 (*ngx_stat_reading
)--;
834 (*ngx_stat_writing
)++;
838 rev
->event_handler
= ngx_http_block_read
;
842 } else if (rc
!= NGX_AGAIN
) {
844 /* there was error while a header line parsing */
847 if (rc
== NGX_HTTP_PARSE_INVALID_HEADER
848 && (rev
->log
->log_level
& NGX_LOG_DEBUG_HTTP
))
851 for (p
= r
->header_name_start
;
852 p
< r
->header_in
->last
- 1;
860 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0,
861 "http invalid header: \"%s\"",
862 r
->header_name_start
);
866 ngx_http_client_error(r
, rc
, NGX_HTTP_BAD_REQUEST
);
870 /* NGX_AGAIN: a header line parsing is still not complete */
876 static ssize_t
ngx_http_read_request_header(ngx_http_request_t
*r
)
880 ngx_http_core_srv_conf_t
*cscf
;
882 rev
= r
->connection
->read
;
884 n
= r
->header_in
->last
- r
->header_in
->pos
;
894 n
= r
->connection
->recv(r
->connection
, r
->header_in
->last
,
895 r
->header_in
->end
- r
->header_in
->last
);
897 if (n
== NGX_AGAIN
) {
898 if (!r
->header_timeout_set
) {
899 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
900 ngx_add_timer(rev
, cscf
->client_header_timeout
);
901 r
->header_timeout_set
= 1;
904 if (ngx_handle_read_event(rev
, 0) == NGX_ERROR
) {
905 ngx_http_close_request(r
, NGX_HTTP_INTERNAL_SERVER_ERROR
);
906 ngx_http_close_connection(r
->connection
);
914 ngx_log_error(NGX_LOG_INFO
, r
->connection
->log
, 0,
915 "client closed prematurely connection");
918 if (n
== 0 || n
== NGX_ERROR
) {
919 ngx_http_close_request(r
, NGX_HTTP_BAD_REQUEST
);
920 ngx_http_close_connection(r
->connection
);
924 r
->header_in
->last
+= n
;
930 static ngx_int_t
ngx_http_alloc_large_header_buffer(ngx_http_request_t
*r
,
931 ngx_uint_t request_line
)
935 ngx_http_connection_t
*hc
;
936 ngx_http_core_srv_conf_t
*cscf
;
938 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
939 "http alloc large header buffer");
941 if (request_line
&& r
->state
== 0) {
943 /* the client fills up the buffer with "\r\n" */
945 r
->request_length
+= r
->header_in
->end
- r
->header_in
->start
;
947 r
->header_in
->pos
= r
->header_in
->start
;
948 r
->header_in
->last
= r
->header_in
->start
;
953 old
= request_line
? r
->request_start
: r
->header_name_start
;
955 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
958 && (size_t) (r
->header_in
->pos
- old
)
959 >= cscf
->large_client_header_buffers
.size
)
964 hc
= r
->http_connection
;
967 b
= hc
->free
[--hc
->nfree
];
969 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
970 "http large header free: %p %uz",
971 b
->pos
, b
->end
- b
->last
);
973 } else if (hc
->nbusy
< cscf
->large_client_header_buffers
.num
) {
975 if (hc
->busy
== NULL
) {
976 hc
->busy
= ngx_palloc(r
->connection
->pool
,
977 cscf
->large_client_header_buffers
.num
* sizeof(ngx_buf_t
*));
978 if (hc
->busy
== NULL
) {
983 b
= ngx_create_temp_buf(r
->connection
->pool
,
984 cscf
->large_client_header_buffers
.size
);
989 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
990 "http large header alloc: %p %uz",
991 b
->pos
, b
->end
- b
->last
);
997 hc
->busy
[hc
->nbusy
++] = b
;
1001 * r->state == 0 means that a header line was parsed successfully
1002 * and we do not need to copy incomplete header line and
1003 * to relocate the parser header pointers
1006 r
->request_length
+= r
->header_in
->end
- r
->header_in
->start
;
1013 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1014 "http large header copy: %d", r
->header_in
->pos
- old
);
1016 r
->request_length
+= old
- r
->header_in
->start
;
1020 ngx_memcpy(new, old
, r
->header_in
->pos
- old
);
1022 b
->pos
= new + (r
->header_in
->pos
- old
);
1023 b
->last
= new + (r
->header_in
->pos
- old
);
1026 r
->request_start
= new;
1028 if (r
->request_end
) {
1029 r
->request_end
= new + (r
->request_end
- old
);
1032 r
->method_end
= new + (r
->method_end
- old
);
1034 r
->uri_start
= new + (r
->uri_start
- old
);
1035 r
->uri_end
= new + (r
->uri_end
- old
);
1037 if (r
->schema_start
) {
1038 r
->schema_start
= new + (r
->schema_start
- old
);
1039 r
->schema_end
= new + (r
->schema_end
- old
);
1042 if (r
->host_start
) {
1043 r
->host_start
= new + (r
->host_start
- old
);
1044 r
->host_end
= new + (r
->host_end
- old
);
1047 if (r
->port_start
) {
1048 r
->port_start
= new + (r
->port_start
- old
);
1049 r
->port_end
= new + (r
->port_end
- old
);
1053 r
->uri_ext
= new + (r
->uri_ext
- old
);
1056 if (r
->args_start
) {
1057 r
->args_start
= new + (r
->args_start
- old
);
1061 r
->header_name_start
= new;
1062 r
->header_name_end
= new + (r
->header_name_end
- old
);
1063 r
->header_start
= new + (r
->header_start
- old
);
1064 r
->header_end
= new + (r
->header_end
- old
);
1073 static ngx_int_t
ngx_http_process_request_header(ngx_http_request_t
*r
)
1075 u_char
*ua
, *user_agent
, ch
;
1078 if (r
->headers_in
.host
) {
1079 for (len
= 0; len
< r
->headers_in
.host
->value
.len
; len
++) {
1080 ch
= r
->headers_in
.host
->value
.data
[len
];
1086 r
->headers_in
.host
->value
.data
[len
] = ngx_tolower(ch
);
1088 r
->headers_in
.host_name_len
= len
;
1090 if (ngx_http_find_virtual_server(r
) != NGX_OK
) {
1091 return NGX_HTTP_PARSE_INVALID_HOST
;
1095 if (r
->http_version
> NGX_HTTP_VERSION_10
) {
1096 return NGX_HTTP_PARSE_NO_HOST_HEADER
;
1098 r
->headers_in
.host_name_len
= 0;
1101 if (r
->headers_in
.content_length
) {
1102 r
->headers_in
.content_length_n
=
1103 ngx_atoi(r
->headers_in
.content_length
->value
.data
,
1104 r
->headers_in
.content_length
->value
.len
);
1106 if (r
->headers_in
.content_length_n
== NGX_ERROR
) {
1107 return NGX_HTTP_PARSE_INVALID_CL_HEADER
;
1111 if (r
->method
== NGX_HTTP_POST
&& r
->headers_in
.content_length_n
== -1) {
1112 return NGX_HTTP_PARSE_POST_WO_CL_HEADER
;
1115 if (r
->plain_http
) {
1116 return NGX_HTTP_PARSE_HTTP_TO_HTTPS
;
1119 if (r
->headers_in
.connection
) {
1120 if (r
->headers_in
.connection
->value
.len
== 5
1121 && ngx_strcasecmp(r
->headers_in
.connection
->value
.data
, "close")
1124 r
->headers_in
.connection_type
= NGX_HTTP_CONNECTION_CLOSE
;
1126 } else if (r
->headers_in
.connection
->value
.len
== 10
1127 && ngx_strcasecmp(r
->headers_in
.connection
->value
.data
,
1130 r
->headers_in
.connection_type
= NGX_HTTP_CONNECTION_KEEP_ALIVE
;
1132 if (r
->headers_in
.keep_alive
) {
1133 r
->headers_in
.keep_alive_n
=
1134 ngx_atoi(r
->headers_in
.keep_alive
->value
.data
,
1135 r
->headers_in
.keep_alive
->value
.len
);
1140 if (r
->headers_in
.user_agent
) {
1143 * check some widespread browsers while the headers are still
1147 user_agent
= r
->headers_in
.user_agent
->value
.data
;
1149 ua
= (u_char
*) ngx_strstr(user_agent
, "MSIE");
1151 if (ua
&& ua
+ 8 < user_agent
+ r
->headers_in
.user_agent
->value
.len
) {
1153 r
->headers_in
.msie
= 1;
1155 if (ua
[4] == ' ' && ua
[5] == '4' && ua
[6] == '.') {
1156 r
->headers_in
.msie4
= 1;
1160 /* MSIE ignores the SSL "close notify" alert */
1162 r
->connection
->ssl
->no_send_shut
= 1;
1167 if (ngx_strstr(user_agent
, "Opera")) {
1168 r
->headers_in
.opera
= 1;
1169 r
->headers_in
.msie
= 0;
1170 r
->headers_in
.msie4
= 0;
1173 if (!r
->headers_in
.msie
&& !r
->headers_in
.opera
) {
1175 if (ngx_strstr(user_agent
, "Gecko/")) {
1176 r
->headers_in
.gecko
= 1;
1178 } else if (ngx_strstr(user_agent
, "Konqueror")) {
1179 r
->headers_in
.konqueror
= 1;
1188 static ngx_int_t
ngx_http_find_virtual_server(ngx_http_request_t
*r
)
1191 ngx_uint_t i
, n
, key
, found
;
1192 ngx_http_server_name_t
*name
;
1193 ngx_http_core_main_conf_t
*cmcf
;
1194 ngx_http_core_srv_conf_t
*cscf
;
1195 ngx_http_core_loc_conf_t
*clcf
;
1197 if (r
->virtual_names
->hash
) {
1198 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
1200 ngx_http_server_names_hash_key(key
,
1201 r
->headers_in
.host
->value
.data
,
1202 r
->headers_in
.host_name_len
,
1203 cmcf
->server_names_hash
);
1205 name
= r
->virtual_names
->hash
[key
].elts
;
1206 n
= r
->virtual_names
->hash
[key
].nelts
;
1209 name
= r
->virtual_names
->names
.elts
;
1210 n
= r
->virtual_names
->names
.nelts
;
1215 for (i
= 0; i
< n
; i
++) {
1217 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1218 "server name: %V", &name
[i
].name
);
1220 if (r
->headers_in
.host_name_len
!= name
[i
].name
.len
) {
1224 rc
= ngx_strncmp(r
->headers_in
.host
->value
.data
,
1225 name
[i
].name
.data
, name
[i
].name
.len
);
1228 r
->server_name
= name
[i
].name
;
1235 /* the server names are lexicographically sorted */
1240 if (!found
&& r
->virtual_names
->wildcards
.nelts
) {
1242 name
= r
->virtual_names
->wildcards
.elts
;
1243 for (i
= 0; i
< r
->virtual_names
->wildcards
.nelts
; i
++) {
1245 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1246 "server name: %V", &name
[i
].name
);
1248 if (r
->headers_in
.host_name_len
<= name
[i
].name
.len
) {
1252 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1254 r
->headers_in
.host
->value
.data
1255 + (r
->headers_in
.host_name_len
- name
[i
].name
.len
));
1257 if (ngx_strncmp(r
->headers_in
.host
->value
.data
1258 + (r
->headers_in
.host_name_len
- name
[i
].name
.len
),
1259 name
[i
].name
.data
, name
[i
].name
.len
) == 0)
1261 r
->server_name
.len
= r
->headers_in
.host_name_len
;
1262 r
->server_name
.data
= r
->headers_in
.host
->value
.data
;
1271 r
->srv_conf
= name
[i
].core_srv_conf
->ctx
->srv_conf
;
1272 r
->loc_conf
= name
[i
].core_srv_conf
->ctx
->loc_conf
;
1274 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1275 r
->connection
->log
->file
= clcf
->err_log
->file
;
1277 if (!(r
->connection
->log
->log_level
& NGX_LOG_DEBUG_CONNECTION
)) {
1278 r
->connection
->log
->log_level
= clcf
->err_log
->log_level
;
1284 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
1286 if (cscf
->restrict_host_names
!= NGX_HTTP_RESTRICT_HOST_OFF
) {
1294 void ngx_http_finalize_request(ngx_http_request_t
*r
, int rc
)
1296 ngx_http_core_loc_conf_t
*clcf
;
1298 /* r may be already destroyed when rc == NGX_DONE */
1300 if (rc
== NGX_DONE
|| r
->main
) {
1304 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1305 "http finalize request: %d", rc
);
1307 if (rc
>= NGX_HTTP_SPECIAL_RESPONSE
) {
1309 if (r
->connection
->read
->timer_set
) {
1310 ngx_del_timer(r
->connection
->read
);
1313 if (r
->connection
->write
->timer_set
) {
1314 ngx_del_timer(r
->connection
->write
);
1317 if (rc
== NGX_HTTP_CLIENT_CLOSED_REQUEST
|| r
->closed
) {
1318 ngx_http_close_request(r
, 0);
1319 ngx_http_close_connection(r
->connection
);
1323 ngx_http_finalize_request(r
, ngx_http_special_response_handler(r
, rc
));
1327 } else if (rc
== NGX_ERROR
) {
1328 ngx_http_close_request(r
, 0);
1329 ngx_http_close_connection(r
->connection
);
1332 } else if (rc
== NGX_AGAIN
) {
1333 ngx_http_set_write_handler(r
);
1337 if (r
->connection
->read
->timer_set
) {
1338 ngx_del_timer(r
->connection
->read
);
1341 if (r
->connection
->write
->timer_set
) {
1342 r
->connection
->write
->delayed
= 0;
1343 ngx_del_timer(r
->connection
->write
);
1346 if (r
->connection
->read
->pending_eof
) {
1347 #if (NGX_HAVE_KQUEUE)
1348 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
,
1349 r
->connection
->read
->kq_errno
,
1350 "kevent() reported about an closed connection");
1352 ngx_http_close_request(r
, 0);
1353 ngx_http_close_connection(r
->connection
);
1357 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1361 && r
->keepalive
!= 0
1362 && clcf
->keepalive_timeout
> 0)
1364 ngx_http_set_keepalive(r
);
1367 } else if (r
->lingering_close
&& clcf
->lingering_timeout
> 0) {
1368 ngx_http_set_lingering_close(r
);
1372 ngx_http_close_request(r
, 0);
1373 ngx_http_close_connection(r
->connection
);
1377 static void ngx_http_set_write_handler(ngx_http_request_t
*r
)
1380 ngx_http_core_loc_conf_t
*clcf
;
1382 wev
= r
->connection
->write
;
1383 wev
->event_handler
= ngx_http_writer
;
1385 r
->http_state
= NGX_HTTP_WRITING_REQUEST_STATE
;
1387 if (wev
->ready
&& wev
->delayed
) {
1391 clcf
= ngx_http_get_module_loc_conf(r
->main
? r
->main
: r
,
1392 ngx_http_core_module
);
1393 if (!wev
->delayed
) {
1394 ngx_add_timer(wev
, clcf
->send_timeout
);
1397 if (ngx_handle_write_event(wev
, clcf
->send_lowat
) == NGX_ERROR
) {
1398 ngx_http_close_request(r
, 0);
1399 ngx_http_close_connection(r
->connection
);
1406 void ngx_http_writer(ngx_event_t
*wev
)
1409 ngx_connection_t
*c
;
1410 ngx_http_request_t
*r
;
1411 ngx_http_core_loc_conf_t
*clcf
;
1413 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, wev
->log
, 0, "http writer handler");
1418 if (wev
->timedout
) {
1419 if (!wev
->delayed
) {
1420 ngx_http_client_error(r
, 0, NGX_HTTP_REQUEST_TIME_OUT
);
1428 clcf
= ngx_http_get_module_loc_conf(r
->main
? r
->main
: r
,
1429 ngx_http_core_module
);
1430 ngx_add_timer(wev
, clcf
->send_timeout
);
1432 if (ngx_handle_write_event(wev
, clcf
->send_lowat
) == NGX_ERROR
) {
1433 ngx_http_close_request(r
, 0);
1434 ngx_http_close_connection(r
->connection
);
1442 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, wev
->log
, 0,
1443 "http writer delayed");
1445 clcf
= ngx_http_get_module_loc_conf(r
->main
? r
->main
: r
,
1446 ngx_http_core_module
);
1448 if (ngx_handle_write_event(wev
, clcf
->send_lowat
) == NGX_ERROR
) {
1449 ngx_http_close_request(r
, 0);
1450 ngx_http_close_connection(r
->connection
);
1457 rc
= ngx_http_output_filter(r
, NULL
);
1459 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1460 "http writer output filter: %d", rc
);
1462 if (rc
== NGX_AGAIN
) {
1463 clcf
= ngx_http_get_module_loc_conf(r
->main
? r
->main
: r
,
1464 ngx_http_core_module
);
1465 if (!wev
->ready
&& !wev
->delayed
) {
1466 ngx_add_timer(wev
, clcf
->send_timeout
);
1469 if (ngx_handle_write_event(wev
, clcf
->send_lowat
) == NGX_ERROR
) {
1470 ngx_http_close_request(r
, 0);
1471 ngx_http_close_connection(r
->connection
);
1477 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "http writer done");
1479 ngx_http_finalize_request(r
, rc
);
1483 static void ngx_http_block_read(ngx_event_t
*rev
)
1485 ngx_connection_t
*c
;
1486 ngx_http_request_t
*r
;
1488 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0, "http read blocked");
1490 /* aio does not call this handler */
1492 if ((ngx_event_flags
& NGX_USE_LEVEL_EVENT
) && rev
->active
) {
1493 if (ngx_del_event(rev
, NGX_READ_EVENT
, 0) == NGX_ERROR
) {
1496 ngx_http_close_request(r
, 0);
1497 ngx_http_close_connection(c
);
1503 ngx_int_t
ngx_http_discard_body(ngx_http_request_t
*r
)
1508 rev
= r
->connection
->read
;
1510 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, rev
->log
, 0, "http set discard body");
1512 if (rev
->timer_set
) {
1516 if (r
->headers_in
.content_length_n
<= 0) {
1520 size
= r
->header_in
->last
- r
->header_in
->pos
;
1523 if (r
->headers_in
.content_length_n
> size
) {
1524 r
->headers_in
.content_length_n
-= size
;
1527 r
->header_in
->pos
+= r
->headers_in
.content_length_n
;
1528 r
->headers_in
.content_length_n
= 0;
1533 rev
->event_handler
= ngx_http_read_discarded_body_event
;
1535 if (ngx_handle_level_read_event(rev
) == NGX_ERROR
) {
1536 return NGX_HTTP_INTERNAL_SERVER_ERROR
;
1539 return ngx_http_read_discarded_body(r
);
1543 static void ngx_http_read_discarded_body_event(ngx_event_t
*rev
)
1546 ngx_connection_t
*c
;
1547 ngx_http_request_t
*r
;
1552 rc
= ngx_http_read_discarded_body(r
);
1554 if (rc
== NGX_AGAIN
) {
1555 if (ngx_handle_level_read_event(rev
) == NGX_ERROR
) {
1556 ngx_http_close_request(r
, rc
);
1557 ngx_http_close_connection(c
);
1563 ngx_http_close_request(r
, rc
);
1564 ngx_http_close_connection(c
);
1569 static ngx_int_t
ngx_http_read_discarded_body(ngx_http_request_t
*r
)
1572 u_char buffer
[NGX_HTTP_DISCARD_BUFFER_SIZE
];
1574 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
1575 "http read discarded body");
1577 if (r
->headers_in
.content_length_n
== 0) {
1582 size
= r
->headers_in
.content_length_n
;
1584 if (size
> NGX_HTTP_DISCARD_BUFFER_SIZE
) {
1585 size
= NGX_HTTP_DISCARD_BUFFER_SIZE
;
1588 n
= r
->connection
->recv(r
->connection
, buffer
, size
);
1590 if (n
== NGX_ERROR
) {
1595 * if a client request body is discarded then we already set
1596 * some HTTP response code for client and we can ignore the error
1602 if (n
== NGX_AGAIN
) {
1606 r
->headers_in
.content_length_n
-= n
;
1612 static void ngx_http_set_keepalive(ngx_http_request_t
*r
)
1617 ngx_event_t
*rev
, *wev
;
1618 ngx_connection_t
*c
;
1619 ngx_http_connection_t
*hc
;
1620 ngx_http_core_srv_conf_t
*cscf
;
1621 ngx_http_core_loc_conf_t
*clcf
;
1626 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "set http keepalive handler");
1628 c
->log
->action
= "closing request";
1630 hc
= r
->http_connection
;
1633 if (b
->pos
< b
->last
) {
1635 /* the pipelined request */
1637 if (b
!= c
->buffer
) {
1640 * If the large header buffers were allocated while the previous
1641 * request processing then we do not use c->buffer for
1642 * the pipelined request (see ngx_http_init_request()).
1644 * Now we would move the large header buffers to the free list.
1647 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
1649 if (hc
->free
== NULL
) {
1650 hc
->free
= ngx_palloc(c
->pool
,
1651 cscf
->large_client_header_buffers
.num
* sizeof(ngx_buf_t
*));
1653 if (hc
->free
== NULL
) {
1654 ngx_http_close_request(r
, 0);
1655 ngx_http_close_connection(c
);
1660 for (i
= 0; i
< hc
->nbusy
- 1; i
++) {
1662 hc
->free
[hc
->nfree
++] = f
;
1672 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1674 ngx_http_close_request(r
, 0);
1677 ngx_add_timer(rev
, clcf
->keepalive_timeout
);
1679 if (ngx_handle_level_read_event(rev
) == NGX_ERROR
) {
1680 ngx_http_close_connection(c
);
1685 wev
->event_handler
= ngx_http_empty_handler
;
1687 if (b
->pos
< b
->last
) {
1689 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "pipelined request");
1692 c
->log
->action
= "reading client pipelined request line";
1693 ngx_http_init_request(rev
);
1700 * To keep a memory footprint as small as possible for an idle
1701 * keepalive connection we try to free the ngx_http_request_t and
1702 * c->buffer's memory if they were allocated outside the c->pool.
1703 * The large header buffers are always allocated outside the c->pool and
1707 if (ngx_pfree(c
->pool
, r
) == NGX_OK
) {
1713 if (ngx_pfree(c
->pool
, b
->start
) == NGX_OK
) {
1716 * the special note for ngx_http_keepalive_handler() that
1717 * c->buffer's memory was freed
1727 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "hc free: %p %d",
1728 hc
->free
, hc
->nfree
);
1731 for (i
= 0; i
< hc
->nfree
; i
++) {
1732 ngx_pfree(c
->pool
, hc
->free
[i
]);
1739 ngx_log_debug2(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "hc busy: %p %d",
1740 hc
->busy
, hc
->nbusy
);
1743 for (i
= 0; i
< hc
->nbusy
; i
++) {
1744 ngx_pfree(c
->pool
, hc
->busy
[i
]);
1751 rev
->event_handler
= ngx_http_keepalive_handler
;
1754 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
1755 if (ngx_del_event(wev
, NGX_WRITE_EVENT
, NGX_DISABLE_EVENT
)
1758 ngx_http_close_connection(c
);
1762 } else if (ngx_event_flags
& NGX_USE_LEVEL_EVENT
) {
1763 if (ngx_del_event(wev
, NGX_WRITE_EVENT
, 0) == NGX_ERROR
) {
1764 ngx_http_close_connection(c
);
1770 c
->log
->action
= "keepalive";
1772 if (c
->tcp_nopush
== NGX_TCP_NOPUSH_SET
) {
1773 if (ngx_tcp_push(c
->fd
) == NGX_ERROR
) {
1774 ngx_connection_error(c
, ngx_socket_errno
, ngx_tcp_push_n
" failed");
1775 ngx_http_close_connection(c
);
1779 c
->tcp_nopush
= NGX_TCP_NOPUSH_UNSET
;
1780 tcp_nodelay
= ngx_tcp_nodelay_and_tcp_nopush
? 1 : 0;
1787 && clcf
->tcp_nodelay
1788 && c
->tcp_nodelay
== NGX_TCP_NODELAY_UNSET
)
1790 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "tcp_nodelay");
1792 if (setsockopt(c
->fd
, IPPROTO_TCP
, TCP_NODELAY
,
1793 (const void *) &tcp_nodelay
, sizeof(int)) == -1)
1795 ngx_connection_error(c
, ngx_socket_errno
,
1796 "setsockopt(TCP_NODELAY) failed");
1797 ngx_http_close_connection(c
);
1801 c
->tcp_nodelay
= NGX_TCP_NODELAY_SET
;
1805 /* if ngx_http_request_t was freed then we need some other place */
1806 r
->http_state
= NGX_HTTP_KEEPALIVE_STATE
;
1810 ngx_http_keepalive_handler(rev
);
1815 static void ngx_http_keepalive_handler(ngx_event_t
*rev
)
1820 ngx_connection_t
*c
;
1821 ngx_http_connection_t
*hc
;
1825 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "http keepalive handler");
1827 if (rev
->timedout
) {
1828 ngx_http_close_connection(c
);
1832 #if (NGX_HAVE_KQUEUE)
1834 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
1835 if (rev
->pending_eof
) {
1836 c
->log
->handler
= NULL
;
1837 ngx_log_error(NGX_LOG_INFO
, c
->log
, rev
->kq_errno
,
1838 "kevent() reported that client %V closed "
1839 "keepalive connection", &c
->addr_text
);
1842 c
->ssl
->no_send_shut
= 1;
1845 ngx_http_close_connection(c
);
1854 size
= b
->end
- b
->start
;
1856 if (b
->pos
== NULL
) {
1859 * The c->buffer's memory was freed by ngx_http_set_keepalive().
1860 * However, the c->buffer->start and c->buffer->end were not changed
1861 * to keep the buffer size.
1864 if (!(b
->pos
= ngx_palloc(c
->pool
, size
))) {
1865 ngx_http_close_connection(c
);
1871 b
->end
= b
->pos
+ size
;
1875 * MSIE closes a keepalive connection with RST flag
1876 * so we ignore ECONNRESET here.
1879 c
->log_error
= NGX_ERROR_IGNORE_ECONNRESET
;
1880 ngx_set_socket_errno(0);
1882 n
= c
->recv(c
, b
->last
, size
);
1883 c
->log_error
= NGX_ERROR_INFO
;
1885 if (n
== NGX_AGAIN
) {
1886 if (ngx_handle_level_read_event(rev
) == NGX_ERROR
) {
1887 ngx_http_close_connection(c
);
1893 if (n
== NGX_ERROR
) {
1894 ngx_http_close_connection(c
);
1898 c
->log
->handler
= NULL
;
1901 ngx_log_error(NGX_LOG_INFO
, c
->log
, ngx_socket_errno
,
1902 "client %V closed keepalive connection", &c
->addr_text
);
1903 ngx_http_close_connection(c
);
1909 c
->log
->handler
= ngx_http_log_error
;
1910 c
->log
->action
= "reading client request line";
1912 ngx_http_init_request(rev
);
1916 static void ngx_http_set_lingering_close(ngx_http_request_t
*r
)
1918 ngx_event_t
*rev
, *wev
;
1919 ngx_connection_t
*c
;
1920 ngx_http_core_loc_conf_t
*clcf
;
1924 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1927 rev
->event_handler
= ngx_http_lingering_close_handler
;
1929 r
->lingering_time
= ngx_time() + clcf
->lingering_time
/ 1000;
1930 ngx_add_timer(rev
, clcf
->lingering_timeout
);
1932 if (ngx_handle_level_read_event(rev
) == NGX_ERROR
) {
1933 ngx_http_close_request(r
, 0);
1934 ngx_http_close_connection(c
);
1939 wev
->event_handler
= ngx_http_empty_handler
;
1942 if (ngx_event_flags
& NGX_USE_KQUEUE_EVENT
) {
1943 if (ngx_del_event(wev
, NGX_WRITE_EVENT
, NGX_DISABLE_EVENT
)
1946 ngx_http_close_request(r
, 0);
1947 ngx_http_close_connection(c
);
1951 } else if (ngx_event_flags
& NGX_USE_LEVEL_EVENT
) {
1952 if (ngx_del_event(wev
, NGX_WRITE_EVENT
, 0) == NGX_ERROR
) {
1953 ngx_http_close_request(r
, 0);
1954 ngx_http_close_connection(c
);
1960 if (ngx_shutdown_socket(c
->fd
, NGX_WRITE_SHUTDOWN
) == -1) {
1961 ngx_connection_error(c
, ngx_socket_errno
,
1962 ngx_shutdown_socket_n
" failed");
1963 ngx_http_close_request(r
, 0);
1964 ngx_http_close_connection(c
);
1969 ngx_http_lingering_close_handler(rev
);
1974 static void ngx_http_lingering_close_handler(ngx_event_t
*rev
)
1978 ngx_connection_t
*c
;
1979 ngx_http_request_t
*r
;
1980 ngx_http_core_loc_conf_t
*clcf
;
1981 u_char buffer
[NGX_HTTP_LINGERING_BUFFER_SIZE
];
1986 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
1987 "http lingering close handler");
1989 if (rev
->timedout
) {
1990 ngx_http_close_request(r
, 0);
1991 ngx_http_close_connection(c
);
1995 timer
= r
->lingering_time
- ngx_time();
1997 ngx_http_close_request(r
, 0);
1998 ngx_http_close_connection(c
);
2003 n
= c
->recv(c
, buffer
, NGX_HTTP_LINGERING_BUFFER_SIZE
);
2005 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0, "lingering read: %d", n
);
2007 if (n
== NGX_ERROR
|| n
== 0) {
2008 ngx_http_close_request(r
, 0);
2009 ngx_http_close_connection(c
);
2013 } while (rev
->ready
);
2015 if (ngx_handle_level_read_event(rev
) == NGX_ERROR
) {
2016 ngx_http_close_request(r
, 0);
2017 ngx_http_close_connection(c
);
2021 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
2025 if (timer
> clcf
->lingering_timeout
) {
2026 timer
= clcf
->lingering_timeout
;
2029 ngx_add_timer(rev
, timer
);
2033 void ngx_http_empty_handler(ngx_event_t
*wev
)
2035 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, wev
->log
, 0, "http empty handler");
2041 ngx_int_t
ngx_http_send_last(ngx_http_request_t
*r
)
2046 if (!(b
= ngx_calloc_buf(r
->pool
))) {
2054 return ngx_http_output_filter(r
, &out
);
2058 void ngx_http_close_request(ngx_http_request_t
*r
, int error
)
2062 ngx_http_log_ctx_t
*ctx
;
2063 ngx_http_cleanup_t
*cleanup
;
2064 ngx_http_core_loc_conf_t
*clcf
;
2067 log
= r
->connection
->log
;
2069 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, log
, 0, "http close request");
2071 if (r
->pool
== NULL
) {
2072 ngx_log_error(NGX_LOG_ALERT
, log
, 0,
2073 "http request already closed");
2078 if (r
->stat_reading
) {
2079 (*ngx_stat_reading
)--;
2082 if (r
->stat_writing
) {
2083 (*ngx_stat_writing
)--;
2087 if (error
&& r
->headers_out
.status
== 0) {
2088 r
->headers_out
.status
= error
;
2091 ngx_http_log_handler(r
);
2093 cleanup
= r
->cleanup
.elts
;
2094 for (i
= 0; i
< r
->cleanup
.nelts
; i
++) {
2095 if (!cleanup
[i
].valid
) {
2099 #if (NGX_HTTP_CACHE)
2101 if (cleanup
[i
].cache
) {
2102 ngx_http_cache_unlock(cleanup
[i
].data
.cache
.hash
,
2103 cleanup
[i
].data
.cache
.cache
, log
);
2109 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, log
, 0, "http cleanup fd: %d",
2110 cleanup
[i
].data
.file
.fd
);
2112 if (ngx_close_file(cleanup
[i
].data
.file
.fd
) == NGX_FILE_ERROR
) {
2113 ngx_log_error(NGX_LOG_ALERT
, log
, ngx_errno
,
2114 ngx_close_file_n
" \"%s\" failed",
2115 cleanup
[i
].data
.file
.name
);
2120 if (r
->file
.fd
!= NGX_INVALID_FILE
) {
2121 if (ngx_close_file(r
->file
.fd
) == NGX_FILE_ERROR
) {
2122 ngx_log_error(NGX_LOG_ALERT
, log
, ngx_errno
,
2123 ngx_close_file_n
" \"%V\" failed", &r
->file
.name
);
2128 && r
->request_body
->temp_file
2129 && r
->request_body
->temp_file
->file
.fd
!= NGX_INVALID_FILE
)
2131 if (ngx_close_file(r
->request_body
->temp_file
->file
.fd
)
2134 ngx_log_error(NGX_LOG_ALERT
, log
, ngx_errno
,
2135 ngx_close_file_n
" deleted file \"%V\" failed",
2136 &r
->request_body
->temp_file
->file
.name
);
2140 if (r
->connection
->timedout
) {
2141 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
2143 if (clcf
->reset_timedout_connection
) {
2147 if (setsockopt(r
->connection
->fd
, SOL_SOCKET
, SO_LINGER
,
2148 (const void *) &l
, sizeof(struct linger
)) == -1)
2150 ngx_log_error(NGX_LOG_ALERT
, log
, ngx_socket_errno
,
2151 "setsockopt(SO_LINGER) failed");
2156 /* the variuos request strings were allocated from r->pool */
2158 ctx
->request
= NULL
;
2160 r
->request_line
.len
= 0;
2162 ngx_destroy_pool(r
->pool
);
2168 void ngx_ssl_close_handler(ngx_event_t
*ev
)
2170 ngx_connection_t
*c
;
2174 ngx_log_debug0(NGX_LOG_DEBUG_HTTP
, ev
->log
, 0, "http ssl close handler");
2176 if (ngx_ssl_shutdown(c
) == NGX_AGAIN
) {
2180 ngx_http_close_connection(c
);
2186 void ngx_http_close_connection(ngx_connection_t
*c
)
2190 ngx_log_debug1(NGX_LOG_DEBUG_HTTP
, c
->log
, 0,
2191 "close http connection: %d", c
->fd
);
2196 if (ngx_ssl_shutdown(c
) == NGX_AGAIN
) {
2197 c
->read
->event_handler
= ngx_ssl_close_handler
;
2198 c
->write
->event_handler
= ngx_ssl_close_handler
;
2206 (*ngx_stat_active
)--;
2211 ngx_close_connection(c
);
2213 ngx_destroy_pool(c
->pool
);
2217 static void ngx_http_client_error(ngx_http_request_t
*r
,
2218 int client_error
, int error
)
2221 ngx_http_log_ctx_t
*ctx
;
2222 ngx_http_core_srv_conf_t
*cscf
;
2224 ctx
= r
->connection
->log
->data
;
2226 if (error
== NGX_HTTP_REQUEST_TIME_OUT
) {
2227 ngx_log_error(NGX_LOG_INFO
, r
->connection
->log
, NGX_ETIMEDOUT
,
2228 "client timed out");
2229 r
->connection
->timedout
= 1;
2230 ngx_http_close_request(r
, error
);
2231 ngx_http_close_connection(r
->connection
);
2235 r
->connection
->log
->handler
= NULL
;
2239 switch (client_error
) {
2241 case NGX_HTTP_PARSE_INVALID_HOST
:
2242 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
2243 "client %V sent invalid \"Host\" header \"%V\", URL: \"%V\"",
2244 ctx
->client
, &r
->headers_in
.host
->value
,
2245 &ctx
->request
->unparsed_uri
);
2247 error
= NGX_HTTP_INVALID_HOST
;
2249 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
2251 if (cscf
->restrict_host_names
== NGX_HTTP_RESTRICT_HOST_CLOSE
) {
2252 ngx_http_close_request(r
, error
);
2253 ngx_http_close_connection(r
->connection
);
2259 case NGX_HTTP_PARSE_HTTP_TO_HTTPS
:
2260 error
= NGX_HTTP_TO_HTTPS
;
2261 if (ctx
->request
->headers_in
.referer
) {
2262 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
2263 "client %V sent plain HTTP request to HTTPS port, "
2264 "URL: \"%V\", referrer \"%V\"",
2265 ctx
->client
, &ctx
->request
->unparsed_uri
,
2266 &ctx
->request
->headers_in
.referer
->value
);
2269 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
2270 "client %V sent plain HTTP request to HTTPS port, "
2271 "URL: \"%V\"", ctx
->client
, &ctx
->request
->unparsed_uri
);
2277 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
2278 client_header_errors
[client_error
- NGX_HTTP_CLIENT_ERROR
],
2279 ctx
->client
, &ctx
->request
->unparsed_uri
);
2284 if (error
== NGX_HTTP_REQUEST_URI_TOO_LARGE
) {
2285 r
->request_line
.len
= r
->header_in
->end
- r
->request_start
;
2286 r
->request_line
.data
= r
->request_start
;
2289 if (r
->request_line
.data
== NULL
) {
2290 for (p
= r
->request_start
; p
< r
->header_in
->last
; p
++) {
2291 if (*p
== CR
|| *p
== LF
) {
2296 r
->request_line
.len
= p
- r
->request_start
;
2297 r
->request_line
.data
= r
->request_start
;
2301 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
2302 client_header_errors
[client_error
- NGX_HTTP_CLIENT_ERROR
],
2303 ctx
->client
, &r
->request_line
);
2306 r
->connection
->log
->handler
= ngx_http_log_error
;
2308 ngx_http_finalize_request(r
, error
);
2312 static u_char
*ngx_http_log_error(ngx_log_t
*log
, u_char
*buf
, size_t len
)
2315 ngx_http_log_ctx_t
*ctx
;
2322 p
= ngx_snprintf(p
, len
, " while %s", log
->action
);
2326 p
= ngx_snprintf(p
, len
, ", client: %V", ctx
->client
);
2328 if (ctx
->request
== NULL
) {
2334 p
= ngx_snprintf(p
, len
, ", URL: \"%V\"", &ctx
->request
->unparsed_uri
);
2336 if (ctx
->request
->headers_in
.referer
== NULL
) {
2342 return ngx_snprintf(p
, len
, ", referrer: \"%V\"",
2343 &ctx
->request
->headers_in
.referer
->value
);