blob: 0145fe7d4b98ddd02ecd452d1dea6ebf259c13c7 [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++) {
856 h->lowcase_key[i] = ngx_tolower(h->lowcase_key[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 Sysoev44d87222006-05-06 16:28:56 +00001272#if (NGX_HTTP_SSL)
1273
1274 if (r->connection->ssl) {
1275 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
1276
1277 if (sscf->verify) {
1278 rc = SSL_get_verify_result(r->connection->ssl->connection);
1279
1280 if (rc != X509_V_OK) {
1281 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1282 "client SSL certificate verify error: %l ", rc);
1283 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
1284 return NGX_ERROR;
1285 }
1286
1287 if (SSL_get_peer_certificate(r->connection->ssl->connection)
1288 == NULL)
1289 {
1290 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1291 "client sent no required SSL certificate");
1292 ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
1293 return NGX_ERROR;
1294 }
1295 }
1296 }
1297
1298#endif
1299
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001300 if (r->headers_in.connection) {
1301 if (r->headers_in.connection->value.len == 5
1302 && ngx_strcasecmp(r->headers_in.connection->value.data, "close")
Igor Sysoev899b44e2005-05-12 14:58:06 +00001303 == 0)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001304 {
1305 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1306
1307 } else if (r->headers_in.connection->value.len == 10
1308 && ngx_strcasecmp(r->headers_in.connection->value.data,
Igor Sysoev899b44e2005-05-12 14:58:06 +00001309 "keep-alive") == 0)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001310 {
1311 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1312
1313 if (r->headers_in.keep_alive) {
1314 r->headers_in.keep_alive_n =
Igor Sysoevc1571722005-03-19 12:38:37 +00001315 ngx_atotm(r->headers_in.keep_alive->value.data,
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001316 r->headers_in.keep_alive->value.len);
1317 }
1318 }
1319 }
1320
Igor Sysoev2f657222004-06-16 15:32:11 +00001321 if (r->headers_in.user_agent) {
1322
1323 /*
1324 * check some widespread browsers while the headers are still
1325 * in CPU cache
1326 */
1327
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001328 user_agent = r->headers_in.user_agent->value.data;
1329
1330 ua = (u_char *) ngx_strstr(user_agent, "MSIE");
1331
1332 if (ua && ua + 8 < user_agent + r->headers_in.user_agent->value.len) {
1333
Igor Sysoev2f657222004-06-16 15:32:11 +00001334 r->headers_in.msie = 1;
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001335
Igor Sysoev2f657222004-06-16 15:32:11 +00001336 if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') {
1337 r->headers_in.msie4 = 1;
1338 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001339
1340#if 0
1341 /* MSIE ignores the SSL "close notify" alert */
Igor Sysoev42b12b32004-12-02 18:40:46 +00001342 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00001343 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00001344 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001345#endif
Igor Sysoev2f657222004-06-16 15:32:11 +00001346 }
Igor Sysoev85cccfb2004-09-15 16:00:43 +00001347
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001348 if (ngx_strstr(user_agent, "Opera")) {
Igor Sysoev85cccfb2004-09-15 16:00:43 +00001349 r->headers_in.opera = 1;
1350 r->headers_in.msie = 0;
1351 r->headers_in.msie4 = 0;
1352 }
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001353
1354 if (!r->headers_in.msie && !r->headers_in.opera) {
1355
Igor Sysoeva2c81192004-09-19 18:27:00 +00001356 if (ngx_strstr(user_agent, "Gecko/")) {
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001357 r->headers_in.gecko = 1;
1358
1359 } else if (ngx_strstr(user_agent, "Konqueror")) {
1360 r->headers_in.konqueror = 1;
1361 }
1362 }
Igor Sysoev2f657222004-06-16 15:32:11 +00001363 }
1364
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001365 return NGX_OK;
1366}
1367
1368
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001369static void
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001370ngx_http_find_virtual_server(ngx_http_request_t *r,
1371 ngx_http_virtual_names_t *vn, ngx_uint_t hash)
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001372{
Igor Sysoev305a9d82005-12-26 17:07:48 +00001373 size_t len;
1374 u_char *host;
Igor Sysoev305a9d82005-12-26 17:07:48 +00001375 ngx_http_core_loc_conf_t *clcf;
1376 ngx_http_core_srv_conf_t *cscf;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001377
Igor Sysoev305a9d82005-12-26 17:07:48 +00001378 host = r->headers_in.host->value.data;
1379 len = r->headers_in.host_name_len;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001380
Igor Sysoev305a9d82005-12-26 17:07:48 +00001381 if (vn->hash.buckets) {
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001382 cscf = ngx_hash_find(&vn->hash, hash, host, len);
Igor Sysoev305a9d82005-12-26 17:07:48 +00001383 if (cscf) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001384 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001385 }
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001386 }
1387
Igor Sysoev305a9d82005-12-26 17:07:48 +00001388 if (vn->dns_wildcards && vn->dns_wildcards->hash.buckets) {
1389 cscf = ngx_hash_find_wildcard(vn->dns_wildcards, host, len);
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001390
Igor Sysoev305a9d82005-12-26 17:07:48 +00001391 if (cscf) {
1392 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001393 }
1394 }
1395
Igor Sysoev1765f472006-07-07 16:33:19 +00001396 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1397
1398 if (cscf->wildcard) {
1399 r->server_name.len = len;
1400 r->server_name.data = host;
1401 }
1402
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001403 return;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001404
Igor Sysoev899b44e2005-05-12 14:58:06 +00001405found:
1406
Igor Sysoev305a9d82005-12-26 17:07:48 +00001407 r->server_name.len = len;
1408 r->server_name.data = host;
1409
1410 r->srv_conf = cscf->ctx->srv_conf;
1411 r->loc_conf = cscf->ctx->loc_conf;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001412
1413 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1414 r->connection->log->file = clcf->err_log->file;
1415
1416 if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1417 r->connection->log->log_level = clcf->err_log->log_level;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001418 }
1419
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001420 return;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001421}
1422
1423
Igor Sysoev899b44e2005-05-12 14:58:06 +00001424static void
1425ngx_http_request_handler(ngx_event_t *ev)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001426{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001427 ngx_connection_t *c;
1428 ngx_http_request_t *r;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001429 ngx_http_log_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001430
1431 c = ev->data;
1432 r = c->data;
1433
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001434 ctx = c->log->data;
1435 ctx->current_request = r;
1436
Igor Sysoev899b44e2005-05-12 14:58:06 +00001437 if (ev->write) {
1438 r->write_event_handler(r);
1439
1440 } else {
1441 r->read_event_handler(r);
1442 }
1443}
1444
1445
1446void
1447ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1448{
1449 ngx_http_request_t *pr;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001450 ngx_http_log_ctx_t *ctx;
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001451 ngx_http_core_loc_conf_t *clcf;
1452
Igor Sysoev899b44e2005-05-12 14:58:06 +00001453 if (rc == NGX_DONE) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001454 /* the request pool may be already destroyed */
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001455 return;
1456 }
1457
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001458 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1459 "http finalize request: %d, \"%V?%V\"",
1460 rc, &r->uri, &r->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001461
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001462 if (rc == NGX_ERROR
1463 || rc == NGX_HTTP_REQUEST_TIME_OUT
1464 || r->connection->error)
1465 {
Igor Sysoev7f7846d2006-04-26 09:52:47 +00001466 if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
1467 && r->headers_out.status == 0)
1468 {
1469 r->headers_out.status = NGX_HTTP_CLIENT_CLOSED_REQUEST;
1470 }
1471
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001472 if (ngx_http_post_action(r) == NGX_OK) {
1473 return;
1474 }
1475
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001476 ngx_http_close_request(r, 0);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001477 return;
1478 }
1479
Igor Sysoev7bdb7202006-04-19 15:30:56 +00001480 if (rc >= NGX_HTTP_SPECIAL_RESPONSE
1481 || rc == NGX_HTTP_CREATED
1482 || rc == NGX_HTTP_NO_CONTENT)
1483 {
Igor Sysoevcdc46302005-12-07 14:51:31 +00001484 if (rc == NGX_HTTP_CLOSE) {
1485 ngx_http_close_request(r, rc);
1486 return;
1487 }
1488
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001489 if (r == r->main) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001490 if (r->connection->read->timer_set) {
1491 ngx_del_timer(r->connection->read);
1492 }
1493
1494 if (r->connection->write->timer_set) {
1495 ngx_del_timer(r->connection->write);
1496 }
1497 }
1498
1499 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001500 return;
1501 }
1502
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001503 if (r != r->main || rc == NGX_AGAIN) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001504 if (ngx_http_set_write_handler(r) != NGX_OK) {
1505 return;
1506 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001507 }
1508
1509 r->done = 1;
1510
1511 if (r != r->connection->data) {
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001512 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1513 "http finalize non-active request: \"%V?%V\"",
1514 &r->uri, &r->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001515 return;
1516 }
1517
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001518 if (r != r->main) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001519
1520 pr = r->parent;
1521
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001522 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1523 "http parent request: \"%V?%V\"", &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001524
Igor Sysoev899b44e2005-05-12 14:58:06 +00001525 if (rc != NGX_AGAIN) {
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001526 r->connection->data = pr;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001527 }
1528
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001529 ctx = r->connection->log->data;
1530 ctx->current_request = pr;
1531
Igor Sysoev899b44e2005-05-12 14:58:06 +00001532 if (pr->postponed) {
1533
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001534 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1535 "http request: \"%V?%V\" has postponed",
1536 &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001537
Igor Sysoev899b44e2005-05-12 14:58:06 +00001538 if (rc != NGX_AGAIN && pr->postponed->request == r) {
1539 pr->postponed = pr->postponed->next;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001540 }
1541
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001542 if (r->fast_subrequest) {
Igor Sysoevac72bd12006-05-04 15:32:46 +00001543
1544 if (rc == NGX_AGAIN) {
1545 r->fast_subrequest = 0;
1546 }
1547
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001548 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1549 "http fast subrequest: \"%V?%V\" done",
1550 &r->uri, &r->args);
1551 return;
1552 }
1553
Igor Sysoevac72bd12006-05-04 15:32:46 +00001554 if (rc != NGX_AGAIN) {
1555 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1556 "http wake parent request: \"%V?%V\"",
1557 &pr->uri, &pr->args);
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001558
Igor Sysoevac72bd12006-05-04 15:32:46 +00001559 pr->write_event_handler(pr);
1560 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001561 }
1562
1563 return;
1564 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001565
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001566 if (rc == NGX_AGAIN) {
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001567 return;
Igor Sysoev5192b362005-07-08 14:34:20 +00001568 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001569
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001570 if (r->connection->buffered) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001571 (void) ngx_http_set_write_handler(r);
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001572 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001573 }
1574
Igor Sysoev6d16e1e2006-04-05 13:40:54 +00001575 if (!r->post_action) {
1576 r->request_complete = 1;
1577 }
1578
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001579 if (ngx_http_post_action(r) == NGX_OK) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001580 return;
1581 }
1582
Igor Sysoev0a280a32003-10-12 16:49:16 +00001583 if (r->connection->read->timer_set) {
1584 ngx_del_timer(r->connection->read);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001585 }
1586
Igor Sysoev0a280a32003-10-12 16:49:16 +00001587 if (r->connection->write->timer_set) {
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001588 r->connection->write->delayed = 0;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001589 ngx_del_timer(r->connection->write);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001590 }
1591
Igor Sysoev24025022005-12-16 15:07:08 +00001592 if (r->connection->destroyed) {
1593 return;
1594 }
1595
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001596 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001597
Igor Sysoevc5991982004-01-16 06:15:48 +00001598 if (!ngx_terminate
Igor Sysoev3f4685f2004-04-25 20:13:21 +00001599 && !ngx_exiting
Igor Sysoevc5991982004-01-16 06:15:48 +00001600 && r->keepalive != 0
1601 && clcf->keepalive_timeout > 0)
1602 {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001603 ngx_http_set_keepalive(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001604 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001605
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001606 } else if (r->lingering_close && clcf->lingering_timeout > 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001607 ngx_http_set_lingering_close(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001608 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001609 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001610
Igor Sysoevc5991982004-01-16 06:15:48 +00001611 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001612}
1613
1614
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001615static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001616ngx_http_set_write_handler(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001617{
Igor Sysoevd581fd52003-05-13 16:02:32 +00001618 ngx_event_t *wev;
Igor Sysoeva9830112003-05-19 16:39:14 +00001619 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001620
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001621 r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
1622
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001623 r->write_event_handler = ngx_http_writer;
1624
Igor Sysoev899b44e2005-05-12 14:58:06 +00001625 wev = r->connection->write;
1626
Igor Sysoevef066482004-06-21 15:59:32 +00001627 if (wev->ready && wev->delayed) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001628 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001629 }
1630
Igor Sysoev899b44e2005-05-12 14:58:06 +00001631 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001632 if (!wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001633 ngx_add_timer(wev, clcf->send_timeout);
1634 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001635
Igor Sysoev924bd792004-10-11 15:07:03 +00001636 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001637 ngx_http_close_request(r, 0);
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001638 return NGX_ERROR;
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001639 }
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001640
1641 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001642}
1643
1644
Igor Sysoev899b44e2005-05-12 14:58:06 +00001645static void
1646ngx_http_writer(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001647{
1648 int rc;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001649 ngx_event_t *wev;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001650 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001651 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001652
Igor Sysoev899b44e2005-05-12 14:58:06 +00001653 c = r->connection;
1654 wev = c->write;
Igor Sysoev160d7742003-11-19 16:26:41 +00001655
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001656 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1657 "http writer handler: \"%V?%V\"", &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001658
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001659 if (wev->timedout) {
Igor Sysoevef066482004-06-21 15:59:32 +00001660 if (!wev->delayed) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001661 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
1662 "client timed out");
1663 c->timedout = 1;
Igor Sysoev055951d2005-10-21 19:12:18 +00001664
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001665 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001666 return;
1667 }
1668
1669 wev->timedout = 0;
Igor Sysoevef066482004-06-21 15:59:32 +00001670 wev->delayed = 0;
Igor Sysoev73a73b52004-06-20 19:54:15 +00001671
1672 if (!wev->ready) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001673 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001674 ngx_add_timer(wev, clcf->send_timeout);
1675
Igor Sysoev924bd792004-10-11 15:07:03 +00001676 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001677 ngx_http_close_request(r, 0);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001678 }
1679
1680 return;
1681 }
1682
1683 } else {
Igor Sysoevef066482004-06-21 15:59:32 +00001684 if (wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001685 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1686 "http writer delayed");
Igor Sysoevef066482004-06-21 15:59:32 +00001687
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001688 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001689
Igor Sysoev924bd792004-10-11 15:07:03 +00001690 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001691 ngx_http_close_request(r, 0);
Igor Sysoevef066482004-06-21 15:59:32 +00001692 }
1693
Igor Sysoev73a73b52004-06-20 19:54:15 +00001694 return;
1695 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001696 }
1697
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001698 rc = ngx_http_output_filter(r, NULL);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001699
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001700 if (c->destroyed) {
1701 return;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001702 }
1703
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001704 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
1705 "http writer output filter: %d, \"%V?%V\"",
1706 rc, &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001707
1708 if (rc == NGX_AGAIN) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001709 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001710 if (!wev->ready && !wev->delayed) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001711 ngx_add_timer(wev, clcf->send_timeout);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001712 }
1713
Igor Sysoev924bd792004-10-11 15:07:03 +00001714 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001715 ngx_http_close_request(r, 0);
Igor Sysoev0a280a32003-10-12 16:49:16 +00001716 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001717
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001718 if (r == r->main) {
1719 return;
1720 }
1721
1722 rc = NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001723 }
1724
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001725 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1726 "http writer done: \"%V?%V\"", &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001727
Igor Sysoev0a280a32003-10-12 16:49:16 +00001728 ngx_http_finalize_request(r, rc);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001729}
1730
1731
Igor Sysoev899b44e2005-05-12 14:58:06 +00001732static void
1733ngx_http_block_read(ngx_http_request_t *r)
1734{
1735 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1736 "http read blocked");
Igor Sysoev42feecb2002-12-15 06:25:09 +00001737
Igor Sysoev73009772003-02-06 17:21:13 +00001738 /* aio does not call this handler */
1739
Igor Sysoev899b44e2005-05-12 14:58:06 +00001740 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
1741 && r->connection->read->active)
1742 {
1743 if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0)
1744 == NGX_ERROR)
1745 {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001746 ngx_http_close_request(r, 0);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001747 }
Igor Sysoev73009772003-02-06 17:21:13 +00001748 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001749}
1750
1751
Igor Sysoevc1571722005-03-19 12:38:37 +00001752static void
1753ngx_http_set_keepalive(ngx_http_request_t *r)
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001754{
Igor Sysoev924bd792004-10-11 15:07:03 +00001755 int tcp_nodelay;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001756 ngx_int_t i;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001757 ngx_buf_t *b, *f;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001758 ngx_event_t *rev, *wev;
1759 ngx_connection_t *c;
Igor Sysoevdd888c42004-09-21 05:38:28 +00001760 ngx_http_connection_t *hc;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001761 ngx_http_core_srv_conf_t *cscf;
1762 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001763
Igor Sysoev6253ca12003-05-27 12:18:54 +00001764 c = r->connection;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001765 rev = c->read;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001766
Igor Sysoeve04084c2004-01-26 08:52:49 +00001767 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001768
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001769 c->log->action = "closing request";
Igor Sysoevdd888c42004-09-21 05:38:28 +00001770
1771 hc = r->http_connection;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001772 b = r->header_in;
1773
Igor Sysoev236e0452004-09-23 16:39:34 +00001774 if (b->pos < b->last) {
Igor Sysoevf7abd722004-09-23 06:32:00 +00001775
Igor Sysoev236e0452004-09-23 16:39:34 +00001776 /* the pipelined request */
Igor Sysoevf7abd722004-09-23 06:32:00 +00001777
1778 if (b != c->buffer) {
1779
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001780 /*
1781 * If the large header buffers were allocated while the previous
1782 * request processing then we do not use c->buffer for
1783 * the pipelined request (see ngx_http_init_request()).
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001784 *
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001785 * Now we would move the large header buffers to the free list.
1786 */
Igor Sysoevf7abd722004-09-23 06:32:00 +00001787
1788 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1789
1790 if (hc->free == NULL) {
1791 hc->free = ngx_palloc(c->pool,
1792 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev236e0452004-09-23 16:39:34 +00001793
Igor Sysoevf7abd722004-09-23 06:32:00 +00001794 if (hc->free == NULL) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001795 ngx_http_close_request(r, 0);
Igor Sysoevf7abd722004-09-23 06:32:00 +00001796 return;
1797 }
1798 }
1799
1800 for (i = 0; i < hc->nbusy - 1; i++) {
1801 f = hc->busy[i];
1802 hc->free[hc->nfree++] = f;
1803 f->pos = f->start;
1804 f->last = f->start;
1805 }
1806
1807 hc->busy[0] = b;
1808 hc->nbusy = 1;
1809 }
1810 }
1811
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001812 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1813
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001814 ngx_http_request_done(r, 0);
1815
Igor Sysoevdd888c42004-09-21 05:38:28 +00001816 c->data = hc;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001817
Igor Sysoevfa73aac2003-05-21 13:28:21 +00001818 ngx_add_timer(rev, clcf->keepalive_timeout);
1819
Igor Sysoev899b44e2005-05-12 14:58:06 +00001820 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001821 ngx_http_close_connection(c);
1822 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00001823 }
1824
Igor Sysoev7b6062a2004-02-12 20:57:10 +00001825 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001826 wev->handler = ngx_http_empty_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001827
Igor Sysoev369145c2004-05-28 15:49:23 +00001828 if (b->pos < b->last) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001829
Igor Sysoeve04084c2004-01-26 08:52:49 +00001830 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
Igor Sysoev6253ca12003-05-27 12:18:54 +00001831
Igor Sysoev055951d2005-10-21 19:12:18 +00001832#if (NGX_STAT_STUB)
1833 ngx_atomic_fetch_add(ngx_stat_reading, 1);
1834#endif
1835
Igor Sysoevdd888c42004-09-21 05:38:28 +00001836 hc->pipeline = 1;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001837 c->log->action = "reading client pipelined request line";
Igor Sysoev055951d2005-10-21 19:12:18 +00001838
Igor Sysoevd581fd52003-05-13 16:02:32 +00001839 ngx_http_init_request(rev);
1840 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001841 }
1842
Igor Sysoevdd888c42004-09-21 05:38:28 +00001843 hc->pipeline = 0;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001844
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001845 /*
1846 * To keep a memory footprint as small as possible for an idle
1847 * keepalive connection we try to free the ngx_http_request_t and
1848 * c->buffer's memory if they were allocated outside the c->pool.
1849 * The large header buffers are always allocated outside the c->pool and
1850 * are freed too.
1851 */
1852
Igor Sysoev236e0452004-09-23 16:39:34 +00001853 if (ngx_pfree(c->pool, r) == NGX_OK) {
1854 hc->request = NULL;
1855 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00001856
Igor Sysoev236e0452004-09-23 16:39:34 +00001857 b = c->buffer;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001858
Igor Sysoev236e0452004-09-23 16:39:34 +00001859 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001860
1861 /*
1862 * the special note for ngx_http_keepalive_handler() that
1863 * c->buffer's memory was freed
1864 */
1865
Igor Sysoev236e0452004-09-23 16:39:34 +00001866 b->pos = NULL;
1867
1868 } else {
1869 b->pos = b->start;
1870 b->last = b->start;
1871 }
1872
Igor Sysoev1b735832004-11-11 14:07:14 +00001873 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00001874 hc->free, hc->nfree);
1875
1876 if (hc->free) {
1877 for (i = 0; i < hc->nfree; i++) {
1878 ngx_pfree(c->pool, hc->free[i]);
1879 hc->free[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001880 }
1881
Igor Sysoev236e0452004-09-23 16:39:34 +00001882 hc->nfree = 0;
1883 }
1884
Igor Sysoev1b735832004-11-11 14:07:14 +00001885 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00001886 hc->busy, hc->nbusy);
1887
1888 if (hc->busy) {
1889 for (i = 0; i < hc->nbusy; i++) {
1890 ngx_pfree(c->pool, hc->busy[i]);
1891 hc->busy[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001892 }
1893
Igor Sysoev236e0452004-09-23 16:39:34 +00001894 hc->nbusy = 0;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001895 }
1896
Igor Sysoev899b44e2005-05-12 14:58:06 +00001897 rev->handler = ngx_http_keepalive_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001898
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001899 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
1900 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
1901 ngx_http_close_connection(c);
1902 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001903 }
1904 }
1905
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001906 c->log->action = "keepalive";
Igor Sysoev6a644c62003-03-04 06:33:48 +00001907
Igor Sysoev67f450d2004-06-01 06:04:46 +00001908 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
Igor Sysoevc1571722005-03-19 12:38:37 +00001909 if (ngx_tcp_push(c->fd) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00001910 ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
1911 ngx_http_close_connection(c);
1912 return;
Igor Sysoev9cf78302003-06-04 17:28:33 +00001913 }
Igor Sysoev924bd792004-10-11 15:07:03 +00001914
Igor Sysoev67f450d2004-06-01 06:04:46 +00001915 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
Igor Sysoev42b12b32004-12-02 18:40:46 +00001916 tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
Igor Sysoev924bd792004-10-11 15:07:03 +00001917
1918 } else {
Igor Sysoev42b12b32004-12-02 18:40:46 +00001919 tcp_nodelay = 1;
1920 }
Igor Sysoev924bd792004-10-11 15:07:03 +00001921
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001922 if (tcp_nodelay
1923 && clcf->tcp_nodelay
1924 && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
1925 {
Igor Sysoev42b12b32004-12-02 18:40:46 +00001926 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
Igor Sysoev924bd792004-10-11 15:07:03 +00001927
Igor Sysoev42b12b32004-12-02 18:40:46 +00001928 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
Igor Sysoevcdf609a2006-04-17 19:55:41 +00001929 (const void *) &tcp_nodelay, sizeof(int))
1930 == -1)
Igor Sysoev42b12b32004-12-02 18:40:46 +00001931 {
1932 ngx_connection_error(c, ngx_socket_errno,
1933 "setsockopt(TCP_NODELAY) failed");
1934 ngx_http_close_connection(c);
1935 return;
Igor Sysoev924bd792004-10-11 15:07:03 +00001936 }
Igor Sysoev42b12b32004-12-02 18:40:46 +00001937
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001938 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
Igor Sysoev9cf78302003-06-04 17:28:33 +00001939 }
1940
Igor Sysoevf7abd722004-09-23 06:32:00 +00001941#if 0
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001942 /* if ngx_http_request_t was freed then we need some other place */
Igor Sysoevc83f6832004-06-24 07:53:37 +00001943 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001944#endif
Igor Sysoevc83f6832004-06-24 07:53:37 +00001945
Igor Sysoevb5faed22003-10-29 08:30:44 +00001946 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001947 ngx_http_keepalive_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00001948 }
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001949}
1950
1951
Igor Sysoevc1571722005-03-19 12:38:37 +00001952static void
1953ngx_http_keepalive_handler(ngx_event_t *rev)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001954{
Igor Sysoevc1571722005-03-19 12:38:37 +00001955 size_t size;
1956 ssize_t n;
1957 ngx_buf_t *b;
1958 ngx_connection_t *c;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001959
Igor Sysoev0ad25372004-07-16 06:33:35 +00001960 c = rev->data;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001961
Igor Sysoeve04084c2004-01-26 08:52:49 +00001962 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
Igor Sysoev1af7c822002-09-13 14:47:42 +00001963
Igor Sysoevdc479b42003-03-20 16:09:44 +00001964 if (rev->timedout) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001965 ngx_http_close_connection(c);
1966 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00001967 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001968
Igor Sysoevf6906042004-11-25 16:17:31 +00001969#if (NGX_HAVE_KQUEUE)
Igor Sysoev236e0452004-09-23 16:39:34 +00001970
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001971 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoevcdc46302005-12-07 14:51:31 +00001972 if (rev->pending_eof) {
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001973 c->log->handler = NULL;
Igor Sysoev236e0452004-09-23 16:39:34 +00001974 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
Igor Sysoev1b735832004-11-11 14:07:14 +00001975 "kevent() reported that client %V closed "
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001976 "keepalive connection", &c->addr_text);
Igor Sysoev42b12b32004-12-02 18:40:46 +00001977#if (NGX_HTTP_SSL)
1978 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00001979 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00001980 }
1981#endif
Igor Sysoev236e0452004-09-23 16:39:34 +00001982 ngx_http_close_connection(c);
1983 return;
1984 }
1985 }
1986
1987#endif
1988
Igor Sysoev236e0452004-09-23 16:39:34 +00001989 b = c->buffer;
1990 size = b->end - b->start;
1991
1992 if (b->pos == NULL) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001993
1994 /*
1995 * The c->buffer's memory was freed by ngx_http_set_keepalive().
1996 * However, the c->buffer->start and c->buffer->end were not changed
1997 * to keep the buffer size.
1998 */
1999
Igor Sysoevc1571722005-03-19 12:38:37 +00002000 b->pos = ngx_palloc(c->pool, size);
2001 if (b->pos == NULL) {
Igor Sysoev236e0452004-09-23 16:39:34 +00002002 ngx_http_close_connection(c);
2003 return;
2004 }
2005
2006 b->start = b->pos;
2007 b->last = b->pos;
2008 b->end = b->pos + size;
2009 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00002010
Igor Sysoev0a280a32003-10-12 16:49:16 +00002011 /*
2012 * MSIE closes a keepalive connection with RST flag
2013 * so we ignore ECONNRESET here.
2014 */
Igor Sysoevb7387572003-03-11 20:38:13 +00002015
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002016 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
Igor Sysoevb7387572003-03-11 20:38:13 +00002017 ngx_set_socket_errno(0);
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00002018
Igor Sysoev236e0452004-09-23 16:39:34 +00002019 n = c->recv(c, b->last, size);
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002020 c->log_error = NGX_ERROR_INFO;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002021
Igor Sysoevd581fd52003-05-13 16:02:32 +00002022 if (n == NGX_AGAIN) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002023 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002024 ngx_http_close_connection(c);
2025 }
2026
Igor Sysoevd581fd52003-05-13 16:02:32 +00002027 return;
2028 }
2029
2030 if (n == NGX_ERROR) {
2031 ngx_http_close_connection(c);
2032 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00002033 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002034
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002035 c->log->handler = NULL;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002036
2037 if (n == 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +00002038 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002039 "client %V closed keepalive connection", &c->addr_text);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002040 ngx_http_close_connection(c);
2041 return;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002042 }
2043
Igor Sysoevf7abd722004-09-23 06:32:00 +00002044 b->last += n;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002045
Igor Sysoev055951d2005-10-21 19:12:18 +00002046#if (NGX_STAT_STUB)
2047 ngx_atomic_fetch_add(ngx_stat_reading, 1);
2048#endif
2049
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002050 c->log->handler = ngx_http_log_error;
2051 c->log->action = "reading client request line";
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002052
Igor Sysoevd581fd52003-05-13 16:02:32 +00002053 ngx_http_init_request(rev);
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002054}
2055
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002056
Igor Sysoevc1571722005-03-19 12:38:37 +00002057static void
2058ngx_http_set_lingering_close(ngx_http_request_t *r)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002059{
Igor Sysoev0a280a32003-10-12 16:49:16 +00002060 ngx_event_t *rev, *wev;
Igor Sysoevb7387572003-03-11 20:38:13 +00002061 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002062 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002063
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002064 c = r->connection;
Igor Sysoev9b25d692003-01-26 21:08:14 +00002065
Igor Sysoev6253ca12003-05-27 12:18:54 +00002066 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002067
Igor Sysoev0a280a32003-10-12 16:49:16 +00002068 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002069 rev->handler = ngx_http_lingering_close_handler;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002070
Igor Sysoev208eed22005-10-07 13:30:52 +00002071 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
Igor Sysoev6253ca12003-05-27 12:18:54 +00002072 ngx_add_timer(rev, clcf->lingering_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +00002073
Igor Sysoev899b44e2005-05-12 14:58:06 +00002074 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00002075 ngx_http_close_request(r, 0);
Igor Sysoev0a280a32003-10-12 16:49:16 +00002076 return;
2077 }
2078
2079 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002080 wev->handler = ngx_http_empty_handler;
Igor Sysoev0a280a32003-10-12 16:49:16 +00002081
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002082 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2083 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
2084 ngx_http_close_request(r, 0);
2085 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00002086 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002087 }
2088
Igor Sysoevb7387572003-03-11 20:38:13 +00002089 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00002090 ngx_connection_error(c, ngx_socket_errno,
2091 ngx_shutdown_socket_n " failed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002092 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002093 return;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002094 }
2095
Igor Sysoevb5faed22003-10-29 08:30:44 +00002096 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002097 ngx_http_lingering_close_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00002098 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002099}
2100
2101
Igor Sysoevc1571722005-03-19 12:38:37 +00002102static void
2103ngx_http_lingering_close_handler(ngx_event_t *rev)
Igor Sysoev42feecb2002-12-15 06:25:09 +00002104{
Igor Sysoevdc479b42003-03-20 16:09:44 +00002105 ssize_t n;
2106 ngx_msec_t timer;
2107 ngx_connection_t *c;
2108 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002109 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002110 u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
Igor Sysoev1af7c822002-09-13 14:47:42 +00002111
Igor Sysoev6253ca12003-05-27 12:18:54 +00002112 c = rev->data;
2113 r = c->data;
Igor Sysoev86de4cb2003-01-30 07:28:09 +00002114
Igor Sysoeve04084c2004-01-26 08:52:49 +00002115 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2116 "http lingering close handler");
Igor Sysoevdc479b42003-03-20 16:09:44 +00002117
2118 if (rev->timedout) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002119 c->timedout = 1;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002120 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002121 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002122 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002123
Igor Sysoevc0247302004-06-27 18:01:57 +00002124 timer = r->lingering_time - ngx_time();
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002125 if (timer <= 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002126 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002127 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002128 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002129
Igor Sysoevdc479b42003-03-20 16:09:44 +00002130 do {
Igor Sysoevf7abd722004-09-23 06:32:00 +00002131 n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002132
Igor Sysoeve04084c2004-01-26 08:52:49 +00002133 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002134
Igor Sysoevdc479b42003-03-20 16:09:44 +00002135 if (n == NGX_ERROR || n == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002136 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002137 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002138 }
2139
2140 } while (rev->ready);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002141
Igor Sysoev899b44e2005-05-12 14:58:06 +00002142 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00002143 ngx_http_close_request(r, 0);
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002144 return;
2145 }
2146
Igor Sysoevf7abd722004-09-23 06:32:00 +00002147 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2148
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002149 timer *= 1000;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002150
Igor Sysoev6253ca12003-05-27 12:18:54 +00002151 if (timer > clcf->lingering_timeout) {
2152 timer = clcf->lingering_timeout;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002153 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002154
Igor Sysoevdc479b42003-03-20 16:09:44 +00002155 ngx_add_timer(rev, timer);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002156}
2157
Igor Sysoev2b542382002-08-20 14:48:28 +00002158
Igor Sysoevc1571722005-03-19 12:38:37 +00002159void
2160ngx_http_empty_handler(ngx_event_t *wev)
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002161{
Igor Sysoeve04084c2004-01-26 08:52:49 +00002162 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002163
2164 return;
2165}
2166
2167
Igor Sysoev899b44e2005-05-12 14:58:06 +00002168void
2169ngx_http_request_empty_handler(ngx_http_request_t *r)
2170{
2171 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002172 "http request empty handler");
Igor Sysoev899b44e2005-05-12 14:58:06 +00002173
2174 return;
2175}
2176
2177
Igor Sysoevc1571722005-03-19 12:38:37 +00002178ngx_int_t
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002179ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002180{
Igor Sysoev369145c2004-05-28 15:49:23 +00002181 ngx_buf_t *b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002182 ngx_chain_t out;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002183
Igor Sysoevc1571722005-03-19 12:38:37 +00002184 b = ngx_calloc_buf(r->pool);
2185 if (b == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +00002186 return NGX_ERROR;
2187 }
2188
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002189 if (flags & NGX_HTTP_LAST) {
2190 b->last_buf = 1;
2191 }
2192
2193 if (flags & NGX_HTTP_FLUSH) {
2194 b->flush = 1;
2195 }
2196
Igor Sysoev369145c2004-05-28 15:49:23 +00002197 out.buf = b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002198 out.next = NULL;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002199
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002200 return ngx_http_output_filter(r, &out);
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002201}
2202
2203
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002204static ngx_int_t
2205ngx_http_post_action(ngx_http_request_t *r)
2206{
2207 ngx_http_core_loc_conf_t *clcf;
2208
2209 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2210
2211 if (clcf->post_action.data == NULL) {
2212 return NGX_DECLINED;
2213 }
2214
Igor Sysoev8fea8852006-03-15 09:53:04 +00002215 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2216 "post action: \"%V\"", &clcf->post_action);
2217
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002218 r->http_version = NGX_HTTP_VERSION_9;
2219 r->header_only = 1;
Igor Sysoev6d16e1e2006-04-05 13:40:54 +00002220 r->post_action = 1;
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002221
2222 ngx_http_internal_redirect(r, &clcf->post_action, NULL);
2223
2224 return NGX_OK;
2225}
2226
2227
2228static void
Igor Sysoev899b44e2005-05-12 14:58:06 +00002229ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error)
Igor Sysoevd581fd52003-05-13 16:02:32 +00002230{
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002231 ngx_connection_t *c;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002232
2233 c = r->connection;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002234
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002235 ngx_http_request_done(r->main, error);
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002236 ngx_http_close_connection(c);
2237}
2238
2239
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002240static void
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002241ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error)
2242{
2243 ngx_log_t *log;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002244 ngx_uint_t i, n;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002245 struct linger linger;
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002246 ngx_http_cleanup_t *cln;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002247 ngx_http_log_ctx_t *ctx;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002248 ngx_http_handler_pt *log_handler;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002249 ngx_http_core_loc_conf_t *clcf;
2250 ngx_http_core_main_conf_t *cmcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002251
Igor Sysoev865c1502003-11-30 20:03:18 +00002252 log = r->connection->log;
2253
2254 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002255
2256 if (r->pool == NULL) {
Igor Sysoev90c08142005-07-25 09:41:38 +00002257 ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002258 return;
2259 }
2260
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002261 for (cln = r->cleanup; cln; cln = cln->next) {
2262 if (cln->handler) {
2263 cln->handler(cln->data);
2264 }
2265 }
2266
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002267#if (NGX_STAT_STUB)
Igor Sysoev055951d2005-10-21 19:12:18 +00002268
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002269 if (r->stat_reading) {
Igor Sysoev78452232005-10-12 13:50:36 +00002270 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002271 }
2272
2273 if (r->stat_writing) {
Igor Sysoev78452232005-10-12 13:50:36 +00002274 ngx_atomic_fetch_add(ngx_stat_writing, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002275 }
Igor Sysoev055951d2005-10-21 19:12:18 +00002276
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002277#endif
2278
Igor Sysoev669e3312003-12-22 09:40:48 +00002279 if (error && r->headers_out.status == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002280 r->headers_out.status = error;
2281 }
2282
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002283 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2284
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002285 log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
2286 n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
2287 for (i = 0; i < n; i++) {
2288 log_handler[i](r);
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002289 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00002290
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002291 if (r->connection->timedout) {
2292 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2293
2294 if (clcf->reset_timedout_connection) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002295 linger.l_onoff = 1;
2296 linger.l_linger = 0;
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002297
2298 if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
Igor Sysoev899b44e2005-05-12 14:58:06 +00002299 (const void *) &linger, sizeof(struct linger)) == -1)
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002300 {
2301 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
2302 "setsockopt(SO_LINGER) failed");
2303 }
2304 }
2305 }
2306
Igor Sysoev899b44e2005-05-12 14:58:06 +00002307 /* the various request strings were allocated from r->pool */
Igor Sysoev865c1502003-11-30 20:03:18 +00002308 ctx = log->data;
Igor Sysoev1b735832004-11-11 14:07:14 +00002309 ctx->request = NULL;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002310
Igor Sysoevc83f6832004-06-24 07:53:37 +00002311 r->request_line.len = 0;
2312
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002313 r->connection->destroyed = 1;
2314
Igor Sysoevd581fd52003-05-13 16:02:32 +00002315 ngx_destroy_pool(r->pool);
2316}
2317
2318
Igor Sysoev90c08142005-07-25 09:41:38 +00002319static void
Igor Sysoevc1571722005-03-19 12:38:37 +00002320ngx_http_close_connection(ngx_connection_t *c)
Igor Sysoev6b863e32003-05-12 15:52:24 +00002321{
Igor Sysoev02025fd2005-01-18 13:03:58 +00002322 ngx_pool_t *pool;
2323
Igor Sysoeve04084c2004-01-26 08:52:49 +00002324 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev54498db2004-02-11 17:08:49 +00002325 "close http connection: %d", c->fd);
Igor Sysoev6b863e32003-05-12 15:52:24 +00002326
Igor Sysoevceb99292005-09-06 16:09:32 +00002327#if (NGX_HTTP_SSL)
Igor Sysoev924bd792004-10-11 15:07:03 +00002328
2329 if (c->ssl) {
2330 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002331 c->ssl->handler = ngx_http_close_connection;
Igor Sysoev924bd792004-10-11 15:07:03 +00002332 return;
2333 }
2334 }
2335
2336#endif
2337
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002338#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +00002339 ngx_atomic_fetch_add(ngx_stat_active, -1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002340#endif
2341
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002342 c->destroyed = 1;
2343
Igor Sysoev02025fd2005-01-18 13:03:58 +00002344 pool = c->pool;
2345
Igor Sysoev59cf56c2004-09-07 15:29:22 +00002346 ngx_close_connection(c);
Igor Sysoev02025fd2005-01-18 13:03:58 +00002347
Igor Sysoevc1571722005-03-19 12:38:37 +00002348 ngx_destroy_pool(pool);
Igor Sysoev2ba1ee02002-10-04 17:58:04 +00002349}
2350
2351
Igor Sysoevc1571722005-03-19 12:38:37 +00002352static u_char *
2353ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002354{
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002355 u_char *p;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002356 ngx_http_request_t *r;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002357 ngx_http_log_ctx_t *ctx;
Igor Sysoev7578ec92003-06-02 15:24:30 +00002358
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002359 if (log->action) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002360 p = ngx_snprintf(buf, len, " while %s", log->action);
Igor Sysoev1b735832004-11-11 14:07:14 +00002361 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002362 buf = p;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002363 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002364
Igor Sysoev899b44e2005-05-12 14:58:06 +00002365 ctx = log->data;
2366
Igor Sysoevc04deca2005-03-28 14:43:02 +00002367 p = ngx_snprintf(buf, len, ", client: %V", ctx->client);
Igor Sysoev899b44e2005-05-12 14:58:06 +00002368 len -= p - buf;
Igor Sysoev1b735832004-11-11 14:07:14 +00002369
Igor Sysoevc04deca2005-03-28 14:43:02 +00002370 r = ctx->request;
2371
Igor Sysoev899b44e2005-05-12 14:58:06 +00002372 if (r) {
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002373 return r->log_handler(r, ctx->current_request, p, len);
Igor Sysoev1b735832004-11-11 14:07:14 +00002374 }
2375
Igor Sysoev899b44e2005-05-12 14:58:06 +00002376 return p;
2377}
2378
2379
2380static u_char *
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002381ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
2382 u_char *buf, size_t len)
Igor Sysoev899b44e2005-05-12 14:58:06 +00002383{
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002384 u_char *p;
2385 ngx_http_upstream_t *u;
2386 ngx_peer_connection_t *peer;
Igor Sysoev1b735832004-11-11 14:07:14 +00002387
Igor Sysoevc04deca2005-03-28 14:43:02 +00002388 if (r->server_name.data) {
2389 p = ngx_snprintf(buf, len, ", server: %V", &r->server_name);
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002390 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002391 buf = p;
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002392 }
2393
Igor Sysoevc04deca2005-03-28 14:43:02 +00002394 if (r->unparsed_uri.data) {
2395 p = ngx_snprintf(buf, len, ", URL: \"%V\"", &r->unparsed_uri);
2396 len -= p - buf;
2397 buf = p;
Igor Sysoev1b735832004-11-11 14:07:14 +00002398
Igor Sysoevc04deca2005-03-28 14:43:02 +00002399 } else {
2400 if (r->request_line.data == NULL && r->request_start) {
2401 for (p = r->request_start; p < r->header_in->last; p++) {
2402 if (*p == CR || *p == LF) {
2403 break;
2404 }
2405 }
2406
2407 r->request_line.len = p - r->request_start;
2408 r->request_line.data = r->request_start;
2409 }
2410
2411 if (r->request_line.len) {
2412 p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
2413 len -= p - buf;
2414 buf = p;
2415 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002416 }
2417
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002418 if (r != sr) {
2419 p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
2420 len -= p - buf;
2421 buf = p;
2422 }
2423
2424 u = sr->upstream;
2425
2426 if (u) {
2427 peer = &u->peer;
2428
2429 p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
2430 &u->conf->schema,
2431 &peer->peers->peer[peer->cur_peer].name,
2432 peer->peers->peer[peer->cur_peer].uri_separator,
2433 &u->uri);
2434 len -= p - buf;
2435 buf = p;
2436 }
2437
Igor Sysoevc04deca2005-03-28 14:43:02 +00002438 return ngx_http_log_error_info(r, buf, len);
2439}
Igor Sysoev1b735832004-11-11 14:07:14 +00002440
Igor Sysoevc04deca2005-03-28 14:43:02 +00002441
2442u_char *
2443ngx_http_log_error_info(ngx_http_request_t *r, u_char *buf, size_t len)
2444{
2445 u_char *p;
2446
2447 if (r->headers_in.host) {
2448 p = ngx_snprintf(buf, len, ", host: \"%V\"",
2449 &r->headers_in.host->value);
2450 len -= p - buf;
2451 buf = p;
2452 }
2453
2454 if (r->headers_in.referer) {
2455 p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
2456 &r->headers_in.referer->value);
2457 buf = p;
2458 }
2459
2460 return buf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00002461}