blob: 417f3dfa7adf2cc91a8453b6f4ae1183d462463b [file] [log] [blame]
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Igor Sysoevd90282d2004-09-28 08:34:51 +00004 */
5
6
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00007#include <ngx_config.h>
Igor Sysoev0ad17c02002-08-26 15:18:19 +00008#include <ngx_core.h>
Igor Sysoevfcce8d52003-01-23 18:47:54 +00009#include <ngx_event.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000010#include <ngx_http.h>
11
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000012
Igor Sysoev6b863e32003-05-12 15:52:24 +000013static void ngx_http_init_request(ngx_event_t *ev);
14static void ngx_http_process_request_line(ngx_event_t *rev);
15static void ngx_http_process_request_headers(ngx_event_t *rev);
Igor Sysoev6b863e32003-05-12 15:52:24 +000016static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
Igor Sysoevf7abd722004-09-23 06:32:00 +000017static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
Igor Sysoevc1571722005-03-19 12:38:37 +000018 ngx_uint_t request_line);
Igor Sysoev899b44e2005-05-12 14:58:06 +000019
20static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
21 ngx_table_elt_t *h, ngx_uint_t offset);
Igor Sysoevb145b062005-06-15 18:33:41 +000022static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
23 ngx_table_elt_t *h, ngx_uint_t offset);
Igor Sysoev899b44e2005-05-12 14:58:06 +000024static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r,
25 ngx_table_elt_t *h, ngx_uint_t offset);
26
Igor Sysoev2f657222004-06-16 15:32:11 +000027static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
Igor Sysoev3338cfd2006-05-11 14:43:47 +000028static void ngx_http_find_virtual_server(ngx_http_request_t *r,
29 ngx_http_virtual_names_t *vn, ngx_uint_t hash);
Igor Sysoev6b863e32003-05-12 15:52:24 +000030
Igor Sysoev899b44e2005-05-12 14:58:06 +000031static void ngx_http_request_handler(ngx_event_t *ev);
Igor Sysoev85ef94b2005-06-23 13:41:06 +000032static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
Igor Sysoev899b44e2005-05-12 14:58:06 +000033static void ngx_http_writer(ngx_http_request_t *r);
Igor Sysoev6b863e32003-05-12 15:52:24 +000034
Igor Sysoev899b44e2005-05-12 14:58:06 +000035static void ngx_http_block_read(ngx_http_request_t *r);
Igor Sysoevd581fd52003-05-13 16:02:32 +000036static void ngx_http_set_keepalive(ngx_http_request_t *r);
37static void ngx_http_keepalive_handler(ngx_event_t *ev);
38static void ngx_http_set_lingering_close(ngx_http_request_t *r);
39static void ngx_http_lingering_close_handler(ngx_event_t *ev);
Igor Sysoevc2807ec2006-02-16 15:26:46 +000040static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
Igor Sysoev90c08142005-07-25 09:41:38 +000041static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
Igor Sysoev9ac946b2005-10-24 15:09:41 +000042static void ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error);
Igor Sysoev90c08142005-07-25 09:41:38 +000043static void ngx_http_close_connection(ngx_connection_t *c);
Igor Sysoevd581fd52003-05-13 16:02:32 +000044
Igor Sysoeve5a222c2005-01-25 12:27:35 +000045static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
Igor Sysoevbb28b6d2006-07-11 13:20:19 +000046static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
47 ngx_http_request_t *sr, u_char *buf, size_t len);
Igor Sysoev0ad17c02002-08-26 15:18:19 +000048
Igor Sysoevceb99292005-09-06 16:09:32 +000049#if (NGX_HTTP_SSL)
50static void ngx_http_ssl_handshake(ngx_event_t *rev);
Igor Sysoev9fa5a822005-09-30 14:41:25 +000051static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
Igor Sysoevceb99292005-09-06 16:09:32 +000052#endif
53
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000054
Igor Sysoevc04deca2005-03-28 14:43:02 +000055static char *ngx_http_client_errors[] = {
Igor Sysoev0ad17c02002-08-26 15:18:19 +000056
Igor Sysoevc04deca2005-03-28 14:43:02 +000057 /* NGX_HTTP_PARSE_INVALID_METHOD */
58 "client sent invalid method",
Igor Sysoev6a644c62003-03-04 06:33:48 +000059
Igor Sysoevc04deca2005-03-28 14:43:02 +000060 /* NGX_HTTP_PARSE_INVALID_REQUEST */
61 "client sent invalid request",
62
63 /* NGX_HTTP_PARSE_INVALID_09_METHOD */
64 "client sent invalid method in HTTP/0.9 request"
Igor Sysoev016b8522002-08-29 16:59:54 +000065};
66
67
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000068ngx_http_header_t ngx_http_headers_in[] = {
Igor Sysoev899b44e2005-05-12 14:58:06 +000069 { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
Igor Sysoevb145b062005-06-15 18:33:41 +000070 ngx_http_process_unique_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000071
Igor Sysoev899b44e2005-05-12 14:58:06 +000072 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
Igor Sysoevb145b062005-06-15 18:33:41 +000073 ngx_http_process_unique_header_line },
Igor Sysoev899b44e2005-05-12 14:58:06 +000074
75 { ngx_string("If-Modified-Since"),
76 offsetof(ngx_http_headers_in_t, if_modified_since),
77 ngx_http_process_header_line },
78
79 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
80 ngx_http_process_header_line },
81
82 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
83 ngx_http_process_header_line },
84
85 { ngx_string("Content-Length"),
86 offsetof(ngx_http_headers_in_t, content_length),
Igor Sysoevb145b062005-06-15 18:33:41 +000087 ngx_http_process_unique_header_line },
Igor Sysoev899b44e2005-05-12 14:58:06 +000088
89 { ngx_string("Content-Type"),
90 offsetof(ngx_http_headers_in_t, content_type),
91 ngx_http_process_header_line },
92
93 { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
94 ngx_http_process_header_line },
95
Igor Sysoevc31a9bb2005-11-26 10:11:11 +000096 { ngx_string("Transfer-Encoding"),
97 offsetof(ngx_http_headers_in_t, transfer_encoding),
98 ngx_http_process_header_line },
99
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000100#if (NGX_HTTP_GZIP)
101 { ngx_string("Accept-Encoding"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000102 offsetof(ngx_http_headers_in_t, accept_encoding),
103 ngx_http_process_header_line },
104
105 { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
106 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000107#endif
108
109 { ngx_string("Authorization"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000110 offsetof(ngx_http_headers_in_t, authorization),
Igor Sysoevb145b062005-06-15 18:33:41 +0000111 ngx_http_process_unique_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000112
Igor Sysoev899b44e2005-05-12 14:58:06 +0000113 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
114 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000115
Igor Sysoev09c684b2005-11-09 17:25:55 +0000116#if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000117 { ngx_string("X-Forwarded-For"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000118 offsetof(ngx_http_headers_in_t, x_forwarded_for),
119 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000120#endif
Igor Sysoev02025fd2005-01-18 13:03:58 +0000121
Igor Sysoev09c684b2005-11-09 17:25:55 +0000122#if (NGX_HTTP_REALIP)
123 { ngx_string("X-Real-IP"),
124 offsetof(ngx_http_headers_in_t, x_real_ip),
125 ngx_http_process_header_line },
126#endif
127
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000128#if (NGX_HTTP_HEADERS)
Igor Sysoev899b44e2005-05-12 14:58:06 +0000129 { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
130 ngx_http_process_header_line },
131
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000132 { ngx_string("Accept-Language"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000133 offsetof(ngx_http_headers_in_t, accept_language),
134 ngx_http_process_header_line },
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000135#endif
136
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000137#if (NGX_HTTP_DAV)
138 { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
139 ngx_http_process_header_line },
140
141 { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
142 ngx_http_process_header_line },
143#endif
144
Igor Sysoev899b44e2005-05-12 14:58:06 +0000145 { ngx_string("Cookie"), 0, ngx_http_process_cookie },
146
147 { ngx_null_string, 0, NULL }
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000148};
149
150
Igor Sysoevc1571722005-03-19 12:38:37 +0000151void
152ngx_http_init_connection(ngx_connection_t *c)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000153{
Igor Sysoev6253ca12003-05-27 12:18:54 +0000154 ngx_event_t *rev;
Igor Sysoev160d7742003-11-19 16:26:41 +0000155 ngx_http_log_ctx_t *ctx;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000156
Igor Sysoevc1571722005-03-19 12:38:37 +0000157 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
158 if (ctx == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000159 ngx_http_close_connection(c);
160 return;
161 }
162
Igor Sysoev1b735832004-11-11 14:07:14 +0000163 ctx->client = &c->addr_text;
Igor Sysoev1b735832004-11-11 14:07:14 +0000164 ctx->request = NULL;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +0000165 ctx->current_request = NULL;
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000166
167 c->log->connection = c->number;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000168 c->log->handler = ngx_http_log_error;
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000169 c->log->data = ctx;
170 c->log->action = "reading client request line";
171
Igor Sysoevc7a2f682004-02-10 16:23:38 +0000172 c->log_error = NGX_ERROR_INFO;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000173
Igor Sysoevdc479b42003-03-20 16:09:44 +0000174 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000175 rev->handler = ngx_http_init_request;
Igor Sysoev9ac946b2005-10-24 15:09:41 +0000176 c->write->handler = ngx_http_empty_handler;
Igor Sysoev7af6b162004-02-09 07:46:43 +0000177
Igor Sysoev055951d2005-10-21 19:12:18 +0000178#if (NGX_STAT_STUB)
179 ngx_atomic_fetch_add(ngx_stat_reading, 1);
180#endif
181
Igor Sysoevdc479b42003-03-20 16:09:44 +0000182 if (rev->ready) {
Igor Sysoev0ab91b92004-06-06 19:49:18 +0000183 /* the deferred accept(), rtsig, aio, iocp */
Igor Sysoev709405b2004-03-31 15:26:46 +0000184
Igor Sysoevffe71442006-02-08 15:33:12 +0000185 if (ngx_use_accept_mutex) {
Igor Sysoevc2068d02005-10-19 12:33:58 +0000186 ngx_post_event(rev, &ngx_posted_events);
Igor Sysoev709405b2004-03-31 15:26:46 +0000187 return;
188 }
189
Igor Sysoev6b863e32003-05-12 15:52:24 +0000190 ngx_http_init_request(rev);
191 return;
Igor Sysoev016b8522002-08-29 16:59:54 +0000192 }
Igor Sysoev73009772003-02-06 17:21:13 +0000193
Igor Sysoev239baac2003-06-11 15:28:34 +0000194 ngx_add_timer(rev, c->listening->post_accept_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000195
Igor Sysoevb5faed22003-10-29 08:30:44 +0000196 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev055951d2005-10-21 19:12:18 +0000197#if (NGX_STAT_STUB)
198 ngx_atomic_fetch_add(ngx_stat_reading, -1);
199#endif
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000200 ngx_http_close_connection(c);
201 return;
202 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000203}
204
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000205
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000206static void
207ngx_http_init_request(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000208{
Igor Sysoev09c684b2005-11-09 17:25:55 +0000209 socklen_t len;
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000210 ngx_uint_t i;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000211 struct sockaddr_in sin;
212 ngx_connection_t *c;
213 ngx_http_request_t *r;
Igor Sysoev305a9d82005-12-26 17:07:48 +0000214 ngx_http_in_port_t *hip;
215 ngx_http_in_addr_t *hia;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000216 ngx_http_log_ctx_t *ctx;
217 ngx_http_connection_t *hc;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000218 ngx_http_core_srv_conf_t *cscf;
219 ngx_http_core_loc_conf_t *clcf;
220 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000221#if (NGX_HTTP_SSL)
Igor Sysoev09c684b2005-11-09 17:25:55 +0000222 ngx_http_ssl_srv_conf_t *sscf;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000223#endif
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000224
Igor Sysoev055951d2005-10-21 19:12:18 +0000225#if (NGX_STAT_STUB)
226 ngx_atomic_fetch_add(ngx_stat_reading, -1);
227#endif
228
Igor Sysoeva9830112003-05-19 16:39:14 +0000229 c = rev->data;
Igor Sysoeva9830112003-05-19 16:39:14 +0000230
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000231 if (rev->timedout) {
232 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000233
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000234 ngx_http_close_connection(c);
235 return;
236 }
237
Igor Sysoevf7abd722004-09-23 06:32:00 +0000238 hc = c->data;
Igor Sysoevdd888c42004-09-21 05:38:28 +0000239
Igor Sysoev055951d2005-10-21 19:12:18 +0000240 if (hc == NULL) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000241 hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
242 if (hc == NULL) {
Igor Sysoevdd888c42004-09-21 05:38:28 +0000243 ngx_http_close_connection(c);
244 return;
245 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000246 }
Igor Sysoevdd888c42004-09-21 05:38:28 +0000247
Igor Sysoevf7abd722004-09-23 06:32:00 +0000248 r = hc->request;
249
250 if (r) {
251 ngx_memzero(r, sizeof(ngx_http_request_t));
252
253 r->pipeline = hc->pipeline;
254
255 if (hc->nbusy) {
256 r->header_in = hc->busy[0];
257 }
258
Igor Sysoevf7abd722004-09-23 06:32:00 +0000259 } else {
Igor Sysoevc1571722005-03-19 12:38:37 +0000260 r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
261 if (r == NULL) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000262 ngx_http_close_connection(c);
263 return;
264 }
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000265
Igor Sysoevdd888c42004-09-21 05:38:28 +0000266 hc->request = r;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000267 }
268
Igor Sysoevdd888c42004-09-21 05:38:28 +0000269 c->data = r;
270 r->http_connection = hc;
271
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000272 c->sent = 0;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000273 r->signature = NGX_HTTP_MODULE;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000274
Igor Sysoev6253ca12003-05-27 12:18:54 +0000275 /* find the server configuration for the address:port */
276
277 /* AF_INET only */
278
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000279 hip = c->listening->servers;
Igor Sysoev305a9d82005-12-26 17:07:48 +0000280 hia = hip->addrs;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000281
Igor Sysoev305a9d82005-12-26 17:07:48 +0000282 r->port = hip->port;
283 r->port_text = &hip->port_text;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000284
285 i = 0;
286
Igor Sysoev305a9d82005-12-26 17:07:48 +0000287 if (hip->naddrs > 1) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000288
Igor Sysoev239baac2003-06-11 15:28:34 +0000289 /*
Igor Sysoevd00b3652004-08-23 19:09:29 +0000290 * There are several addresses on this port and one of them
291 * is the "*:port" wildcard so getsockname() is needed to determine
Igor Sysoev239baac2003-06-11 15:28:34 +0000292 * the server address.
Igor Sysoevd00b3652004-08-23 19:09:29 +0000293 *
Igor Sysoev239baac2003-06-11 15:28:34 +0000294 * AcceptEx() already gave this address.
295 */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000296
Igor Sysoev1b735832004-11-11 14:07:14 +0000297#if (NGX_WIN32)
Igor Sysoev239baac2003-06-11 15:28:34 +0000298 if (c->local_sockaddr) {
299 r->in_addr =
300 ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000301
Igor Sysoev02025fd2005-01-18 13:03:58 +0000302 } else
Igor Sysoev239baac2003-06-11 15:28:34 +0000303#endif
Igor Sysoev02025fd2005-01-18 13:03:58 +0000304 {
Igor Sysoev239baac2003-06-11 15:28:34 +0000305 len = sizeof(struct sockaddr_in);
Igor Sysoev02025fd2005-01-18 13:03:58 +0000306 if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000307 ngx_connection_error(c, ngx_socket_errno,
308 "getsockname() failed");
Igor Sysoev239baac2003-06-11 15:28:34 +0000309 ngx_http_close_connection(c);
310 return;
311 }
Igor Sysoev10a543a2004-03-16 07:10:12 +0000312
Igor Sysoev02025fd2005-01-18 13:03:58 +0000313 r->in_addr = sin.sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000314 }
315
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000316 /* the last address is "*" */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000317
Igor Sysoev305a9d82005-12-26 17:07:48 +0000318 for ( /* void */ ; i < hip->naddrs - 1; i++) {
319 if (hia[i].addr == r->in_addr) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000320 break;
321 }
322 }
323
324 } else {
Igor Sysoev305a9d82005-12-26 17:07:48 +0000325 r->in_addr = hia[0].addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000326 }
327
Igor Sysoev305a9d82005-12-26 17:07:48 +0000328 r->virtual_names = hia[i].virtual_names;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000329
330 /* the default server configuration for the address:port */
Igor Sysoev305a9d82005-12-26 17:07:48 +0000331 cscf = hia[i].core_srv_conf;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000332
333 r->main_conf = cscf->ctx->main_conf;
334 r->srv_conf = cscf->ctx->srv_conf;
335 r->loc_conf = cscf->ctx->loc_conf;
336
Igor Sysoev305a9d82005-12-26 17:07:48 +0000337 r->server_name = cscf->server_name;
338
Igor Sysoev899b44e2005-05-12 14:58:06 +0000339 rev->handler = ngx_http_process_request_line;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000340
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000341#if (NGX_HTTP_SSL)
342
Igor Sysoevf38e0462004-07-16 17:11:43 +0000343 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000344 if (sscf->enable) {
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000345
346 if (c->ssl == NULL) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000347 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
Igor Sysoev02f742b2005-04-08 15:18:55 +0000348 == NGX_ERROR)
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000349 {
350 ngx_http_close_connection(c);
351 return;
352 }
353
Igor Sysoev899b44e2005-05-12 14:58:06 +0000354 rev->handler = ngx_http_ssl_handshake;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000355 }
356
Igor Sysoevd52477f2005-05-16 13:53:20 +0000357 r->main_filter_need_in_memory = 1;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000358 }
359
Igor Sysoev4aa88882004-07-14 20:07:58 +0000360#endif
361
Igor Sysoev890fc962003-07-20 21:15:59 +0000362 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
363 c->log->file = clcf->err_log->file;
Igor Sysoevfff32322004-04-08 15:58:25 +0000364 if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
365 c->log->log_level = clcf->err_log->log_level;
366 }
Igor Sysoev890fc962003-07-20 21:15:59 +0000367
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000368 if (c->buffer == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +0000369 c->buffer = ngx_create_temp_buf(c->pool,
370 cscf->client_header_buffer_size);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000371 if (c->buffer == NULL) {
372 ngx_http_close_connection(c);
373 return;
374 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000375 }
376
Igor Sysoevf7abd722004-09-23 06:32:00 +0000377 if (r->header_in == NULL) {
378 r->header_in = c->buffer;
379 }
380
Igor Sysoevc1571722005-03-19 12:38:37 +0000381 r->pool = ngx_create_pool(cscf->request_pool_size, c->log);
382 if (r->pool == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000383 ngx_http_close_connection(c);
384 return;
385 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000386
Igor Sysoev89690bf2004-03-23 06:01:52 +0000387
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000388 if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000389 sizeof(ngx_table_elt_t))
390 == NGX_ERROR)
Igor Sysoev980a9242004-09-05 19:54:02 +0000391 {
392 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev980a9242004-09-05 19:54:02 +0000393 return;
394 }
395
Igor Sysoev6b863e32003-05-12 15:52:24 +0000396 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
397 if (r->ctx == NULL) {
398 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000399 return;
400 }
Igor Sysoeve0268b92002-09-11 15:18:33 +0000401
Igor Sysoev09c684b2005-11-09 17:25:55 +0000402 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
403
404 r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
405 * sizeof(ngx_http_variable_value_t));
406 if (r->variables == NULL) {
407 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
408 return;
409 }
410
Igor Sysoevc78c41c2004-07-07 06:15:04 +0000411 c->single_connection = 1;
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000412 c->destroyed = 0;
413
Igor Sysoev6b863e32003-05-12 15:52:24 +0000414 r->connection = c;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000415
Igor Sysoevf6e1fe32005-10-04 10:38:53 +0000416 r->main = r;
417
Igor Sysoev11d75322005-03-01 15:20:36 +0000418 r->start_time = ngx_time();
419
Igor Sysoev94e32ce2006-04-07 14:08:04 +0000420 r->method = NGX_HTTP_UNKNOWN;
421
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000422 r->headers_in.content_length_n = -1;
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000423 r->headers_in.keep_alive_n = -1;
424 r->headers_out.content_length_n = -1;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000425 r->headers_out.last_modified_time = -1;
426
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000427 r->http_state = NGX_HTTP_READING_REQUEST_STATE;
428
Igor Sysoevc04deca2005-03-28 14:43:02 +0000429 ctx = c->log->data;
430 ctx->request = r;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +0000431 ctx->current_request = r;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000432 r->log_handler = ngx_http_log_error_handler;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000433
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000434#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000435 ngx_atomic_fetch_add(ngx_stat_reading, 1);
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000436 r->stat_reading = 1;
Igor Sysoev78452232005-10-12 13:50:36 +0000437 ngx_atomic_fetch_add(ngx_stat_requests, 1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000438#endif
439
Igor Sysoev899b44e2005-05-12 14:58:06 +0000440 rev->handler(rev);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000441}
442
443
444#if (NGX_HTTP_SSL)
445
Igor Sysoevc1571722005-03-19 12:38:37 +0000446static void
447ngx_http_ssl_handshake(ngx_event_t *rev)
Igor Sysoevf38e0462004-07-16 17:11:43 +0000448{
Igor Sysoevf38e0462004-07-16 17:11:43 +0000449 u_char buf[1];
Igor Sysoev1b735832004-11-11 14:07:14 +0000450 ssize_t n;
451 ngx_int_t rc;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000452 ngx_connection_t *c;
453 ngx_http_request_t *r;
454
455 c = rev->data;
456 r = c->data;
457
458 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
459 "http check ssl handshake");
460
461 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000462 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
463 c->timedout = 1;
464 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000465 return;
466 }
467
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000468 n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000469
470 if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
471 return;
472 }
473
474 if (n == 1) {
475 if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
476 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000477 "https ssl handshake: 0x%02Xd", buf[0]);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000478
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000479 rc = ngx_ssl_handshake(c);
480
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000481 if (rc == NGX_AGAIN) {
482 c->ssl->handler = ngx_http_ssl_handshake_handler;
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000483 return;
484 }
485
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000486 ngx_http_ssl_handshake_handler(c);
487
488 return;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000489
490 } else {
491 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
492 "plain http");
493
494 r->plain_http = 1;
495 }
496 }
497
Igor Sysoev899b44e2005-05-12 14:58:06 +0000498 rev->handler = ngx_http_process_request_line;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000499 ngx_http_process_request_line(rev);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000500}
501
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000502
503static void
504ngx_http_ssl_handshake_handler(ngx_connection_t *c)
505{
506 ngx_http_request_t *r;
507
508 if (c->ssl->handshaked) {
509
510 /*
511 * The majority of browsers do not send the "close notify" alert.
512 * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
513 * and Links. And what is more, MSIE ignores the server's alert.
514 *
515 * Opera and recent Mozilla send the alert.
516 */
517
518 c->ssl->no_wait_shutdown = 1;
519
520 c->read->handler = ngx_http_process_request_line;
521 /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
522
523 ngx_http_process_request_line(c->read);
524
525 return;
526 }
527
528 r = c->data;
529
530 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000531
532 return;
533}
534
535
Igor Sysoevf38e0462004-07-16 17:11:43 +0000536#endif
537
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000538
Igor Sysoevc1571722005-03-19 12:38:37 +0000539static void
540ngx_http_process_request_line(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000541{
Igor Sysoevf7abd722004-09-23 06:32:00 +0000542 ssize_t n;
Igor Sysoevc3e47462004-09-24 16:12:19 +0000543 ngx_int_t rc, rv;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000544 ngx_connection_t *c;
545 ngx_http_request_t *r;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000546
Igor Sysoeva9830112003-05-19 16:39:14 +0000547 c = rev->data;
548 r = c->data;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000549
Igor Sysoev2b58fbf2003-12-09 15:08:11 +0000550 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
551 "http process request line");
Igor Sysoevdc479b42003-03-20 16:09:44 +0000552
553 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000554 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
555 c->timedout = 1;
556 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000557 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000558 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000559
Igor Sysoevf7abd722004-09-23 06:32:00 +0000560 rc = NGX_AGAIN;
Igor Sysoev016b8522002-08-29 16:59:54 +0000561
Igor Sysoevf7abd722004-09-23 06:32:00 +0000562 for ( ;; ) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000563
Igor Sysoevf7abd722004-09-23 06:32:00 +0000564 if (rc == NGX_AGAIN) {
565 n = ngx_http_read_request_header(r);
Igor Sysoevdc479b42003-03-20 16:09:44 +0000566
Igor Sysoevf7abd722004-09-23 06:32:00 +0000567 if (n == NGX_AGAIN || n == NGX_ERROR) {
Igor Sysoev865c1502003-11-30 20:03:18 +0000568 return;
569 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000570 }
571
Igor Sysoevf7abd722004-09-23 06:32:00 +0000572 rc = ngx_http_parse_request_line(r, r->header_in);
Igor Sysoeva9830112003-05-19 16:39:14 +0000573
Igor Sysoevf7abd722004-09-23 06:32:00 +0000574 if (rc == NGX_OK) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000575
Igor Sysoevf7abd722004-09-23 06:32:00 +0000576 /* the request line has been parsed successfully */
Igor Sysoev6b863e32003-05-12 15:52:24 +0000577
Igor Sysoev1b735832004-11-11 14:07:14 +0000578 r->request_line.len = r->request_end - r->request_start;
579 r->request_line.data = r->request_start;
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000580
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000581
Igor Sysoevdc479b42003-03-20 16:09:44 +0000582 if (r->args_start) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000583 r->uri.len = r->args_start - 1 - r->uri_start;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000584 } else {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000585 r->uri.len = r->uri_end - r->uri_start;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000586 }
587
Igor Sysoevf6906042004-11-25 16:17:31 +0000588
Igor Sysoev924bd792004-10-11 15:07:03 +0000589 if (r->complex_uri || r->quoted_uri) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000590
Igor Sysoevc1571722005-03-19 12:38:37 +0000591 r->uri.data = ngx_palloc(r->pool, r->uri.len + 1);
592 if (r->uri.data == NULL) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000593 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev1b735832004-11-11 14:07:14 +0000594 return;
595 }
596
Igor Sysoevf7abd722004-09-23 06:32:00 +0000597 rc = ngx_http_parse_complex_uri(r);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000598
Igor Sysoevc04deca2005-03-28 14:43:02 +0000599 if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) {
600 ngx_log_error(NGX_LOG_INFO, c->log, 0,
601 "client sent invalid request");
602 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000603 return;
604 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000605
Igor Sysoevf7abd722004-09-23 06:32:00 +0000606 } else {
Igor Sysoev1b735832004-11-11 14:07:14 +0000607 r->uri.data = r->uri_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000608 }
609
Igor Sysoevf6906042004-11-25 16:17:31 +0000610
Igor Sysoev1b735832004-11-11 14:07:14 +0000611 r->unparsed_uri.len = r->uri_end - r->uri_start;
612 r->unparsed_uri.data = r->uri_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000613
Igor Sysoevf7abd722004-09-23 06:32:00 +0000614
Igor Sysoev899b44e2005-05-12 14:58:06 +0000615 r->method_name.len = r->method_end - r->request_start + 1;
616 r->method_name.data = r->request_line.data;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000617
Igor Sysoev1b735832004-11-11 14:07:14 +0000618
Igor Sysoev02025fd2005-01-18 13:03:58 +0000619 if (r->http_protocol.data) {
620 r->http_protocol.len = r->request_end - r->http_protocol.data;
621 }
622
623
Igor Sysoevf7abd722004-09-23 06:32:00 +0000624 if (r->uri_ext) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000625 if (r->args_start) {
626 r->exten.len = r->args_start - 1 - r->uri_ext;
627 } else {
628 r->exten.len = r->uri_end - r->uri_ext;
629 }
630
Igor Sysoev1b735832004-11-11 14:07:14 +0000631 r->exten.data = r->uri_ext;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000632 }
633
Igor Sysoev1b735832004-11-11 14:07:14 +0000634
Igor Sysoevf7abd722004-09-23 06:32:00 +0000635 if (r->args_start && r->uri_end > r->args_start) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000636 r->args.len = r->uri_end - r->args_start;
Igor Sysoev1b735832004-11-11 14:07:14 +0000637 r->args.data = r->args_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000638 }
639
Igor Sysoevf7abd722004-09-23 06:32:00 +0000640
641 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000642 "http request line: \"%V\"", &r->request_line);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000643
644 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000645 "http uri: \"%V\"", &r->uri);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000646
647 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000648 "http args: \"%V\"", &r->args);
649
650 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
651 "http exten: \"%V\"", &r->exten);
652
Igor Sysoevf7abd722004-09-23 06:32:00 +0000653 if (r->http_version < NGX_HTTP_VERSION_10) {
Igor Sysoeve5035392005-08-30 10:55:07 +0000654
655 if (rev->timer_set) {
656 ngx_del_timer(rev);
657 }
658
659#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000660 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoeve5035392005-08-30 10:55:07 +0000661 r->stat_reading = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000662 ngx_atomic_fetch_add(ngx_stat_writing, 1);
Igor Sysoeve5035392005-08-30 10:55:07 +0000663 r->stat_writing = 1;
664#endif
665
666 rev->handler = ngx_http_request_handler;
667 c->write->handler = ngx_http_request_handler;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000668 r->read_event_handler = ngx_http_block_read;
Igor Sysoeve5035392005-08-30 10:55:07 +0000669
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000670 r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
Igor Sysoevef809b82006-06-28 16:00:26 +0000671 r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000672
Igor Sysoevf7abd722004-09-23 06:32:00 +0000673 ngx_http_handler(r);
Igor Sysoeve5035392005-08-30 10:55:07 +0000674
Igor Sysoev6b863e32003-05-12 15:52:24 +0000675 return;
676 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000677
Igor Sysoevdc479b42003-03-20 16:09:44 +0000678
Igor Sysoevf7abd722004-09-23 06:32:00 +0000679 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000680 sizeof(ngx_table_elt_t))
681 == NGX_ERROR)
Igor Sysoevf7abd722004-09-23 06:32:00 +0000682 {
683 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000684 return;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000685 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000686
687
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000688 if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000689 sizeof(ngx_table_elt_t *))
690 == NGX_ERROR)
Igor Sysoevf7abd722004-09-23 06:32:00 +0000691 {
692 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000693 return;
694 }
695
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000696 c->log->action = "reading client request headers";
Igor Sysoevf7abd722004-09-23 06:32:00 +0000697
Igor Sysoev899b44e2005-05-12 14:58:06 +0000698 rev->handler = ngx_http_process_request_headers;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000699 ngx_http_process_request_headers(rev);
700
701 return;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000702 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000703
Igor Sysoevc04deca2005-03-28 14:43:02 +0000704 if (rc != NGX_AGAIN) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000705
706 /* there was error while a request line parsing */
707
Igor Sysoevc04deca2005-03-28 14:43:02 +0000708 ngx_log_error(NGX_LOG_INFO, c->log, 0,
709 ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
710 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000711 return;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000712 }
713
Igor Sysoevf7abd722004-09-23 06:32:00 +0000714 /* NGX_AGAIN: a request line parsing is still incomplete */
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000715
Igor Sysoev236e0452004-09-23 16:39:34 +0000716 if (r->header_in->pos == r->header_in->end) {
Igor Sysoeva1c8a922004-01-19 18:09:14 +0000717
Igor Sysoevf7abd722004-09-23 06:32:00 +0000718 rv = ngx_http_alloc_large_header_buffer(r, 1);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000719
Igor Sysoevf7abd722004-09-23 06:32:00 +0000720 if (rv == NGX_ERROR) {
721 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000722 return;
723 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000724
Igor Sysoevf7abd722004-09-23 06:32:00 +0000725 if (rv == NGX_DECLINED) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000726 r->request_line.len = r->header_in->end - r->request_start;
727 r->request_line.data = r->request_start;
728
729 ngx_log_error(NGX_LOG_INFO, c->log, 0,
730 "client sent too long URI");
731 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000732 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000733 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000734 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000735 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000736}
737
Igor Sysoev1af7c822002-09-13 14:47:42 +0000738
Igor Sysoevc1571722005-03-19 12:38:37 +0000739static void
740ngx_http_process_request_headers(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000741{
Igor Sysoev02f742b2005-04-08 15:18:55 +0000742 ssize_t n;
743 ngx_int_t rc, rv;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000744 ngx_str_t header;
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000745 ngx_uint_t i;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000746 ngx_table_elt_t *h;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000747 ngx_connection_t *c;
748 ngx_http_header_t *hh;
749 ngx_http_request_t *r;
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000750 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000751 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000752
Igor Sysoeva9830112003-05-19 16:39:14 +0000753 c = rev->data;
754 r = c->data;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000755
Igor Sysoev865c1502003-11-30 20:03:18 +0000756 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
757 "http process request header line");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000758
Igor Sysoev6b863e32003-05-12 15:52:24 +0000759 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000760 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
761 c->timedout = 1;
762 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000763 return;
764 }
765
Igor Sysoev02f742b2005-04-08 15:18:55 +0000766 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000767 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000768
Igor Sysoevd581fd52003-05-13 16:02:32 +0000769 rc = NGX_AGAIN;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000770
Igor Sysoev016b8522002-08-29 16:59:54 +0000771 for ( ;; ) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000772
Igor Sysoevd581fd52003-05-13 16:02:32 +0000773 if (rc == NGX_AGAIN) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000774
Igor Sysoev236e0452004-09-23 16:39:34 +0000775 if (r->header_in->pos == r->header_in->end) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000776
777 rv = ngx_http_alloc_large_header_buffer(r, 0);
778
779 if (rv == NGX_ERROR) {
780 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000781 return;
782 }
783
784 if (rv == NGX_DECLINED) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000785 header.len = r->header_in->end - r->header_name_start;
786 header.data = r->header_name_start;
Igor Sysoev90c08142005-07-25 09:41:38 +0000787
788 if (header.len > NGX_MAX_ERROR_STR - 300) {
789 header.len = NGX_MAX_ERROR_STR - 300;
790 header.data[header.len++] = '.';
791 header.data[header.len++] = '.';
792 header.data[header.len++] = '.';
793 }
794
Igor Sysoevc04deca2005-03-28 14:43:02 +0000795 ngx_log_error(NGX_LOG_INFO, c->log, 0,
796 "client sent too long header line: \"%V\"",
797 &header);
798 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000799 return;
800 }
801 }
802
Igor Sysoevd581fd52003-05-13 16:02:32 +0000803 n = ngx_http_read_request_header(r);
804
805 if (n == NGX_AGAIN || n == NGX_ERROR) {
806 return;
807 }
808 }
809
Igor Sysoeve6779222003-10-03 15:50:53 +0000810 rc = ngx_http_parse_header_line(r, r->header_in);
Igor Sysoev016b8522002-08-29 16:59:54 +0000811
Igor Sysoev0dad6292003-03-05 17:30:51 +0000812 if (rc == NGX_OK) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000813
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000814 if (r->invalid_header && cscf->ignore_invalid_headers) {
Igor Sysoev4d656dc2005-03-22 16:02:46 +0000815
816 /* there was error while a header line parsing */
817
818 header.len = r->header_end - r->header_name_start;
819 header.data = r->header_name_start;
820
Igor Sysoevc04deca2005-03-28 14:43:02 +0000821 ngx_log_error(NGX_LOG_INFO, c->log, 0,
822 "client sent invalid header line: \"%V\"",
Igor Sysoev4d656dc2005-03-22 16:02:46 +0000823 &header);
824 continue;
825 }
826
Igor Sysoevd581fd52003-05-13 16:02:32 +0000827 /* a header line has been parsed successfully */
828
Igor Sysoevc1571722005-03-19 12:38:37 +0000829 h = ngx_list_push(&r->headers_in.headers);
830 if (h == NULL) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000831 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000832 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000833 }
834
Igor Sysoev02f742b2005-04-08 15:18:55 +0000835 h->hash = r->header_hash;
836
Igor Sysoevd581fd52003-05-13 16:02:32 +0000837 h->key.len = r->header_name_end - r->header_name_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000838 h->key.data = r->header_name_start;
839 h->key.data[h->key.len] = '\0';
840
Igor Sysoevd581fd52003-05-13 16:02:32 +0000841 h->value.len = r->header_end - r->header_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000842 h->value.data = r->header_start;
843 h->value.data[h->value.len] = '\0';
Igor Sysoevd581fd52003-05-13 16:02:32 +0000844
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000845 h->lowcase_key = ngx_palloc(r->pool, h->key.len);
846 if (h->lowcase_key == NULL) {
847 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
848 return;
849 }
Igor Sysoev899b44e2005-05-12 14:58:06 +0000850
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000851 if (h->key.len == r->lowcase_index) {
852 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
853
854 } else {
855 for (i = 0; i < h->key.len; i++) {
Igor Sysoev8f125582006-07-28 15:16:17 +0000856 h->lowcase_key[i] = ngx_tolower(h->key.data[i]);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000857 }
Igor Sysoevd581fd52003-05-13 16:02:32 +0000858 }
859
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000860 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
861 h->lowcase_key, h->key.len);
862
863 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
864 return;
865 }
866
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000867 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000868 "http header: \"%V: %V\"",
869 &h->key, &h->value);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000870
Igor Sysoev6253ca12003-05-27 12:18:54 +0000871 continue;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000872 }
Igor Sysoev6253ca12003-05-27 12:18:54 +0000873
Igor Sysoevc04deca2005-03-28 14:43:02 +0000874 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000875
876 /* a whole header has been parsed successfully */
877
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000878 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
879 "http header done");
Igor Sysoev42feecb2002-12-15 06:25:09 +0000880
Igor Sysoev6a12fc92004-12-06 14:45:08 +0000881 r->request_length += r->header_in->pos - r->header_in->start;
882
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000883 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
884
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000885 rc = ngx_http_process_request_header(r);
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000886
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000887 if (rc != NGX_OK) {
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000888 return;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000889 }
890
Igor Sysoev425a42c2003-10-27 16:16:17 +0000891 if (rev->timer_set) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000892 ngx_del_timer(rev);
893 }
894
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000895#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000896 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000897 r->stat_reading = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000898 ngx_atomic_fetch_add(ngx_stat_writing, 1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000899 r->stat_writing = 1;
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000900#endif
901
Igor Sysoev899b44e2005-05-12 14:58:06 +0000902 rev->handler = ngx_http_request_handler;
903 c->write->handler = ngx_http_request_handler;
904 r->read_event_handler = ngx_http_block_read;
905
Igor Sysoevd581fd52003-05-13 16:02:32 +0000906 ngx_http_handler(r);
Igor Sysoeve5035392005-08-30 10:55:07 +0000907
Igor Sysoevd581fd52003-05-13 16:02:32 +0000908 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000909 }
910
Igor Sysoevc04deca2005-03-28 14:43:02 +0000911 if (rc == NGX_AGAIN) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000912
Igor Sysoevc04deca2005-03-28 14:43:02 +0000913 /* a header line parsing is still not complete */
914
915 continue;
916 }
917
918 /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
919
920 header.len = r->header_end - r->header_name_start;
921 header.data = r->header_name_start;
922 ngx_log_error(NGX_LOG_INFO, c->log, 0,
923 "client sent invalid header line: \"%V\\r...\"",
924 &header);
925 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevc04deca2005-03-28 14:43:02 +0000926 return;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000927 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000928}
929
Igor Sysoevb0869052002-12-10 18:05:12 +0000930
Igor Sysoevc1571722005-03-19 12:38:37 +0000931static ssize_t
932ngx_http_read_request_header(ngx_http_request_t *r)
Igor Sysoev6b863e32003-05-12 15:52:24 +0000933{
Igor Sysoev187fcd82003-05-23 11:53:01 +0000934 ssize_t n;
935 ngx_event_t *rev;
936 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000937
Igor Sysoev239baac2003-06-11 15:28:34 +0000938 rev = r->connection->read;
939
Igor Sysoev6b863e32003-05-12 15:52:24 +0000940 n = r->header_in->last - r->header_in->pos;
941
942 if (n > 0) {
943 return n;
944 }
945
Igor Sysoevb145b062005-06-15 18:33:41 +0000946 if (rev->ready) {
947 n = r->connection->recv(r->connection, r->header_in->last,
948 r->header_in->end - r->header_in->last);
949 } else {
950 n = NGX_AGAIN;
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000951 }
952
Igor Sysoev6b863e32003-05-12 15:52:24 +0000953 if (n == NGX_AGAIN) {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000954 if (!r->header_timeout_set) {
Igor Sysoevf38e0462004-07-16 17:11:43 +0000955 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev187fcd82003-05-23 11:53:01 +0000956 ngx_add_timer(rev, cscf->client_header_timeout);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000957 r->header_timeout_set = 1;
958 }
959
Igor Sysoevb5faed22003-10-29 08:30:44 +0000960 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000961 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000962 return NGX_ERROR;
963 }
964
Igor Sysoev6b863e32003-05-12 15:52:24 +0000965 return NGX_AGAIN;
966 }
967
968 if (n == 0) {
969 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
970 "client closed prematurely connection");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000971 }
Igor Sysoev6b863e32003-05-12 15:52:24 +0000972
973 if (n == 0 || n == NGX_ERROR) {
Igor Sysoevac72bd12006-05-04 15:32:46 +0000974 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000975 return NGX_ERROR;
976 }
977
978 r->header_in->last += n;
979
980 return n;
981}
982
983
Igor Sysoevc1571722005-03-19 12:38:37 +0000984static ngx_int_t
985ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
986 ngx_uint_t request_line)
Igor Sysoev85080d02004-09-22 16:18:21 +0000987{
988 u_char *old, *new;
Igor Sysoev85080d02004-09-22 16:18:21 +0000989 ngx_buf_t *b;
990 ngx_http_connection_t *hc;
991 ngx_http_core_srv_conf_t *cscf;
992
993 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
994 "http alloc large header buffer");
995
Igor Sysoevf7abd722004-09-23 06:32:00 +0000996 if (request_line && r->state == 0) {
997
998 /* the client fills up the buffer with "\r\n" */
999
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001000 r->request_length += r->header_in->end - r->header_in->start;
1001
Igor Sysoevf7abd722004-09-23 06:32:00 +00001002 r->header_in->pos = r->header_in->start;
1003 r->header_in->last = r->header_in->start;
1004
1005 return NGX_OK;
1006 }
1007
Igor Sysoev85080d02004-09-22 16:18:21 +00001008 old = request_line ? r->request_start : r->header_name_start;
1009
1010 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1011
Igor Sysoevf7abd722004-09-23 06:32:00 +00001012 if (r->state != 0
1013 && (size_t) (r->header_in->pos - old)
1014 >= cscf->large_client_header_buffers.size)
1015 {
Igor Sysoev85080d02004-09-22 16:18:21 +00001016 return NGX_DECLINED;
1017 }
1018
1019 hc = r->http_connection;
1020
1021 if (hc->nfree) {
1022 b = hc->free[--hc->nfree];
1023
Igor Sysoev236e0452004-09-23 16:39:34 +00001024 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +00001025 "http large header free: %p %uz",
Igor Sysoev236e0452004-09-23 16:39:34 +00001026 b->pos, b->end - b->last);
1027
Igor Sysoevf7abd722004-09-23 06:32:00 +00001028 } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
Igor Sysoev85080d02004-09-22 16:18:21 +00001029
1030 if (hc->busy == NULL) {
1031 hc->busy = ngx_palloc(r->connection->pool,
Igor Sysoevf7abd722004-09-23 06:32:00 +00001032 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev85080d02004-09-22 16:18:21 +00001033 if (hc->busy == NULL) {
1034 return NGX_ERROR;
1035 }
1036 }
1037
1038 b = ngx_create_temp_buf(r->connection->pool,
Igor Sysoevf7abd722004-09-23 06:32:00 +00001039 cscf->large_client_header_buffers.size);
Igor Sysoev85080d02004-09-22 16:18:21 +00001040 if (b == NULL) {
1041 return NGX_ERROR;
1042 }
1043
Igor Sysoev236e0452004-09-23 16:39:34 +00001044 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +00001045 "http large header alloc: %p %uz",
Igor Sysoev236e0452004-09-23 16:39:34 +00001046 b->pos, b->end - b->last);
1047
Igor Sysoev85080d02004-09-22 16:18:21 +00001048 } else {
1049 return NGX_DECLINED;
1050 }
1051
1052 hc->busy[hc->nbusy++] = b;
1053
Igor Sysoevf7abd722004-09-23 06:32:00 +00001054 if (r->state == 0) {
1055 /*
1056 * r->state == 0 means that a header line was parsed successfully
1057 * and we do not need to copy incomplete header line and
1058 * to relocate the parser header pointers
1059 */
1060
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001061 r->request_length += r->header_in->end - r->header_in->start;
1062
Igor Sysoevf7abd722004-09-23 06:32:00 +00001063 r->header_in = b;
1064
1065 return NGX_OK;
1066 }
1067
Igor Sysoev236e0452004-09-23 16:39:34 +00001068 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1069 "http large header copy: %d", r->header_in->pos - old);
1070
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001071 r->request_length += old - r->header_in->start;
1072
Igor Sysoev85080d02004-09-22 16:18:21 +00001073 new = b->start;
1074
Igor Sysoev236e0452004-09-23 16:39:34 +00001075 ngx_memcpy(new, old, r->header_in->pos - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001076
1077 b->pos = new + (r->header_in->pos - old);
Igor Sysoev236e0452004-09-23 16:39:34 +00001078 b->last = new + (r->header_in->pos - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001079
1080 if (request_line) {
1081 r->request_start = new;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001082
1083 if (r->request_end) {
1084 r->request_end = new + (r->request_end - old);
1085 }
1086
1087 r->method_end = new + (r->method_end - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001088
1089 r->uri_start = new + (r->uri_start - old);
1090 r->uri_end = new + (r->uri_end - old);
1091
Igor Sysoevf7abd722004-09-23 06:32:00 +00001092 if (r->schema_start) {
1093 r->schema_start = new + (r->schema_start - old);
1094 r->schema_end = new + (r->schema_end - old);
1095 }
1096
1097 if (r->host_start) {
1098 r->host_start = new + (r->host_start - old);
1099 r->host_end = new + (r->host_end - old);
1100 }
1101
1102 if (r->port_start) {
1103 r->port_start = new + (r->port_start - old);
1104 r->port_end = new + (r->port_end - old);
1105 }
1106
Igor Sysoev85080d02004-09-22 16:18:21 +00001107 if (r->uri_ext) {
1108 r->uri_ext = new + (r->uri_ext - old);
1109 }
1110
1111 if (r->args_start) {
1112 r->args_start = new + (r->args_start - old);
1113 }
1114
1115 } else {
1116 r->header_name_start = new;
1117 r->header_name_end = new + (r->header_name_end - old);
1118 r->header_start = new + (r->header_start - old);
1119 r->header_end = new + (r->header_end - old);
1120 }
1121
1122 r->header_in = b;
1123
1124 return NGX_OK;
1125}
1126
Igor Sysoev85080d02004-09-22 16:18:21 +00001127
Igor Sysoevc1571722005-03-19 12:38:37 +00001128static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001129ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1130 ngx_uint_t offset)
1131{
1132 ngx_table_elt_t **ph;
1133
1134 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1135
1136 if (*ph == NULL) {
1137 *ph = h;
1138 }
1139
1140 return NGX_OK;
1141}
1142
1143
1144static ngx_int_t
Igor Sysoevb145b062005-06-15 18:33:41 +00001145ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1146 ngx_uint_t offset)
1147{
1148 ngx_table_elt_t **ph;
1149
1150 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1151
1152 if (*ph == NULL) {
1153 *ph = h;
1154 return NGX_OK;
1155 }
1156
1157 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1158 "client sent duplicate header line: \"%V: %V\"",
1159 &h->key, &h->value);
1160
1161 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1162
1163 return NGX_ERROR;
1164}
1165
1166
1167static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001168ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
1169 ngx_uint_t offset)
1170{
1171 ngx_table_elt_t **cookie;
1172
1173 cookie = ngx_array_push(&r->headers_in.cookies);
Igor Sysoevb145b062005-06-15 18:33:41 +00001174 if (cookie) {
1175 *cookie = h;
1176 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001177 }
1178
Igor Sysoevb145b062005-06-15 18:33:41 +00001179 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001180
Igor Sysoevb145b062005-06-15 18:33:41 +00001181 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001182}
1183
1184
1185static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001186ngx_http_process_request_header(ngx_http_request_t *r)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001187{
Igor Sysoev44d87222006-05-06 16:28:56 +00001188 size_t len;
1189 u_char *ua, *user_agent, ch;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001190 ngx_uint_t hash;
Igor Sysoev44d87222006-05-06 16:28:56 +00001191#if (NGX_HTTP_SSL)
1192 long rc;
1193 ngx_http_ssl_srv_conf_t *sscf;
1194#endif
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001195
1196 if (r->headers_in.host) {
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001197
1198 hash = 0;
1199
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001200 for (len = 0; len < r->headers_in.host->value.len; len++) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001201 ch = r->headers_in.host->value.data[len];
1202
1203 if (ch == ':') {
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001204 break;
1205 }
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001206
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001207 ch = ngx_tolower(ch);
1208 r->headers_in.host->value.data[len] = ch;
1209 hash = ngx_hash(hash, ch);
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001210 }
Igor Sysoevc04deca2005-03-28 14:43:02 +00001211
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001212 if (len && r->headers_in.host->value.data[len - 1] == '.') {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001213 len--;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001214 hash = ngx_hash_key(r->headers_in.host->value.data, len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001215 }
1216
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001217 r->headers_in.host_name_len = len;
1218
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001219 if (r->virtual_names) {
1220 ngx_http_find_virtual_server(r, r->virtual_names, hash);
1221 }
Igor Sysoev3043bfc2004-05-14 16:51:47 +00001222
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001223 } else {
1224 if (r->http_version > NGX_HTTP_VERSION_10) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001225 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1226 "client sent HTTP/1.1 request without \"Host\" header");
1227 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1228 return NGX_ERROR;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001229 }
Igor Sysoevc04deca2005-03-28 14:43:02 +00001230
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001231 r->headers_in.host_name_len = 0;
1232 }
1233
1234 if (r->headers_in.content_length) {
1235 r->headers_in.content_length_n =
Igor Sysoev1765f472006-07-07 16:33:19 +00001236 ngx_atoof(r->headers_in.content_length->value.data,
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001237 r->headers_in.content_length->value.len);
1238
1239 if (r->headers_in.content_length_n == NGX_ERROR) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001240 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1241 "client sent invalid \"Content-Length\" header");
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001242 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
Igor Sysoevc04deca2005-03-28 14:43:02 +00001243 return NGX_ERROR;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001244 }
1245 }
1246
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00001247 if (r->method & (NGX_HTTP_POST|NGX_HTTP_PUT)
1248 && r->headers_in.content_length_n == -1)
1249 {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001250 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1251 "client sent POST method without \"Content-Length\" header");
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001252 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
1253 return NGX_ERROR;
1254 }
1255
1256 if (r->headers_in.transfer_encoding
1257 && ngx_strstr(r->headers_in.transfer_encoding->value.data, "chunked"))
1258 {
1259 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1260 "client sent \"Transfer-Encoding: chunked\" header");
1261 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
Igor Sysoevc04deca2005-03-28 14:43:02 +00001262 return NGX_ERROR;
Igor Sysoev6881bfb2004-03-30 06:27:36 +00001263 }
1264
Igor Sysoevf38e0462004-07-16 17:11:43 +00001265 if (r->plain_http) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001266 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1267 "client sent plain HTTP request to HTTPS port");
1268 ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1269 return NGX_ERROR;
Igor Sysoevf38e0462004-07-16 17:11:43 +00001270 }
1271
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001272 if (r->headers_in.connection) {
1273 if (r->headers_in.connection->value.len == 5
1274 && ngx_strcasecmp(r->headers_in.connection->value.data, "close")
Igor Sysoev899b44e2005-05-12 14:58:06 +00001275 == 0)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001276 {
1277 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1278
1279 } else if (r->headers_in.connection->value.len == 10
1280 && ngx_strcasecmp(r->headers_in.connection->value.data,
Igor Sysoev899b44e2005-05-12 14:58:06 +00001281 "keep-alive") == 0)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001282 {
1283 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1284
1285 if (r->headers_in.keep_alive) {
1286 r->headers_in.keep_alive_n =
Igor Sysoevc1571722005-03-19 12:38:37 +00001287 ngx_atotm(r->headers_in.keep_alive->value.data,
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001288 r->headers_in.keep_alive->value.len);
1289 }
1290 }
1291 }
1292
Igor Sysoev2f657222004-06-16 15:32:11 +00001293 if (r->headers_in.user_agent) {
1294
1295 /*
1296 * check some widespread browsers while the headers are still
1297 * in CPU cache
1298 */
1299
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001300 user_agent = r->headers_in.user_agent->value.data;
1301
1302 ua = (u_char *) ngx_strstr(user_agent, "MSIE");
1303
1304 if (ua && ua + 8 < user_agent + r->headers_in.user_agent->value.len) {
1305
Igor Sysoev2f657222004-06-16 15:32:11 +00001306 r->headers_in.msie = 1;
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001307
Igor Sysoev2f657222004-06-16 15:32:11 +00001308 if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') {
1309 r->headers_in.msie4 = 1;
1310 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001311
1312#if 0
1313 /* MSIE ignores the SSL "close notify" alert */
Igor Sysoev42b12b32004-12-02 18:40:46 +00001314 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00001315 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00001316 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001317#endif
Igor Sysoev2f657222004-06-16 15:32:11 +00001318 }
Igor Sysoev85cccfb2004-09-15 16:00:43 +00001319
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001320 if (ngx_strstr(user_agent, "Opera")) {
Igor Sysoev85cccfb2004-09-15 16:00:43 +00001321 r->headers_in.opera = 1;
1322 r->headers_in.msie = 0;
1323 r->headers_in.msie4 = 0;
1324 }
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001325
1326 if (!r->headers_in.msie && !r->headers_in.opera) {
1327
Igor Sysoeva2c81192004-09-19 18:27:00 +00001328 if (ngx_strstr(user_agent, "Gecko/")) {
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001329 r->headers_in.gecko = 1;
1330
1331 } else if (ngx_strstr(user_agent, "Konqueror")) {
1332 r->headers_in.konqueror = 1;
1333 }
1334 }
Igor Sysoev2f657222004-06-16 15:32:11 +00001335 }
1336
Igor Sysoevb71c6902006-08-04 16:04:04 +00001337#if (NGX_HTTP_SSL)
1338
1339 if (r->connection->ssl) {
1340 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
1341
1342 if (sscf->verify) {
1343 rc = SSL_get_verify_result(r->connection->ssl->connection);
1344
1345 if (rc != X509_V_OK) {
1346 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
Igor Sysoevc55a1042006-08-09 19:59:45 +00001347 "client SSL certificate verify error: (%l:%s)",
Igor Sysoevb71c6902006-08-04 16:04:04 +00001348 rc, X509_verify_cert_error_string(rc));
1349 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
1350 return NGX_ERROR;
1351 }
1352
1353 if (SSL_get_peer_certificate(r->connection->ssl->connection)
1354 == NULL)
1355 {
1356 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1357 "client sent no required SSL certificate");
1358 ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
1359 return NGX_ERROR;
1360 }
1361 }
1362 }
1363
1364#endif
1365
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001366 return NGX_OK;
1367}
1368
1369
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001370static void
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001371ngx_http_find_virtual_server(ngx_http_request_t *r,
1372 ngx_http_virtual_names_t *vn, ngx_uint_t hash)
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001373{
Igor Sysoev305a9d82005-12-26 17:07:48 +00001374 size_t len;
1375 u_char *host;
Igor Sysoev305a9d82005-12-26 17:07:48 +00001376 ngx_http_core_loc_conf_t *clcf;
1377 ngx_http_core_srv_conf_t *cscf;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001378
Igor Sysoev305a9d82005-12-26 17:07:48 +00001379 host = r->headers_in.host->value.data;
1380 len = r->headers_in.host_name_len;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001381
Igor Sysoev305a9d82005-12-26 17:07:48 +00001382 if (vn->hash.buckets) {
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001383 cscf = ngx_hash_find(&vn->hash, hash, host, len);
Igor Sysoev305a9d82005-12-26 17:07:48 +00001384 if (cscf) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001385 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001386 }
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001387 }
1388
Igor Sysoev305a9d82005-12-26 17:07:48 +00001389 if (vn->dns_wildcards && vn->dns_wildcards->hash.buckets) {
1390 cscf = ngx_hash_find_wildcard(vn->dns_wildcards, host, len);
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001391
Igor Sysoev305a9d82005-12-26 17:07:48 +00001392 if (cscf) {
1393 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001394 }
1395 }
1396
Igor Sysoev1765f472006-07-07 16:33:19 +00001397 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1398
1399 if (cscf->wildcard) {
1400 r->server_name.len = len;
1401 r->server_name.data = host;
1402 }
1403
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001404 return;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001405
Igor Sysoev899b44e2005-05-12 14:58:06 +00001406found:
1407
Igor Sysoev305a9d82005-12-26 17:07:48 +00001408 r->server_name.len = len;
1409 r->server_name.data = host;
1410
1411 r->srv_conf = cscf->ctx->srv_conf;
1412 r->loc_conf = cscf->ctx->loc_conf;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001413
1414 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1415 r->connection->log->file = clcf->err_log->file;
1416
1417 if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1418 r->connection->log->log_level = clcf->err_log->log_level;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001419 }
1420
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001421 return;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001422}
1423
1424
Igor Sysoev899b44e2005-05-12 14:58:06 +00001425static void
1426ngx_http_request_handler(ngx_event_t *ev)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001427{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001428 ngx_connection_t *c;
1429 ngx_http_request_t *r;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001430 ngx_http_log_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001431
1432 c = ev->data;
1433 r = c->data;
1434
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001435 ctx = c->log->data;
1436 ctx->current_request = r;
1437
Igor Sysoev899b44e2005-05-12 14:58:06 +00001438 if (ev->write) {
1439 r->write_event_handler(r);
1440
1441 } else {
1442 r->read_event_handler(r);
1443 }
1444}
1445
1446
1447void
1448ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1449{
1450 ngx_http_request_t *pr;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001451 ngx_http_log_ctx_t *ctx;
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001452 ngx_http_core_loc_conf_t *clcf;
1453
Igor Sysoev899b44e2005-05-12 14:58:06 +00001454 if (rc == NGX_DONE) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001455 /* the request pool may be already destroyed */
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001456 return;
1457 }
1458
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001459 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1460 "http finalize request: %d, \"%V?%V\"",
1461 rc, &r->uri, &r->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001462
Igor Sysoev8f125582006-07-28 15:16:17 +00001463 if (r != r->main
1464 && rc != NGX_ERROR
1465 && !r->connection->error
1466 && !r->request_output
1467 && r->out)
1468 {
1469 if (!r->header_sent) {
1470 rc = ngx_http_set_content_type(r);
1471
1472 if (rc == NGX_OK) {
1473 rc = ngx_http_send_header(r);
1474
1475 if (rc != NGX_ERROR) {
1476 rc = ngx_http_output_filter(r, r->out);
1477 }
1478 }
1479
1480 } else {
1481 rc = ngx_http_output_filter(r, r->out);
1482 }
1483 }
1484
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001485 if (rc == NGX_ERROR
1486 || rc == NGX_HTTP_REQUEST_TIME_OUT
1487 || r->connection->error)
1488 {
Igor Sysoev7f7846d2006-04-26 09:52:47 +00001489 if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
1490 && r->headers_out.status == 0)
1491 {
1492 r->headers_out.status = NGX_HTTP_CLIENT_CLOSED_REQUEST;
1493 }
1494
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001495 if (ngx_http_post_action(r) == NGX_OK) {
1496 return;
1497 }
1498
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001499 ngx_http_close_request(r, 0);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001500 return;
1501 }
1502
Igor Sysoev7bdb7202006-04-19 15:30:56 +00001503 if (rc >= NGX_HTTP_SPECIAL_RESPONSE
1504 || rc == NGX_HTTP_CREATED
1505 || rc == NGX_HTTP_NO_CONTENT)
1506 {
Igor Sysoevcdc46302005-12-07 14:51:31 +00001507 if (rc == NGX_HTTP_CLOSE) {
1508 ngx_http_close_request(r, rc);
1509 return;
1510 }
1511
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001512 if (r == r->main) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001513 if (r->connection->read->timer_set) {
1514 ngx_del_timer(r->connection->read);
1515 }
1516
1517 if (r->connection->write->timer_set) {
1518 ngx_del_timer(r->connection->write);
1519 }
1520 }
1521
1522 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001523 return;
1524 }
1525
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001526 if (r != r->main || rc == NGX_AGAIN) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001527 if (ngx_http_set_write_handler(r) != NGX_OK) {
1528 return;
1529 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001530 }
1531
1532 r->done = 1;
1533
1534 if (r != r->connection->data) {
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001535 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1536 "http finalize non-active request: \"%V?%V\"",
1537 &r->uri, &r->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001538 return;
1539 }
1540
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001541 if (r != r->main) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001542
1543 pr = r->parent;
1544
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001545 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1546 "http parent request: \"%V?%V\"", &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001547
Igor Sysoev899b44e2005-05-12 14:58:06 +00001548 if (rc != NGX_AGAIN) {
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001549 r->connection->data = pr;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001550 }
1551
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001552 ctx = r->connection->log->data;
1553 ctx->current_request = pr;
1554
Igor Sysoev899b44e2005-05-12 14:58:06 +00001555 if (pr->postponed) {
1556
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001557 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1558 "http request: \"%V?%V\" has postponed",
1559 &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001560
Igor Sysoev899b44e2005-05-12 14:58:06 +00001561 if (rc != NGX_AGAIN && pr->postponed->request == r) {
1562 pr->postponed = pr->postponed->next;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001563 }
1564
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001565 if (r->fast_subrequest) {
Igor Sysoevac72bd12006-05-04 15:32:46 +00001566
1567 if (rc == NGX_AGAIN) {
1568 r->fast_subrequest = 0;
1569 }
1570
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001571 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1572 "http fast subrequest: \"%V?%V\" done",
1573 &r->uri, &r->args);
1574 return;
1575 }
1576
Igor Sysoevac72bd12006-05-04 15:32:46 +00001577 if (rc != NGX_AGAIN) {
1578 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1579 "http wake parent request: \"%V?%V\"",
1580 &pr->uri, &pr->args);
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001581
Igor Sysoevac72bd12006-05-04 15:32:46 +00001582 pr->write_event_handler(pr);
1583 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001584 }
1585
1586 return;
1587 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001588
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001589 if (rc == NGX_AGAIN) {
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001590 return;
Igor Sysoev5192b362005-07-08 14:34:20 +00001591 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001592
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001593 if (r->connection->buffered) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001594 (void) ngx_http_set_write_handler(r);
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001595 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001596 }
1597
Igor Sysoev6d16e1e2006-04-05 13:40:54 +00001598 if (!r->post_action) {
1599 r->request_complete = 1;
1600 }
1601
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001602 if (ngx_http_post_action(r) == NGX_OK) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001603 return;
1604 }
1605
Igor Sysoev0a280a32003-10-12 16:49:16 +00001606 if (r->connection->read->timer_set) {
1607 ngx_del_timer(r->connection->read);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001608 }
1609
Igor Sysoev0a280a32003-10-12 16:49:16 +00001610 if (r->connection->write->timer_set) {
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001611 r->connection->write->delayed = 0;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001612 ngx_del_timer(r->connection->write);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001613 }
1614
Igor Sysoev24025022005-12-16 15:07:08 +00001615 if (r->connection->destroyed) {
1616 return;
1617 }
1618
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001619 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001620
Igor Sysoevc5991982004-01-16 06:15:48 +00001621 if (!ngx_terminate
Igor Sysoev3f4685f2004-04-25 20:13:21 +00001622 && !ngx_exiting
Igor Sysoevc5991982004-01-16 06:15:48 +00001623 && r->keepalive != 0
1624 && clcf->keepalive_timeout > 0)
1625 {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001626 ngx_http_set_keepalive(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001627 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001628
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001629 } else if (r->lingering_close && clcf->lingering_timeout > 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001630 ngx_http_set_lingering_close(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001631 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001632 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001633
Igor Sysoevc5991982004-01-16 06:15:48 +00001634 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001635}
1636
1637
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001638static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001639ngx_http_set_write_handler(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001640{
Igor Sysoevd581fd52003-05-13 16:02:32 +00001641 ngx_event_t *wev;
Igor Sysoeva9830112003-05-19 16:39:14 +00001642 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001643
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001644 r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
1645
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001646 r->write_event_handler = ngx_http_writer;
1647
Igor Sysoev899b44e2005-05-12 14:58:06 +00001648 wev = r->connection->write;
1649
Igor Sysoevef066482004-06-21 15:59:32 +00001650 if (wev->ready && wev->delayed) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001651 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001652 }
1653
Igor Sysoev899b44e2005-05-12 14:58:06 +00001654 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001655 if (!wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001656 ngx_add_timer(wev, clcf->send_timeout);
1657 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001658
Igor Sysoev924bd792004-10-11 15:07:03 +00001659 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001660 ngx_http_close_request(r, 0);
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001661 return NGX_ERROR;
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001662 }
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001663
1664 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001665}
1666
1667
Igor Sysoev899b44e2005-05-12 14:58:06 +00001668static void
1669ngx_http_writer(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001670{
1671 int rc;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001672 ngx_event_t *wev;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001673 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001674 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001675
Igor Sysoev899b44e2005-05-12 14:58:06 +00001676 c = r->connection;
1677 wev = c->write;
Igor Sysoev160d7742003-11-19 16:26:41 +00001678
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001679 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1680 "http writer handler: \"%V?%V\"", &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001681
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001682 if (wev->timedout) {
Igor Sysoevef066482004-06-21 15:59:32 +00001683 if (!wev->delayed) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001684 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
1685 "client timed out");
1686 c->timedout = 1;
Igor Sysoev055951d2005-10-21 19:12:18 +00001687
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001688 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001689 return;
1690 }
1691
1692 wev->timedout = 0;
Igor Sysoevef066482004-06-21 15:59:32 +00001693 wev->delayed = 0;
Igor Sysoev73a73b52004-06-20 19:54:15 +00001694
1695 if (!wev->ready) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001696 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001697 ngx_add_timer(wev, clcf->send_timeout);
1698
Igor Sysoev924bd792004-10-11 15:07:03 +00001699 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001700 ngx_http_close_request(r, 0);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001701 }
1702
1703 return;
1704 }
1705
1706 } else {
Igor Sysoevef066482004-06-21 15:59:32 +00001707 if (wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001708 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1709 "http writer delayed");
Igor Sysoevef066482004-06-21 15:59:32 +00001710
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001711 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001712
Igor Sysoev924bd792004-10-11 15:07:03 +00001713 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001714 ngx_http_close_request(r, 0);
Igor Sysoevef066482004-06-21 15:59:32 +00001715 }
1716
Igor Sysoev73a73b52004-06-20 19:54:15 +00001717 return;
1718 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001719 }
1720
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001721 rc = ngx_http_output_filter(r, NULL);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001722
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001723 if (c->destroyed) {
1724 return;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001725 }
1726
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001727 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
1728 "http writer output filter: %d, \"%V?%V\"",
1729 rc, &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001730
1731 if (rc == NGX_AGAIN) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001732 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001733 if (!wev->ready && !wev->delayed) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001734 ngx_add_timer(wev, clcf->send_timeout);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001735 }
1736
Igor Sysoev924bd792004-10-11 15:07:03 +00001737 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001738 ngx_http_close_request(r, 0);
Igor Sysoev0a280a32003-10-12 16:49:16 +00001739 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001740
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001741 if (r == r->main) {
1742 return;
1743 }
1744
1745 rc = NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001746 }
1747
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001748 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1749 "http writer done: \"%V?%V\"", &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001750
Igor Sysoev0a280a32003-10-12 16:49:16 +00001751 ngx_http_finalize_request(r, rc);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001752}
1753
1754
Igor Sysoev899b44e2005-05-12 14:58:06 +00001755static void
1756ngx_http_block_read(ngx_http_request_t *r)
1757{
1758 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1759 "http read blocked");
Igor Sysoev42feecb2002-12-15 06:25:09 +00001760
Igor Sysoev73009772003-02-06 17:21:13 +00001761 /* aio does not call this handler */
1762
Igor Sysoev899b44e2005-05-12 14:58:06 +00001763 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
1764 && r->connection->read->active)
1765 {
1766 if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0)
1767 == NGX_ERROR)
1768 {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001769 ngx_http_close_request(r, 0);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001770 }
Igor Sysoev73009772003-02-06 17:21:13 +00001771 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001772}
1773
1774
Igor Sysoevc1571722005-03-19 12:38:37 +00001775static void
1776ngx_http_set_keepalive(ngx_http_request_t *r)
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001777{
Igor Sysoev924bd792004-10-11 15:07:03 +00001778 int tcp_nodelay;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001779 ngx_int_t i;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001780 ngx_buf_t *b, *f;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001781 ngx_event_t *rev, *wev;
1782 ngx_connection_t *c;
Igor Sysoevdd888c42004-09-21 05:38:28 +00001783 ngx_http_connection_t *hc;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001784 ngx_http_core_srv_conf_t *cscf;
1785 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001786
Igor Sysoev6253ca12003-05-27 12:18:54 +00001787 c = r->connection;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001788 rev = c->read;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001789
Igor Sysoeve04084c2004-01-26 08:52:49 +00001790 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001791
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001792 c->log->action = "closing request";
Igor Sysoevdd888c42004-09-21 05:38:28 +00001793
1794 hc = r->http_connection;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001795 b = r->header_in;
1796
Igor Sysoev236e0452004-09-23 16:39:34 +00001797 if (b->pos < b->last) {
Igor Sysoevf7abd722004-09-23 06:32:00 +00001798
Igor Sysoev236e0452004-09-23 16:39:34 +00001799 /* the pipelined request */
Igor Sysoevf7abd722004-09-23 06:32:00 +00001800
1801 if (b != c->buffer) {
1802
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001803 /*
1804 * If the large header buffers were allocated while the previous
1805 * request processing then we do not use c->buffer for
1806 * the pipelined request (see ngx_http_init_request()).
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001807 *
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001808 * Now we would move the large header buffers to the free list.
1809 */
Igor Sysoevf7abd722004-09-23 06:32:00 +00001810
1811 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1812
1813 if (hc->free == NULL) {
1814 hc->free = ngx_palloc(c->pool,
1815 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev236e0452004-09-23 16:39:34 +00001816
Igor Sysoevf7abd722004-09-23 06:32:00 +00001817 if (hc->free == NULL) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001818 ngx_http_close_request(r, 0);
Igor Sysoevf7abd722004-09-23 06:32:00 +00001819 return;
1820 }
1821 }
1822
1823 for (i = 0; i < hc->nbusy - 1; i++) {
1824 f = hc->busy[i];
1825 hc->free[hc->nfree++] = f;
1826 f->pos = f->start;
1827 f->last = f->start;
1828 }
1829
1830 hc->busy[0] = b;
1831 hc->nbusy = 1;
1832 }
1833 }
1834
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001835 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1836
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001837 ngx_http_request_done(r, 0);
1838
Igor Sysoevdd888c42004-09-21 05:38:28 +00001839 c->data = hc;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001840
Igor Sysoevfa73aac2003-05-21 13:28:21 +00001841 ngx_add_timer(rev, clcf->keepalive_timeout);
1842
Igor Sysoev899b44e2005-05-12 14:58:06 +00001843 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001844 ngx_http_close_connection(c);
1845 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00001846 }
1847
Igor Sysoev7b6062a2004-02-12 20:57:10 +00001848 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001849 wev->handler = ngx_http_empty_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001850
Igor Sysoev369145c2004-05-28 15:49:23 +00001851 if (b->pos < b->last) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001852
Igor Sysoeve04084c2004-01-26 08:52:49 +00001853 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
Igor Sysoev6253ca12003-05-27 12:18:54 +00001854
Igor Sysoev055951d2005-10-21 19:12:18 +00001855#if (NGX_STAT_STUB)
1856 ngx_atomic_fetch_add(ngx_stat_reading, 1);
1857#endif
1858
Igor Sysoevdd888c42004-09-21 05:38:28 +00001859 hc->pipeline = 1;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001860 c->log->action = "reading client pipelined request line";
Igor Sysoev055951d2005-10-21 19:12:18 +00001861
Igor Sysoevd581fd52003-05-13 16:02:32 +00001862 ngx_http_init_request(rev);
1863 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001864 }
1865
Igor Sysoevdd888c42004-09-21 05:38:28 +00001866 hc->pipeline = 0;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001867
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001868 /*
1869 * To keep a memory footprint as small as possible for an idle
1870 * keepalive connection we try to free the ngx_http_request_t and
1871 * c->buffer's memory if they were allocated outside the c->pool.
1872 * The large header buffers are always allocated outside the c->pool and
1873 * are freed too.
1874 */
1875
Igor Sysoev236e0452004-09-23 16:39:34 +00001876 if (ngx_pfree(c->pool, r) == NGX_OK) {
1877 hc->request = NULL;
1878 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00001879
Igor Sysoev236e0452004-09-23 16:39:34 +00001880 b = c->buffer;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001881
Igor Sysoev236e0452004-09-23 16:39:34 +00001882 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001883
1884 /*
1885 * the special note for ngx_http_keepalive_handler() that
1886 * c->buffer's memory was freed
1887 */
1888
Igor Sysoev236e0452004-09-23 16:39:34 +00001889 b->pos = NULL;
1890
1891 } else {
1892 b->pos = b->start;
1893 b->last = b->start;
1894 }
1895
Igor Sysoev1b735832004-11-11 14:07:14 +00001896 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00001897 hc->free, hc->nfree);
1898
1899 if (hc->free) {
1900 for (i = 0; i < hc->nfree; i++) {
1901 ngx_pfree(c->pool, hc->free[i]);
1902 hc->free[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001903 }
1904
Igor Sysoev236e0452004-09-23 16:39:34 +00001905 hc->nfree = 0;
1906 }
1907
Igor Sysoev1b735832004-11-11 14:07:14 +00001908 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00001909 hc->busy, hc->nbusy);
1910
1911 if (hc->busy) {
1912 for (i = 0; i < hc->nbusy; i++) {
1913 ngx_pfree(c->pool, hc->busy[i]);
1914 hc->busy[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001915 }
1916
Igor Sysoev236e0452004-09-23 16:39:34 +00001917 hc->nbusy = 0;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001918 }
1919
Igor Sysoev899b44e2005-05-12 14:58:06 +00001920 rev->handler = ngx_http_keepalive_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001921
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001922 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
1923 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
1924 ngx_http_close_connection(c);
1925 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001926 }
1927 }
1928
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001929 c->log->action = "keepalive";
Igor Sysoev6a644c62003-03-04 06:33:48 +00001930
Igor Sysoev67f450d2004-06-01 06:04:46 +00001931 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
Igor Sysoevc1571722005-03-19 12:38:37 +00001932 if (ngx_tcp_push(c->fd) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00001933 ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
1934 ngx_http_close_connection(c);
1935 return;
Igor Sysoev9cf78302003-06-04 17:28:33 +00001936 }
Igor Sysoev924bd792004-10-11 15:07:03 +00001937
Igor Sysoev67f450d2004-06-01 06:04:46 +00001938 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
Igor Sysoev42b12b32004-12-02 18:40:46 +00001939 tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
Igor Sysoev924bd792004-10-11 15:07:03 +00001940
1941 } else {
Igor Sysoev42b12b32004-12-02 18:40:46 +00001942 tcp_nodelay = 1;
1943 }
Igor Sysoev924bd792004-10-11 15:07:03 +00001944
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001945 if (tcp_nodelay
1946 && clcf->tcp_nodelay
1947 && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
1948 {
Igor Sysoev42b12b32004-12-02 18:40:46 +00001949 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
Igor Sysoev924bd792004-10-11 15:07:03 +00001950
Igor Sysoev42b12b32004-12-02 18:40:46 +00001951 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
Igor Sysoevcdf609a2006-04-17 19:55:41 +00001952 (const void *) &tcp_nodelay, sizeof(int))
1953 == -1)
Igor Sysoev42b12b32004-12-02 18:40:46 +00001954 {
1955 ngx_connection_error(c, ngx_socket_errno,
1956 "setsockopt(TCP_NODELAY) failed");
1957 ngx_http_close_connection(c);
1958 return;
Igor Sysoev924bd792004-10-11 15:07:03 +00001959 }
Igor Sysoev42b12b32004-12-02 18:40:46 +00001960
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001961 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
Igor Sysoev9cf78302003-06-04 17:28:33 +00001962 }
1963
Igor Sysoevf7abd722004-09-23 06:32:00 +00001964#if 0
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001965 /* if ngx_http_request_t was freed then we need some other place */
Igor Sysoevc83f6832004-06-24 07:53:37 +00001966 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001967#endif
Igor Sysoevc83f6832004-06-24 07:53:37 +00001968
Igor Sysoevb5faed22003-10-29 08:30:44 +00001969 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001970 ngx_http_keepalive_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00001971 }
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001972}
1973
1974
Igor Sysoevc1571722005-03-19 12:38:37 +00001975static void
1976ngx_http_keepalive_handler(ngx_event_t *rev)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001977{
Igor Sysoevc1571722005-03-19 12:38:37 +00001978 size_t size;
1979 ssize_t n;
1980 ngx_buf_t *b;
1981 ngx_connection_t *c;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001982
Igor Sysoev0ad25372004-07-16 06:33:35 +00001983 c = rev->data;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001984
Igor Sysoeve04084c2004-01-26 08:52:49 +00001985 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
Igor Sysoev1af7c822002-09-13 14:47:42 +00001986
Igor Sysoevdc479b42003-03-20 16:09:44 +00001987 if (rev->timedout) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001988 ngx_http_close_connection(c);
1989 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00001990 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001991
Igor Sysoevf6906042004-11-25 16:17:31 +00001992#if (NGX_HAVE_KQUEUE)
Igor Sysoev236e0452004-09-23 16:39:34 +00001993
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001994 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoevcdc46302005-12-07 14:51:31 +00001995 if (rev->pending_eof) {
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001996 c->log->handler = NULL;
Igor Sysoev236e0452004-09-23 16:39:34 +00001997 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
Igor Sysoev1b735832004-11-11 14:07:14 +00001998 "kevent() reported that client %V closed "
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001999 "keepalive connection", &c->addr_text);
Igor Sysoev42b12b32004-12-02 18:40:46 +00002000#if (NGX_HTTP_SSL)
2001 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00002002 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00002003 }
2004#endif
Igor Sysoev236e0452004-09-23 16:39:34 +00002005 ngx_http_close_connection(c);
2006 return;
2007 }
2008 }
2009
2010#endif
2011
Igor Sysoev236e0452004-09-23 16:39:34 +00002012 b = c->buffer;
2013 size = b->end - b->start;
2014
2015 if (b->pos == NULL) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002016
2017 /*
2018 * The c->buffer's memory was freed by ngx_http_set_keepalive().
2019 * However, the c->buffer->start and c->buffer->end were not changed
2020 * to keep the buffer size.
2021 */
2022
Igor Sysoevc1571722005-03-19 12:38:37 +00002023 b->pos = ngx_palloc(c->pool, size);
2024 if (b->pos == NULL) {
Igor Sysoev236e0452004-09-23 16:39:34 +00002025 ngx_http_close_connection(c);
2026 return;
2027 }
2028
2029 b->start = b->pos;
2030 b->last = b->pos;
2031 b->end = b->pos + size;
2032 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00002033
Igor Sysoev0a280a32003-10-12 16:49:16 +00002034 /*
2035 * MSIE closes a keepalive connection with RST flag
2036 * so we ignore ECONNRESET here.
2037 */
Igor Sysoevb7387572003-03-11 20:38:13 +00002038
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002039 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
Igor Sysoevb7387572003-03-11 20:38:13 +00002040 ngx_set_socket_errno(0);
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00002041
Igor Sysoev236e0452004-09-23 16:39:34 +00002042 n = c->recv(c, b->last, size);
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002043 c->log_error = NGX_ERROR_INFO;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002044
Igor Sysoevd581fd52003-05-13 16:02:32 +00002045 if (n == NGX_AGAIN) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002046 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002047 ngx_http_close_connection(c);
2048 }
2049
Igor Sysoevd581fd52003-05-13 16:02:32 +00002050 return;
2051 }
2052
2053 if (n == NGX_ERROR) {
2054 ngx_http_close_connection(c);
2055 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00002056 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002057
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002058 c->log->handler = NULL;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002059
2060 if (n == 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +00002061 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002062 "client %V closed keepalive connection", &c->addr_text);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002063 ngx_http_close_connection(c);
2064 return;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002065 }
2066
Igor Sysoevf7abd722004-09-23 06:32:00 +00002067 b->last += n;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002068
Igor Sysoev055951d2005-10-21 19:12:18 +00002069#if (NGX_STAT_STUB)
2070 ngx_atomic_fetch_add(ngx_stat_reading, 1);
2071#endif
2072
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002073 c->log->handler = ngx_http_log_error;
2074 c->log->action = "reading client request line";
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002075
Igor Sysoevd581fd52003-05-13 16:02:32 +00002076 ngx_http_init_request(rev);
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002077}
2078
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002079
Igor Sysoevc1571722005-03-19 12:38:37 +00002080static void
2081ngx_http_set_lingering_close(ngx_http_request_t *r)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002082{
Igor Sysoev0a280a32003-10-12 16:49:16 +00002083 ngx_event_t *rev, *wev;
Igor Sysoevb7387572003-03-11 20:38:13 +00002084 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002085 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002086
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002087 c = r->connection;
Igor Sysoev9b25d692003-01-26 21:08:14 +00002088
Igor Sysoev6253ca12003-05-27 12:18:54 +00002089 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002090
Igor Sysoev0a280a32003-10-12 16:49:16 +00002091 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002092 rev->handler = ngx_http_lingering_close_handler;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002093
Igor Sysoev208eed22005-10-07 13:30:52 +00002094 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
Igor Sysoev6253ca12003-05-27 12:18:54 +00002095 ngx_add_timer(rev, clcf->lingering_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +00002096
Igor Sysoev899b44e2005-05-12 14:58:06 +00002097 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00002098 ngx_http_close_request(r, 0);
Igor Sysoev0a280a32003-10-12 16:49:16 +00002099 return;
2100 }
2101
2102 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002103 wev->handler = ngx_http_empty_handler;
Igor Sysoev0a280a32003-10-12 16:49:16 +00002104
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002105 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2106 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
2107 ngx_http_close_request(r, 0);
2108 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00002109 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002110 }
2111
Igor Sysoevb7387572003-03-11 20:38:13 +00002112 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00002113 ngx_connection_error(c, ngx_socket_errno,
2114 ngx_shutdown_socket_n " failed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002115 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002116 return;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002117 }
2118
Igor Sysoevb5faed22003-10-29 08:30:44 +00002119 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002120 ngx_http_lingering_close_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00002121 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002122}
2123
2124
Igor Sysoevc1571722005-03-19 12:38:37 +00002125static void
2126ngx_http_lingering_close_handler(ngx_event_t *rev)
Igor Sysoev42feecb2002-12-15 06:25:09 +00002127{
Igor Sysoevdc479b42003-03-20 16:09:44 +00002128 ssize_t n;
2129 ngx_msec_t timer;
2130 ngx_connection_t *c;
2131 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002132 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002133 u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
Igor Sysoev1af7c822002-09-13 14:47:42 +00002134
Igor Sysoev6253ca12003-05-27 12:18:54 +00002135 c = rev->data;
2136 r = c->data;
Igor Sysoev86de4cb2003-01-30 07:28:09 +00002137
Igor Sysoeve04084c2004-01-26 08:52:49 +00002138 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2139 "http lingering close handler");
Igor Sysoevdc479b42003-03-20 16:09:44 +00002140
2141 if (rev->timedout) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002142 c->timedout = 1;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002143 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002144 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002145 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002146
Igor Sysoevc0247302004-06-27 18:01:57 +00002147 timer = r->lingering_time - ngx_time();
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002148 if (timer <= 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002149 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002150 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002151 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002152
Igor Sysoevdc479b42003-03-20 16:09:44 +00002153 do {
Igor Sysoevf7abd722004-09-23 06:32:00 +00002154 n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002155
Igor Sysoeve04084c2004-01-26 08:52:49 +00002156 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002157
Igor Sysoevdc479b42003-03-20 16:09:44 +00002158 if (n == NGX_ERROR || n == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002159 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002160 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002161 }
2162
2163 } while (rev->ready);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002164
Igor Sysoev899b44e2005-05-12 14:58:06 +00002165 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00002166 ngx_http_close_request(r, 0);
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002167 return;
2168 }
2169
Igor Sysoevf7abd722004-09-23 06:32:00 +00002170 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2171
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002172 timer *= 1000;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002173
Igor Sysoev6253ca12003-05-27 12:18:54 +00002174 if (timer > clcf->lingering_timeout) {
2175 timer = clcf->lingering_timeout;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002176 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002177
Igor Sysoevdc479b42003-03-20 16:09:44 +00002178 ngx_add_timer(rev, timer);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002179}
2180
Igor Sysoev2b542382002-08-20 14:48:28 +00002181
Igor Sysoevc1571722005-03-19 12:38:37 +00002182void
2183ngx_http_empty_handler(ngx_event_t *wev)
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002184{
Igor Sysoeve04084c2004-01-26 08:52:49 +00002185 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002186
2187 return;
2188}
2189
2190
Igor Sysoev899b44e2005-05-12 14:58:06 +00002191void
2192ngx_http_request_empty_handler(ngx_http_request_t *r)
2193{
2194 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002195 "http request empty handler");
Igor Sysoev899b44e2005-05-12 14:58:06 +00002196
2197 return;
2198}
2199
2200
Igor Sysoevc1571722005-03-19 12:38:37 +00002201ngx_int_t
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002202ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002203{
Igor Sysoev369145c2004-05-28 15:49:23 +00002204 ngx_buf_t *b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002205 ngx_chain_t out;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002206
Igor Sysoevc1571722005-03-19 12:38:37 +00002207 b = ngx_calloc_buf(r->pool);
2208 if (b == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +00002209 return NGX_ERROR;
2210 }
2211
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002212 if (flags & NGX_HTTP_LAST) {
2213 b->last_buf = 1;
2214 }
2215
2216 if (flags & NGX_HTTP_FLUSH) {
2217 b->flush = 1;
2218 }
2219
Igor Sysoev369145c2004-05-28 15:49:23 +00002220 out.buf = b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002221 out.next = NULL;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002222
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002223 return ngx_http_output_filter(r, &out);
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002224}
2225
2226
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002227static ngx_int_t
2228ngx_http_post_action(ngx_http_request_t *r)
2229{
2230 ngx_http_core_loc_conf_t *clcf;
2231
2232 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2233
2234 if (clcf->post_action.data == NULL) {
2235 return NGX_DECLINED;
2236 }
2237
Igor Sysoev8fea8852006-03-15 09:53:04 +00002238 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2239 "post action: \"%V\"", &clcf->post_action);
2240
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002241 r->http_version = NGX_HTTP_VERSION_9;
2242 r->header_only = 1;
Igor Sysoev6d16e1e2006-04-05 13:40:54 +00002243 r->post_action = 1;
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002244
2245 ngx_http_internal_redirect(r, &clcf->post_action, NULL);
2246
2247 return NGX_OK;
2248}
2249
2250
2251static void
Igor Sysoev899b44e2005-05-12 14:58:06 +00002252ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error)
Igor Sysoevd581fd52003-05-13 16:02:32 +00002253{
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002254 ngx_connection_t *c;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002255
2256 c = r->connection;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002257
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002258 ngx_http_request_done(r->main, error);
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002259 ngx_http_close_connection(c);
2260}
2261
2262
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002263static void
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002264ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error)
2265{
2266 ngx_log_t *log;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002267 ngx_uint_t i, n;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002268 struct linger linger;
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002269 ngx_http_cleanup_t *cln;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002270 ngx_http_log_ctx_t *ctx;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002271 ngx_http_handler_pt *log_handler;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002272 ngx_http_core_loc_conf_t *clcf;
2273 ngx_http_core_main_conf_t *cmcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002274
Igor Sysoev865c1502003-11-30 20:03:18 +00002275 log = r->connection->log;
2276
2277 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002278
2279 if (r->pool == NULL) {
Igor Sysoev90c08142005-07-25 09:41:38 +00002280 ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002281 return;
2282 }
2283
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002284 for (cln = r->cleanup; cln; cln = cln->next) {
2285 if (cln->handler) {
2286 cln->handler(cln->data);
2287 }
2288 }
2289
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002290#if (NGX_STAT_STUB)
Igor Sysoev055951d2005-10-21 19:12:18 +00002291
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002292 if (r->stat_reading) {
Igor Sysoev78452232005-10-12 13:50:36 +00002293 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002294 }
2295
2296 if (r->stat_writing) {
Igor Sysoev78452232005-10-12 13:50:36 +00002297 ngx_atomic_fetch_add(ngx_stat_writing, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002298 }
Igor Sysoev055951d2005-10-21 19:12:18 +00002299
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002300#endif
2301
Igor Sysoev669e3312003-12-22 09:40:48 +00002302 if (error && r->headers_out.status == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002303 r->headers_out.status = error;
2304 }
2305
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002306 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2307
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002308 log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
2309 n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
2310 for (i = 0; i < n; i++) {
2311 log_handler[i](r);
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002312 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00002313
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002314 if (r->connection->timedout) {
2315 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2316
2317 if (clcf->reset_timedout_connection) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002318 linger.l_onoff = 1;
2319 linger.l_linger = 0;
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002320
2321 if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
Igor Sysoev899b44e2005-05-12 14:58:06 +00002322 (const void *) &linger, sizeof(struct linger)) == -1)
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002323 {
2324 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
2325 "setsockopt(SO_LINGER) failed");
2326 }
2327 }
2328 }
2329
Igor Sysoev899b44e2005-05-12 14:58:06 +00002330 /* the various request strings were allocated from r->pool */
Igor Sysoev865c1502003-11-30 20:03:18 +00002331 ctx = log->data;
Igor Sysoev1b735832004-11-11 14:07:14 +00002332 ctx->request = NULL;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002333
Igor Sysoevc83f6832004-06-24 07:53:37 +00002334 r->request_line.len = 0;
2335
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002336 r->connection->destroyed = 1;
2337
Igor Sysoevd581fd52003-05-13 16:02:32 +00002338 ngx_destroy_pool(r->pool);
2339}
2340
2341
Igor Sysoev90c08142005-07-25 09:41:38 +00002342static void
Igor Sysoevc1571722005-03-19 12:38:37 +00002343ngx_http_close_connection(ngx_connection_t *c)
Igor Sysoev6b863e32003-05-12 15:52:24 +00002344{
Igor Sysoev02025fd2005-01-18 13:03:58 +00002345 ngx_pool_t *pool;
2346
Igor Sysoeve04084c2004-01-26 08:52:49 +00002347 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev54498db2004-02-11 17:08:49 +00002348 "close http connection: %d", c->fd);
Igor Sysoev6b863e32003-05-12 15:52:24 +00002349
Igor Sysoevceb99292005-09-06 16:09:32 +00002350#if (NGX_HTTP_SSL)
Igor Sysoev924bd792004-10-11 15:07:03 +00002351
2352 if (c->ssl) {
2353 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002354 c->ssl->handler = ngx_http_close_connection;
Igor Sysoev924bd792004-10-11 15:07:03 +00002355 return;
2356 }
2357 }
2358
2359#endif
2360
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002361#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +00002362 ngx_atomic_fetch_add(ngx_stat_active, -1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002363#endif
2364
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002365 c->destroyed = 1;
2366
Igor Sysoev02025fd2005-01-18 13:03:58 +00002367 pool = c->pool;
2368
Igor Sysoev59cf56c2004-09-07 15:29:22 +00002369 ngx_close_connection(c);
Igor Sysoev02025fd2005-01-18 13:03:58 +00002370
Igor Sysoevc1571722005-03-19 12:38:37 +00002371 ngx_destroy_pool(pool);
Igor Sysoev2ba1ee02002-10-04 17:58:04 +00002372}
2373
2374
Igor Sysoevc1571722005-03-19 12:38:37 +00002375static u_char *
2376ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002377{
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002378 u_char *p;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002379 ngx_http_request_t *r;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002380 ngx_http_log_ctx_t *ctx;
Igor Sysoev7578ec92003-06-02 15:24:30 +00002381
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002382 if (log->action) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002383 p = ngx_snprintf(buf, len, " while %s", log->action);
Igor Sysoev1b735832004-11-11 14:07:14 +00002384 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002385 buf = p;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002386 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002387
Igor Sysoev899b44e2005-05-12 14:58:06 +00002388 ctx = log->data;
2389
Igor Sysoevc04deca2005-03-28 14:43:02 +00002390 p = ngx_snprintf(buf, len, ", client: %V", ctx->client);
Igor Sysoev899b44e2005-05-12 14:58:06 +00002391 len -= p - buf;
Igor Sysoev1b735832004-11-11 14:07:14 +00002392
Igor Sysoevc04deca2005-03-28 14:43:02 +00002393 r = ctx->request;
2394
Igor Sysoev899b44e2005-05-12 14:58:06 +00002395 if (r) {
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002396 return r->log_handler(r, ctx->current_request, p, len);
Igor Sysoev1b735832004-11-11 14:07:14 +00002397 }
2398
Igor Sysoev899b44e2005-05-12 14:58:06 +00002399 return p;
2400}
2401
2402
2403static u_char *
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002404ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
2405 u_char *buf, size_t len)
Igor Sysoev899b44e2005-05-12 14:58:06 +00002406{
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002407 u_char *p;
2408 ngx_http_upstream_t *u;
2409 ngx_peer_connection_t *peer;
Igor Sysoev1b735832004-11-11 14:07:14 +00002410
Igor Sysoevc04deca2005-03-28 14:43:02 +00002411 if (r->server_name.data) {
2412 p = ngx_snprintf(buf, len, ", server: %V", &r->server_name);
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002413 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002414 buf = p;
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002415 }
2416
Igor Sysoevc04deca2005-03-28 14:43:02 +00002417 if (r->unparsed_uri.data) {
2418 p = ngx_snprintf(buf, len, ", URL: \"%V\"", &r->unparsed_uri);
2419 len -= p - buf;
2420 buf = p;
Igor Sysoev1b735832004-11-11 14:07:14 +00002421
Igor Sysoevc04deca2005-03-28 14:43:02 +00002422 } else {
2423 if (r->request_line.data == NULL && r->request_start) {
2424 for (p = r->request_start; p < r->header_in->last; p++) {
2425 if (*p == CR || *p == LF) {
2426 break;
2427 }
2428 }
2429
2430 r->request_line.len = p - r->request_start;
2431 r->request_line.data = r->request_start;
2432 }
2433
2434 if (r->request_line.len) {
2435 p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
2436 len -= p - buf;
2437 buf = p;
2438 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002439 }
2440
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002441 if (r != sr) {
2442 p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
2443 len -= p - buf;
2444 buf = p;
2445 }
2446
2447 u = sr->upstream;
2448
2449 if (u) {
2450 peer = &u->peer;
2451
2452 p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
2453 &u->conf->schema,
2454 &peer->peers->peer[peer->cur_peer].name,
2455 peer->peers->peer[peer->cur_peer].uri_separator,
2456 &u->uri);
2457 len -= p - buf;
2458 buf = p;
2459 }
2460
Igor Sysoevc04deca2005-03-28 14:43:02 +00002461 if (r->headers_in.host) {
2462 p = ngx_snprintf(buf, len, ", host: \"%V\"",
2463 &r->headers_in.host->value);
2464 len -= p - buf;
2465 buf = p;
2466 }
2467
2468 if (r->headers_in.referer) {
2469 p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
2470 &r->headers_in.referer->value);
2471 buf = p;
2472 }
2473
2474 return buf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00002475}