blob: 870dd8bcc3bd24d55d4f7e3ba3a9d8613d351dfc [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 Sysoevc2807ec2006-02-16 15:26:46 +000028static void ngx_http_find_virtual_server(ngx_http_request_t *r);
Igor Sysoev6b863e32003-05-12 15:52:24 +000029
Igor Sysoev899b44e2005-05-12 14:58:06 +000030static void ngx_http_request_handler(ngx_event_t *ev);
Igor Sysoev85ef94b2005-06-23 13:41:06 +000031static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
Igor Sysoev899b44e2005-05-12 14:58:06 +000032static void ngx_http_writer(ngx_http_request_t *r);
Igor Sysoev6b863e32003-05-12 15:52:24 +000033
Igor Sysoev899b44e2005-05-12 14:58:06 +000034static void ngx_http_block_read(ngx_http_request_t *r);
35static void ngx_http_read_discarded_body_handler(ngx_http_request_t *r);
Igor Sysoev2f657222004-06-16 15:32:11 +000036static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r);
Igor Sysoev3a40d482002-09-12 14:42:29 +000037
Igor Sysoevd581fd52003-05-13 16:02:32 +000038static void ngx_http_set_keepalive(ngx_http_request_t *r);
39static void ngx_http_keepalive_handler(ngx_event_t *ev);
40static void ngx_http_set_lingering_close(ngx_http_request_t *r);
41static void ngx_http_lingering_close_handler(ngx_event_t *ev);
Igor Sysoevc2807ec2006-02-16 15:26:46 +000042static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
Igor Sysoev90c08142005-07-25 09:41:38 +000043static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
Igor Sysoev9ac946b2005-10-24 15:09:41 +000044static void ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error);
Igor Sysoev90c08142005-07-25 09:41:38 +000045static void ngx_http_close_connection(ngx_connection_t *c);
Igor Sysoevd581fd52003-05-13 16:02:32 +000046
Igor Sysoeve5a222c2005-01-25 12:27:35 +000047static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
Igor Sysoev899b44e2005-05-12 14:58:06 +000048static u_char *ngx_http_log_error_handler(ngx_http_request_t *r, u_char *buf,
49 size_t len);
Igor Sysoev0ad17c02002-08-26 15:18:19 +000050
Igor Sysoevceb99292005-09-06 16:09:32 +000051#if (NGX_HTTP_SSL)
52static void ngx_http_ssl_handshake(ngx_event_t *rev);
Igor Sysoev9fa5a822005-09-30 14:41:25 +000053static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
Igor Sysoevceb99292005-09-06 16:09:32 +000054#endif
55
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000056
Igor Sysoevc04deca2005-03-28 14:43:02 +000057static char *ngx_http_client_errors[] = {
Igor Sysoev0ad17c02002-08-26 15:18:19 +000058
Igor Sysoevc04deca2005-03-28 14:43:02 +000059 /* NGX_HTTP_PARSE_INVALID_METHOD */
60 "client sent invalid method",
Igor Sysoev6a644c62003-03-04 06:33:48 +000061
Igor Sysoevc04deca2005-03-28 14:43:02 +000062 /* NGX_HTTP_PARSE_INVALID_REQUEST */
63 "client sent invalid request",
64
65 /* NGX_HTTP_PARSE_INVALID_09_METHOD */
66 "client sent invalid method in HTTP/0.9 request"
Igor Sysoev016b8522002-08-29 16:59:54 +000067};
68
69
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000070ngx_http_header_t ngx_http_headers_in[] = {
Igor Sysoev899b44e2005-05-12 14:58:06 +000071 { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
Igor Sysoevb145b062005-06-15 18:33:41 +000072 ngx_http_process_unique_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000073
Igor Sysoev899b44e2005-05-12 14:58:06 +000074 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
Igor Sysoevb145b062005-06-15 18:33:41 +000075 ngx_http_process_unique_header_line },
Igor Sysoev899b44e2005-05-12 14:58:06 +000076
77 { ngx_string("If-Modified-Since"),
78 offsetof(ngx_http_headers_in_t, if_modified_since),
79 ngx_http_process_header_line },
80
81 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
82 ngx_http_process_header_line },
83
84 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
85 ngx_http_process_header_line },
86
87 { ngx_string("Content-Length"),
88 offsetof(ngx_http_headers_in_t, content_length),
Igor Sysoevb145b062005-06-15 18:33:41 +000089 ngx_http_process_unique_header_line },
Igor Sysoev899b44e2005-05-12 14:58:06 +000090
91 { ngx_string("Content-Type"),
92 offsetof(ngx_http_headers_in_t, content_type),
93 ngx_http_process_header_line },
94
95 { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
96 ngx_http_process_header_line },
97
Igor Sysoevc31a9bb2005-11-26 10:11:11 +000098 { ngx_string("Transfer-Encoding"),
99 offsetof(ngx_http_headers_in_t, transfer_encoding),
100 ngx_http_process_header_line },
101
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000102#if (NGX_HTTP_GZIP)
103 { ngx_string("Accept-Encoding"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000104 offsetof(ngx_http_headers_in_t, accept_encoding),
105 ngx_http_process_header_line },
106
107 { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
108 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000109#endif
110
111 { ngx_string("Authorization"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000112 offsetof(ngx_http_headers_in_t, authorization),
Igor Sysoevb145b062005-06-15 18:33:41 +0000113 ngx_http_process_unique_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000114
Igor Sysoev899b44e2005-05-12 14:58:06 +0000115 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
116 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000117
Igor Sysoev09c684b2005-11-09 17:25:55 +0000118#if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000119 { ngx_string("X-Forwarded-For"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000120 offsetof(ngx_http_headers_in_t, x_forwarded_for),
121 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000122#endif
Igor Sysoev02025fd2005-01-18 13:03:58 +0000123
Igor Sysoev09c684b2005-11-09 17:25:55 +0000124#if (NGX_HTTP_REALIP)
125 { ngx_string("X-Real-IP"),
126 offsetof(ngx_http_headers_in_t, x_real_ip),
127 ngx_http_process_header_line },
128#endif
129
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000130#if (NGX_HTTP_HEADERS)
Igor Sysoev899b44e2005-05-12 14:58:06 +0000131 { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
132 ngx_http_process_header_line },
133
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000134 { ngx_string("Accept-Language"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000135 offsetof(ngx_http_headers_in_t, accept_language),
136 ngx_http_process_header_line },
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000137#endif
138
Igor Sysoev899b44e2005-05-12 14:58:06 +0000139 { ngx_string("Cookie"), 0, ngx_http_process_cookie },
140
141 { ngx_null_string, 0, NULL }
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000142};
143
144
Igor Sysoevc1571722005-03-19 12:38:37 +0000145void
146ngx_http_init_connection(ngx_connection_t *c)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000147{
Igor Sysoev6253ca12003-05-27 12:18:54 +0000148 ngx_event_t *rev;
Igor Sysoev160d7742003-11-19 16:26:41 +0000149 ngx_http_log_ctx_t *ctx;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000150
Igor Sysoevc1571722005-03-19 12:38:37 +0000151 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
152 if (ctx == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000153 ngx_http_close_connection(c);
154 return;
155 }
156
Igor Sysoev1b735832004-11-11 14:07:14 +0000157 ctx->client = &c->addr_text;
Igor Sysoev1b735832004-11-11 14:07:14 +0000158 ctx->request = NULL;
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000159
160 c->log->connection = c->number;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000161 c->log->handler = ngx_http_log_error;
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000162 c->log->data = ctx;
163 c->log->action = "reading client request line";
164
Igor Sysoevc7a2f682004-02-10 16:23:38 +0000165 c->log_error = NGX_ERROR_INFO;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000166
Igor Sysoevdc479b42003-03-20 16:09:44 +0000167 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000168 rev->handler = ngx_http_init_request;
Igor Sysoev9ac946b2005-10-24 15:09:41 +0000169 c->write->handler = ngx_http_empty_handler;
Igor Sysoev7af6b162004-02-09 07:46:43 +0000170
Igor Sysoev055951d2005-10-21 19:12:18 +0000171#if (NGX_STAT_STUB)
172 ngx_atomic_fetch_add(ngx_stat_reading, 1);
173#endif
174
Igor Sysoevdc479b42003-03-20 16:09:44 +0000175 if (rev->ready) {
Igor Sysoev0ab91b92004-06-06 19:49:18 +0000176 /* the deferred accept(), rtsig, aio, iocp */
Igor Sysoev709405b2004-03-31 15:26:46 +0000177
Igor Sysoevffe71442006-02-08 15:33:12 +0000178 if (ngx_use_accept_mutex) {
Igor Sysoevc2068d02005-10-19 12:33:58 +0000179 ngx_post_event(rev, &ngx_posted_events);
Igor Sysoev709405b2004-03-31 15:26:46 +0000180 return;
181 }
182
Igor Sysoev6b863e32003-05-12 15:52:24 +0000183 ngx_http_init_request(rev);
184 return;
Igor Sysoev016b8522002-08-29 16:59:54 +0000185 }
Igor Sysoev73009772003-02-06 17:21:13 +0000186
Igor Sysoev239baac2003-06-11 15:28:34 +0000187 ngx_add_timer(rev, c->listening->post_accept_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000188
Igor Sysoevb5faed22003-10-29 08:30:44 +0000189 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev055951d2005-10-21 19:12:18 +0000190#if (NGX_STAT_STUB)
191 ngx_atomic_fetch_add(ngx_stat_reading, -1);
192#endif
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000193 ngx_http_close_connection(c);
194 return;
195 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000196}
197
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000198
Igor Sysoevc1571722005-03-19 12:38:37 +0000199static
200void ngx_http_init_request(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000201{
Igor Sysoev09c684b2005-11-09 17:25:55 +0000202 ngx_uint_t i;
203 socklen_t len;
204 struct sockaddr_in sin;
205 ngx_connection_t *c;
206 ngx_http_request_t *r;
Igor Sysoev305a9d82005-12-26 17:07:48 +0000207 ngx_http_in_port_t *hip;
208 ngx_http_in_addr_t *hia;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000209 ngx_http_log_ctx_t *ctx;
210 ngx_http_connection_t *hc;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000211 ngx_http_core_srv_conf_t *cscf;
212 ngx_http_core_loc_conf_t *clcf;
213 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000214#if (NGX_HTTP_SSL)
Igor Sysoev09c684b2005-11-09 17:25:55 +0000215 ngx_http_ssl_srv_conf_t *sscf;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000216#endif
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000217
Igor Sysoev055951d2005-10-21 19:12:18 +0000218#if (NGX_STAT_STUB)
219 ngx_atomic_fetch_add(ngx_stat_reading, -1);
220#endif
221
Igor Sysoeva9830112003-05-19 16:39:14 +0000222 c = rev->data;
Igor Sysoeva9830112003-05-19 16:39:14 +0000223
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000224 if (rev->timedout) {
225 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000226
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000227 ngx_http_close_connection(c);
228 return;
229 }
230
Igor Sysoevf7abd722004-09-23 06:32:00 +0000231 hc = c->data;
Igor Sysoevdd888c42004-09-21 05:38:28 +0000232
Igor Sysoev055951d2005-10-21 19:12:18 +0000233 if (hc == NULL) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000234 hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
235 if (hc == NULL) {
Igor Sysoevdd888c42004-09-21 05:38:28 +0000236 ngx_http_close_connection(c);
237 return;
238 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000239 }
Igor Sysoevdd888c42004-09-21 05:38:28 +0000240
Igor Sysoevf7abd722004-09-23 06:32:00 +0000241 r = hc->request;
242
243 if (r) {
244 ngx_memzero(r, sizeof(ngx_http_request_t));
245
246 r->pipeline = hc->pipeline;
247
248 if (hc->nbusy) {
249 r->header_in = hc->busy[0];
250 }
251
Igor Sysoevf7abd722004-09-23 06:32:00 +0000252 } else {
Igor Sysoevc1571722005-03-19 12:38:37 +0000253 r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
254 if (r == NULL) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000255 ngx_http_close_connection(c);
256 return;
257 }
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000258
Igor Sysoevdd888c42004-09-21 05:38:28 +0000259 hc->request = r;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000260 }
261
Igor Sysoevdd888c42004-09-21 05:38:28 +0000262 c->data = r;
263 r->http_connection = hc;
264
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000265 c->sent = 0;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000266 r->signature = NGX_HTTP_MODULE;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000267
Igor Sysoev6253ca12003-05-27 12:18:54 +0000268 /* find the server configuration for the address:port */
269
270 /* AF_INET only */
271
Igor Sysoev305a9d82005-12-26 17:07:48 +0000272 hip = c->servers;
273 hia = hip->addrs;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000274
Igor Sysoev305a9d82005-12-26 17:07:48 +0000275 r->port = hip->port;
276 r->port_text = &hip->port_text;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000277
278 i = 0;
279
Igor Sysoev305a9d82005-12-26 17:07:48 +0000280 if (hip->naddrs > 1) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000281
Igor Sysoev239baac2003-06-11 15:28:34 +0000282 /*
Igor Sysoevd00b3652004-08-23 19:09:29 +0000283 * There are several addresses on this port and one of them
284 * is the "*:port" wildcard so getsockname() is needed to determine
Igor Sysoev239baac2003-06-11 15:28:34 +0000285 * the server address.
Igor Sysoevd00b3652004-08-23 19:09:29 +0000286 *
Igor Sysoev239baac2003-06-11 15:28:34 +0000287 * AcceptEx() already gave this address.
288 */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000289
Igor Sysoev1b735832004-11-11 14:07:14 +0000290#if (NGX_WIN32)
Igor Sysoev239baac2003-06-11 15:28:34 +0000291 if (c->local_sockaddr) {
292 r->in_addr =
293 ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000294
Igor Sysoev02025fd2005-01-18 13:03:58 +0000295 } else
Igor Sysoev239baac2003-06-11 15:28:34 +0000296#endif
Igor Sysoev02025fd2005-01-18 13:03:58 +0000297 {
Igor Sysoev239baac2003-06-11 15:28:34 +0000298 len = sizeof(struct sockaddr_in);
Igor Sysoev02025fd2005-01-18 13:03:58 +0000299 if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000300 ngx_connection_error(c, ngx_socket_errno,
301 "getsockname() failed");
Igor Sysoev239baac2003-06-11 15:28:34 +0000302 ngx_http_close_connection(c);
303 return;
304 }
Igor Sysoev10a543a2004-03-16 07:10:12 +0000305
Igor Sysoev02025fd2005-01-18 13:03:58 +0000306 r->in_addr = sin.sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000307 }
308
Igor Sysoev6253ca12003-05-27 12:18:54 +0000309 /* the last in_port->addrs address is "*" */
310
Igor Sysoev305a9d82005-12-26 17:07:48 +0000311 for ( /* void */ ; i < hip->naddrs - 1; i++) {
312 if (hia[i].addr == r->in_addr) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000313 break;
314 }
315 }
316
317 } else {
Igor Sysoev305a9d82005-12-26 17:07:48 +0000318 r->in_addr = hia[0].addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000319 }
320
Igor Sysoev305a9d82005-12-26 17:07:48 +0000321 r->virtual_names = hia[i].virtual_names;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000322
323 /* the default server configuration for the address:port */
Igor Sysoev305a9d82005-12-26 17:07:48 +0000324 cscf = hia[i].core_srv_conf;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000325
326 r->main_conf = cscf->ctx->main_conf;
327 r->srv_conf = cscf->ctx->srv_conf;
328 r->loc_conf = cscf->ctx->loc_conf;
329
Igor Sysoev305a9d82005-12-26 17:07:48 +0000330 r->server_name = cscf->server_name;
331
Igor Sysoev899b44e2005-05-12 14:58:06 +0000332 rev->handler = ngx_http_process_request_line;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000333
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000334#if (NGX_HTTP_SSL)
335
Igor Sysoevf38e0462004-07-16 17:11:43 +0000336 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000337 if (sscf->enable) {
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000338
339 if (c->ssl == NULL) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000340 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
Igor Sysoev02f742b2005-04-08 15:18:55 +0000341 == NGX_ERROR)
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000342 {
343 ngx_http_close_connection(c);
344 return;
345 }
346
Igor Sysoev899b44e2005-05-12 14:58:06 +0000347 rev->handler = ngx_http_ssl_handshake;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000348 }
349
Igor Sysoevd52477f2005-05-16 13:53:20 +0000350 r->main_filter_need_in_memory = 1;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000351 }
352
Igor Sysoev4aa88882004-07-14 20:07:58 +0000353#endif
354
Igor Sysoev890fc962003-07-20 21:15:59 +0000355 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
356 c->log->file = clcf->err_log->file;
Igor Sysoevfff32322004-04-08 15:58:25 +0000357 if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
358 c->log->log_level = clcf->err_log->log_level;
359 }
Igor Sysoev890fc962003-07-20 21:15:59 +0000360
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000361 if (c->buffer == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +0000362 c->buffer = ngx_create_temp_buf(c->pool,
363 cscf->client_header_buffer_size);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000364 if (c->buffer == NULL) {
365 ngx_http_close_connection(c);
366 return;
367 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000368 }
369
Igor Sysoevf7abd722004-09-23 06:32:00 +0000370 if (r->header_in == NULL) {
371 r->header_in = c->buffer;
372 }
373
Igor Sysoevc1571722005-03-19 12:38:37 +0000374 r->pool = ngx_create_pool(cscf->request_pool_size, c->log);
375 if (r->pool == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000376 ngx_http_close_connection(c);
377 return;
378 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000379
Igor Sysoev89690bf2004-03-23 06:01:52 +0000380
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000381 if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000382 sizeof(ngx_table_elt_t))
383 == NGX_ERROR)
Igor Sysoev980a9242004-09-05 19:54:02 +0000384 {
385 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev980a9242004-09-05 19:54:02 +0000386 return;
387 }
388
Igor Sysoev6b863e32003-05-12 15:52:24 +0000389 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
390 if (r->ctx == NULL) {
391 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000392 return;
393 }
Igor Sysoeve0268b92002-09-11 15:18:33 +0000394
Igor Sysoev09c684b2005-11-09 17:25:55 +0000395 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
396
397 r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
398 * sizeof(ngx_http_variable_value_t));
399 if (r->variables == NULL) {
400 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
401 return;
402 }
403
Igor Sysoevc78c41c2004-07-07 06:15:04 +0000404 c->single_connection = 1;
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000405 c->destroyed = 0;
406
Igor Sysoev6b863e32003-05-12 15:52:24 +0000407 r->connection = c;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000408
Igor Sysoevf6e1fe32005-10-04 10:38:53 +0000409 r->main = r;
410
Igor Sysoev11d75322005-03-01 15:20:36 +0000411 r->start_time = ngx_time();
412
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000413 r->headers_in.content_length_n = -1;
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000414 r->headers_in.keep_alive_n = -1;
415 r->headers_out.content_length_n = -1;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000416 r->headers_out.last_modified_time = -1;
417
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000418 r->http_state = NGX_HTTP_READING_REQUEST_STATE;
419
Igor Sysoevc04deca2005-03-28 14:43:02 +0000420 ctx = c->log->data;
421 ctx->request = r;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000422 r->log_handler = ngx_http_log_error_handler;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000423
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000424#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000425 ngx_atomic_fetch_add(ngx_stat_reading, 1);
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000426 r->stat_reading = 1;
Igor Sysoev78452232005-10-12 13:50:36 +0000427 ngx_atomic_fetch_add(ngx_stat_requests, 1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000428#endif
429
Igor Sysoev899b44e2005-05-12 14:58:06 +0000430 rev->handler(rev);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000431}
432
433
434#if (NGX_HTTP_SSL)
435
Igor Sysoevc1571722005-03-19 12:38:37 +0000436static void
437ngx_http_ssl_handshake(ngx_event_t *rev)
Igor Sysoevf38e0462004-07-16 17:11:43 +0000438{
Igor Sysoevf38e0462004-07-16 17:11:43 +0000439 u_char buf[1];
Igor Sysoev1b735832004-11-11 14:07:14 +0000440 ssize_t n;
441 ngx_int_t rc;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000442 ngx_connection_t *c;
443 ngx_http_request_t *r;
444
445 c = rev->data;
446 r = c->data;
447
448 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
449 "http check ssl handshake");
450
451 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000452 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
453 c->timedout = 1;
454 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000455 return;
456 }
457
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000458 n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000459
460 if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
461 return;
462 }
463
464 if (n == 1) {
465 if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
466 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000467 "https ssl handshake: 0x%02Xd", buf[0]);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000468
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000469 rc = ngx_ssl_handshake(c);
470
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000471 if (rc == NGX_AGAIN) {
472 c->ssl->handler = ngx_http_ssl_handshake_handler;
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000473 return;
474 }
475
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000476 ngx_http_ssl_handshake_handler(c);
477
478 return;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000479
480 } else {
481 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
482 "plain http");
483
484 r->plain_http = 1;
485 }
486 }
487
Igor Sysoev899b44e2005-05-12 14:58:06 +0000488 rev->handler = ngx_http_process_request_line;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000489 ngx_http_process_request_line(rev);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000490}
491
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000492
493static void
494ngx_http_ssl_handshake_handler(ngx_connection_t *c)
495{
496 ngx_http_request_t *r;
497
498 if (c->ssl->handshaked) {
499
500 /*
501 * The majority of browsers do not send the "close notify" alert.
502 * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
503 * and Links. And what is more, MSIE ignores the server's alert.
504 *
505 * Opera and recent Mozilla send the alert.
506 */
507
508 c->ssl->no_wait_shutdown = 1;
509
510 c->read->handler = ngx_http_process_request_line;
511 /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
512
513 ngx_http_process_request_line(c->read);
514
515 return;
516 }
517
518 r = c->data;
519
520 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000521
522 return;
523}
524
525
Igor Sysoevf38e0462004-07-16 17:11:43 +0000526#endif
527
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000528
Igor Sysoevc1571722005-03-19 12:38:37 +0000529static void
530ngx_http_process_request_line(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000531{
Igor Sysoevf7abd722004-09-23 06:32:00 +0000532 ssize_t n;
Igor Sysoevc3e47462004-09-24 16:12:19 +0000533 ngx_int_t rc, rv;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000534 ngx_connection_t *c;
535 ngx_http_request_t *r;
536 ngx_http_log_ctx_t *ctx;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000537
Igor Sysoeva9830112003-05-19 16:39:14 +0000538 c = rev->data;
539 r = c->data;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000540
Igor Sysoev2b58fbf2003-12-09 15:08:11 +0000541 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
542 "http process request line");
Igor Sysoevdc479b42003-03-20 16:09:44 +0000543
544 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000545 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
546 c->timedout = 1;
547 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000548 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000549 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000550
Igor Sysoevf7abd722004-09-23 06:32:00 +0000551 rc = NGX_AGAIN;
Igor Sysoev016b8522002-08-29 16:59:54 +0000552
Igor Sysoevf7abd722004-09-23 06:32:00 +0000553 for ( ;; ) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000554
Igor Sysoevf7abd722004-09-23 06:32:00 +0000555 if (rc == NGX_AGAIN) {
556 n = ngx_http_read_request_header(r);
Igor Sysoevdc479b42003-03-20 16:09:44 +0000557
Igor Sysoevf7abd722004-09-23 06:32:00 +0000558 if (n == NGX_AGAIN || n == NGX_ERROR) {
Igor Sysoev865c1502003-11-30 20:03:18 +0000559 return;
560 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000561 }
562
Igor Sysoevf7abd722004-09-23 06:32:00 +0000563 rc = ngx_http_parse_request_line(r, r->header_in);
Igor Sysoeva9830112003-05-19 16:39:14 +0000564
Igor Sysoevf7abd722004-09-23 06:32:00 +0000565 if (rc == NGX_OK) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000566
Igor Sysoevf7abd722004-09-23 06:32:00 +0000567 /* the request line has been parsed successfully */
Igor Sysoev6b863e32003-05-12 15:52:24 +0000568
Igor Sysoev1b735832004-11-11 14:07:14 +0000569 r->request_line.len = r->request_end - r->request_start;
570 r->request_line.data = r->request_start;
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000571
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000572
Igor Sysoevdc479b42003-03-20 16:09:44 +0000573 if (r->args_start) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000574 r->uri.len = r->args_start - 1 - r->uri_start;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000575 } else {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000576 r->uri.len = r->uri_end - r->uri_start;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000577 }
578
Igor Sysoevf6906042004-11-25 16:17:31 +0000579
Igor Sysoev924bd792004-10-11 15:07:03 +0000580 if (r->complex_uri || r->quoted_uri) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000581
Igor Sysoevc1571722005-03-19 12:38:37 +0000582 r->uri.data = ngx_palloc(r->pool, r->uri.len + 1);
583 if (r->uri.data == NULL) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000584 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev1b735832004-11-11 14:07:14 +0000585 return;
586 }
587
Igor Sysoevf7abd722004-09-23 06:32:00 +0000588 rc = ngx_http_parse_complex_uri(r);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000589
Igor Sysoevc04deca2005-03-28 14:43:02 +0000590 if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) {
591 ngx_log_error(NGX_LOG_INFO, c->log, 0,
592 "client sent invalid request");
593 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000594 return;
595 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000596
Igor Sysoevf7abd722004-09-23 06:32:00 +0000597 } else {
Igor Sysoev1b735832004-11-11 14:07:14 +0000598 r->uri.data = r->uri_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000599 }
600
Igor Sysoevf6906042004-11-25 16:17:31 +0000601
Igor Sysoev1b735832004-11-11 14:07:14 +0000602 r->unparsed_uri.len = r->uri_end - r->uri_start;
603 r->unparsed_uri.data = r->uri_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000604
Igor Sysoevf7abd722004-09-23 06:32:00 +0000605
Igor Sysoev899b44e2005-05-12 14:58:06 +0000606 r->method_name.len = r->method_end - r->request_start + 1;
607 r->method_name.data = r->request_line.data;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000608
Igor Sysoev1b735832004-11-11 14:07:14 +0000609
Igor Sysoev02025fd2005-01-18 13:03:58 +0000610 if (r->http_protocol.data) {
611 r->http_protocol.len = r->request_end - r->http_protocol.data;
612 }
613
614
Igor Sysoevf7abd722004-09-23 06:32:00 +0000615 if (r->uri_ext) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000616 if (r->args_start) {
617 r->exten.len = r->args_start - 1 - r->uri_ext;
618 } else {
619 r->exten.len = r->uri_end - r->uri_ext;
620 }
621
Igor Sysoev1b735832004-11-11 14:07:14 +0000622 r->exten.data = r->uri_ext;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000623 }
624
Igor Sysoev1b735832004-11-11 14:07:14 +0000625
Igor Sysoevf7abd722004-09-23 06:32:00 +0000626 if (r->args_start && r->uri_end > r->args_start) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000627 r->args.len = r->uri_end - r->args_start;
Igor Sysoev1b735832004-11-11 14:07:14 +0000628 r->args.data = r->args_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000629 }
630
Igor Sysoevf7abd722004-09-23 06:32:00 +0000631
632 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000633 "http request line: \"%V\"", &r->request_line);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000634
635 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000636 "http uri: \"%V\"", &r->uri);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000637
638 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000639 "http args: \"%V\"", &r->args);
640
641 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
642 "http exten: \"%V\"", &r->exten);
643
Igor Sysoevf7abd722004-09-23 06:32:00 +0000644 if (r->http_version < NGX_HTTP_VERSION_10) {
Igor Sysoeve5035392005-08-30 10:55:07 +0000645
646 if (rev->timer_set) {
647 ngx_del_timer(rev);
648 }
649
650#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000651 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoeve5035392005-08-30 10:55:07 +0000652 r->stat_reading = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000653 ngx_atomic_fetch_add(ngx_stat_writing, 1);
Igor Sysoeve5035392005-08-30 10:55:07 +0000654 r->stat_writing = 1;
655#endif
656
657 rev->handler = ngx_http_request_handler;
658 c->write->handler = ngx_http_request_handler;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000659 r->read_event_handler = ngx_http_block_read;
Igor Sysoeve5035392005-08-30 10:55:07 +0000660
Igor Sysoevf7abd722004-09-23 06:32:00 +0000661 ngx_http_handler(r);
Igor Sysoeve5035392005-08-30 10:55:07 +0000662
Igor Sysoev6b863e32003-05-12 15:52:24 +0000663 return;
664 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000665
Igor Sysoevdc479b42003-03-20 16:09:44 +0000666
Igor Sysoevf7abd722004-09-23 06:32:00 +0000667 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000668 sizeof(ngx_table_elt_t))
669 == NGX_ERROR)
Igor Sysoevf7abd722004-09-23 06:32:00 +0000670 {
671 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000672 return;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000673 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000674
675
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000676 if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000677 sizeof(ngx_table_elt_t *))
678 == NGX_ERROR)
Igor Sysoevf7abd722004-09-23 06:32:00 +0000679 {
680 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000681 return;
682 }
683
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000684 c->log->action = "reading client request headers";
Igor Sysoevf7abd722004-09-23 06:32:00 +0000685
Igor Sysoev899b44e2005-05-12 14:58:06 +0000686 rev->handler = ngx_http_process_request_headers;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000687 ngx_http_process_request_headers(rev);
688
689 return;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000690 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000691
Igor Sysoevc04deca2005-03-28 14:43:02 +0000692 if (rc != NGX_AGAIN) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000693
694 /* there was error while a request line parsing */
695
Igor Sysoevc04deca2005-03-28 14:43:02 +0000696 ngx_log_error(NGX_LOG_INFO, c->log, 0,
697 ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
698 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000699 return;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000700 }
701
Igor Sysoevf7abd722004-09-23 06:32:00 +0000702 /* NGX_AGAIN: a request line parsing is still incomplete */
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000703
Igor Sysoev236e0452004-09-23 16:39:34 +0000704 if (r->header_in->pos == r->header_in->end) {
Igor Sysoeva1c8a922004-01-19 18:09:14 +0000705
Igor Sysoevf7abd722004-09-23 06:32:00 +0000706 rv = ngx_http_alloc_large_header_buffer(r, 1);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000707
Igor Sysoevf7abd722004-09-23 06:32:00 +0000708 if (rv == NGX_ERROR) {
709 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000710 return;
711 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000712
Igor Sysoevf7abd722004-09-23 06:32:00 +0000713 if (rv == NGX_DECLINED) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000714 ctx = c->log->data;
715 ctx->request = r;
716
717 r->request_line.len = r->header_in->end - r->request_start;
718 r->request_line.data = r->request_start;
719
720 ngx_log_error(NGX_LOG_INFO, c->log, 0,
721 "client sent too long URI");
722 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000723 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000724 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000725 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000726 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000727}
728
Igor Sysoev1af7c822002-09-13 14:47:42 +0000729
Igor Sysoevc1571722005-03-19 12:38:37 +0000730static void
731ngx_http_process_request_headers(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000732{
Igor Sysoev02f742b2005-04-08 15:18:55 +0000733 ssize_t n;
734 ngx_int_t rc, rv;
735 ngx_uint_t key;
736 ngx_str_t header;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000737 ngx_table_elt_t *h;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000738 ngx_connection_t *c;
739 ngx_http_header_t *hh;
740 ngx_http_request_t *r;
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000741 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000742 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000743
Igor Sysoeva9830112003-05-19 16:39:14 +0000744 c = rev->data;
745 r = c->data;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000746
Igor Sysoev865c1502003-11-30 20:03:18 +0000747 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
748 "http process request header line");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000749
Igor Sysoev6b863e32003-05-12 15:52:24 +0000750 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000751 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
752 c->timedout = 1;
753 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000754 return;
755 }
756
Igor Sysoev02f742b2005-04-08 15:18:55 +0000757 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000758 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000759 hh = (ngx_http_header_t *) cmcf->headers_in_hash.buckets;
760
Igor Sysoevd581fd52003-05-13 16:02:32 +0000761 rc = NGX_AGAIN;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000762
Igor Sysoev016b8522002-08-29 16:59:54 +0000763 for ( ;; ) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000764
Igor Sysoevd581fd52003-05-13 16:02:32 +0000765 if (rc == NGX_AGAIN) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000766
Igor Sysoev236e0452004-09-23 16:39:34 +0000767 if (r->header_in->pos == r->header_in->end) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000768
769 rv = ngx_http_alloc_large_header_buffer(r, 0);
770
771 if (rv == NGX_ERROR) {
772 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000773 return;
774 }
775
776 if (rv == NGX_DECLINED) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000777 header.len = r->header_in->end - r->header_name_start;
778 header.data = r->header_name_start;
Igor Sysoev90c08142005-07-25 09:41:38 +0000779
780 if (header.len > NGX_MAX_ERROR_STR - 300) {
781 header.len = NGX_MAX_ERROR_STR - 300;
782 header.data[header.len++] = '.';
783 header.data[header.len++] = '.';
784 header.data[header.len++] = '.';
785 }
786
Igor Sysoevc04deca2005-03-28 14:43:02 +0000787 ngx_log_error(NGX_LOG_INFO, c->log, 0,
788 "client sent too long header line: \"%V\"",
789 &header);
790 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000791 return;
792 }
793 }
794
Igor Sysoevd581fd52003-05-13 16:02:32 +0000795 n = ngx_http_read_request_header(r);
796
797 if (n == NGX_AGAIN || n == NGX_ERROR) {
798 return;
799 }
800 }
801
Igor Sysoeve6779222003-10-03 15:50:53 +0000802 rc = ngx_http_parse_header_line(r, r->header_in);
Igor Sysoev016b8522002-08-29 16:59:54 +0000803
Igor Sysoev0dad6292003-03-05 17:30:51 +0000804 if (rc == NGX_OK) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000805
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000806 if (r->invalid_header && cscf->ignore_invalid_headers) {
Igor Sysoev4d656dc2005-03-22 16:02:46 +0000807
808 /* there was error while a header line parsing */
809
810 header.len = r->header_end - r->header_name_start;
811 header.data = r->header_name_start;
812
Igor Sysoevc04deca2005-03-28 14:43:02 +0000813 ngx_log_error(NGX_LOG_INFO, c->log, 0,
814 "client sent invalid header line: \"%V\"",
Igor Sysoev4d656dc2005-03-22 16:02:46 +0000815 &header);
816 continue;
817 }
818
Igor Sysoevd581fd52003-05-13 16:02:32 +0000819 /* a header line has been parsed successfully */
820
Igor Sysoevc1571722005-03-19 12:38:37 +0000821 h = ngx_list_push(&r->headers_in.headers);
822 if (h == NULL) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000823 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000824 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000825 }
826
Igor Sysoev02f742b2005-04-08 15:18:55 +0000827 h->hash = r->header_hash;
828
Igor Sysoevd581fd52003-05-13 16:02:32 +0000829 h->key.len = r->header_name_end - r->header_name_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000830 h->key.data = r->header_name_start;
831 h->key.data[h->key.len] = '\0';
832
Igor Sysoevd581fd52003-05-13 16:02:32 +0000833 h->value.len = r->header_end - r->header_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000834 h->value.data = r->header_start;
835 h->value.data[h->value.len] = '\0';
Igor Sysoevd581fd52003-05-13 16:02:32 +0000836
Igor Sysoev899b44e2005-05-12 14:58:06 +0000837 key = h->hash % cmcf->headers_in_hash.hash_size;
838
839 if (hh[key].name.len == h->key.len
840 && ngx_strcasecmp(hh[key].name.data, h->key.data) == 0)
Igor Sysoev967fd632004-08-27 15:40:59 +0000841 {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000842 if (hh[key].handler(r, h, hh[key].offset) != NGX_OK) {
Igor Sysoev967fd632004-08-27 15:40:59 +0000843 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000844 }
Igor Sysoevd581fd52003-05-13 16:02:32 +0000845 }
846
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000847 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000848 "http header: \"%V: %V\"",
849 &h->key, &h->value);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000850
Igor Sysoev6253ca12003-05-27 12:18:54 +0000851 continue;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000852 }
Igor Sysoev6253ca12003-05-27 12:18:54 +0000853
Igor Sysoevc04deca2005-03-28 14:43:02 +0000854 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000855
856 /* a whole header has been parsed successfully */
857
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000858 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
859 "http header done");
Igor Sysoev42feecb2002-12-15 06:25:09 +0000860
Igor Sysoev6a12fc92004-12-06 14:45:08 +0000861 r->request_length += r->header_in->pos - r->header_in->start;
862
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000863 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
864
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000865 rc = ngx_http_process_request_header(r);
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000866
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000867 if (rc != NGX_OK) {
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000868 return;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000869 }
870
Igor Sysoev425a42c2003-10-27 16:16:17 +0000871 if (rev->timer_set) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000872 ngx_del_timer(rev);
873 }
874
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000875#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000876 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000877 r->stat_reading = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000878 ngx_atomic_fetch_add(ngx_stat_writing, 1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000879 r->stat_writing = 1;
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000880#endif
881
Igor Sysoev899b44e2005-05-12 14:58:06 +0000882 rev->handler = ngx_http_request_handler;
883 c->write->handler = ngx_http_request_handler;
884 r->read_event_handler = ngx_http_block_read;
885
Igor Sysoevd581fd52003-05-13 16:02:32 +0000886 ngx_http_handler(r);
Igor Sysoeve5035392005-08-30 10:55:07 +0000887
Igor Sysoevd581fd52003-05-13 16:02:32 +0000888 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000889 }
890
Igor Sysoevc04deca2005-03-28 14:43:02 +0000891 if (rc == NGX_AGAIN) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000892
Igor Sysoevc04deca2005-03-28 14:43:02 +0000893 /* a header line parsing is still not complete */
894
895 continue;
896 }
897
898 /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
899
900 header.len = r->header_end - r->header_name_start;
901 header.data = r->header_name_start;
902 ngx_log_error(NGX_LOG_INFO, c->log, 0,
903 "client sent invalid header line: \"%V\\r...\"",
904 &header);
905 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevc04deca2005-03-28 14:43:02 +0000906 return;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000907 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000908}
909
Igor Sysoevb0869052002-12-10 18:05:12 +0000910
Igor Sysoevc1571722005-03-19 12:38:37 +0000911static ssize_t
912ngx_http_read_request_header(ngx_http_request_t *r)
Igor Sysoev6b863e32003-05-12 15:52:24 +0000913{
Igor Sysoev187fcd82003-05-23 11:53:01 +0000914 ssize_t n;
915 ngx_event_t *rev;
916 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000917
Igor Sysoev239baac2003-06-11 15:28:34 +0000918 rev = r->connection->read;
919
Igor Sysoev6b863e32003-05-12 15:52:24 +0000920 n = r->header_in->last - r->header_in->pos;
921
922 if (n > 0) {
923 return n;
924 }
925
Igor Sysoevb145b062005-06-15 18:33:41 +0000926 if (rev->ready) {
927 n = r->connection->recv(r->connection, r->header_in->last,
928 r->header_in->end - r->header_in->last);
929 } else {
930 n = NGX_AGAIN;
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000931 }
932
Igor Sysoev6b863e32003-05-12 15:52:24 +0000933 if (n == NGX_AGAIN) {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000934 if (!r->header_timeout_set) {
Igor Sysoevf38e0462004-07-16 17:11:43 +0000935 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev187fcd82003-05-23 11:53:01 +0000936 ngx_add_timer(rev, cscf->client_header_timeout);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000937 r->header_timeout_set = 1;
938 }
939
Igor Sysoevb5faed22003-10-29 08:30:44 +0000940 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000941 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000942 return NGX_ERROR;
943 }
944
Igor Sysoev6b863e32003-05-12 15:52:24 +0000945 return NGX_AGAIN;
946 }
947
948 if (n == 0) {
949 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
950 "client closed prematurely connection");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000951 }
Igor Sysoev6b863e32003-05-12 15:52:24 +0000952
953 if (n == 0 || n == NGX_ERROR) {
954 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000955 return NGX_ERROR;
956 }
957
958 r->header_in->last += n;
959
960 return n;
961}
962
963
Igor Sysoevc1571722005-03-19 12:38:37 +0000964static ngx_int_t
965ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
966 ngx_uint_t request_line)
Igor Sysoev85080d02004-09-22 16:18:21 +0000967{
968 u_char *old, *new;
Igor Sysoev85080d02004-09-22 16:18:21 +0000969 ngx_buf_t *b;
970 ngx_http_connection_t *hc;
971 ngx_http_core_srv_conf_t *cscf;
972
973 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
974 "http alloc large header buffer");
975
Igor Sysoevf7abd722004-09-23 06:32:00 +0000976 if (request_line && r->state == 0) {
977
978 /* the client fills up the buffer with "\r\n" */
979
Igor Sysoev6a12fc92004-12-06 14:45:08 +0000980 r->request_length += r->header_in->end - r->header_in->start;
981
Igor Sysoevf7abd722004-09-23 06:32:00 +0000982 r->header_in->pos = r->header_in->start;
983 r->header_in->last = r->header_in->start;
984
985 return NGX_OK;
986 }
987
Igor Sysoev85080d02004-09-22 16:18:21 +0000988 old = request_line ? r->request_start : r->header_name_start;
989
990 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
991
Igor Sysoevf7abd722004-09-23 06:32:00 +0000992 if (r->state != 0
993 && (size_t) (r->header_in->pos - old)
994 >= cscf->large_client_header_buffers.size)
995 {
Igor Sysoev85080d02004-09-22 16:18:21 +0000996 return NGX_DECLINED;
997 }
998
999 hc = r->http_connection;
1000
1001 if (hc->nfree) {
1002 b = hc->free[--hc->nfree];
1003
Igor Sysoev236e0452004-09-23 16:39:34 +00001004 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +00001005 "http large header free: %p %uz",
Igor Sysoev236e0452004-09-23 16:39:34 +00001006 b->pos, b->end - b->last);
1007
Igor Sysoevf7abd722004-09-23 06:32:00 +00001008 } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
Igor Sysoev85080d02004-09-22 16:18:21 +00001009
1010 if (hc->busy == NULL) {
1011 hc->busy = ngx_palloc(r->connection->pool,
Igor Sysoevf7abd722004-09-23 06:32:00 +00001012 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev85080d02004-09-22 16:18:21 +00001013 if (hc->busy == NULL) {
1014 return NGX_ERROR;
1015 }
1016 }
1017
1018 b = ngx_create_temp_buf(r->connection->pool,
Igor Sysoevf7abd722004-09-23 06:32:00 +00001019 cscf->large_client_header_buffers.size);
Igor Sysoev85080d02004-09-22 16:18:21 +00001020 if (b == NULL) {
1021 return NGX_ERROR;
1022 }
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 alloc: %p %uz",
Igor Sysoev236e0452004-09-23 16:39:34 +00001026 b->pos, b->end - b->last);
1027
Igor Sysoev85080d02004-09-22 16:18:21 +00001028 } else {
1029 return NGX_DECLINED;
1030 }
1031
1032 hc->busy[hc->nbusy++] = b;
1033
Igor Sysoevf7abd722004-09-23 06:32:00 +00001034 if (r->state == 0) {
1035 /*
1036 * r->state == 0 means that a header line was parsed successfully
1037 * and we do not need to copy incomplete header line and
1038 * to relocate the parser header pointers
1039 */
1040
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001041 r->request_length += r->header_in->end - r->header_in->start;
1042
Igor Sysoevf7abd722004-09-23 06:32:00 +00001043 r->header_in = b;
1044
1045 return NGX_OK;
1046 }
1047
Igor Sysoev236e0452004-09-23 16:39:34 +00001048 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1049 "http large header copy: %d", r->header_in->pos - old);
1050
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001051 r->request_length += old - r->header_in->start;
1052
Igor Sysoev85080d02004-09-22 16:18:21 +00001053 new = b->start;
1054
Igor Sysoev236e0452004-09-23 16:39:34 +00001055 ngx_memcpy(new, old, r->header_in->pos - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001056
1057 b->pos = new + (r->header_in->pos - old);
Igor Sysoev236e0452004-09-23 16:39:34 +00001058 b->last = new + (r->header_in->pos - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001059
1060 if (request_line) {
1061 r->request_start = new;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001062
1063 if (r->request_end) {
1064 r->request_end = new + (r->request_end - old);
1065 }
1066
1067 r->method_end = new + (r->method_end - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001068
1069 r->uri_start = new + (r->uri_start - old);
1070 r->uri_end = new + (r->uri_end - old);
1071
Igor Sysoevf7abd722004-09-23 06:32:00 +00001072 if (r->schema_start) {
1073 r->schema_start = new + (r->schema_start - old);
1074 r->schema_end = new + (r->schema_end - old);
1075 }
1076
1077 if (r->host_start) {
1078 r->host_start = new + (r->host_start - old);
1079 r->host_end = new + (r->host_end - old);
1080 }
1081
1082 if (r->port_start) {
1083 r->port_start = new + (r->port_start - old);
1084 r->port_end = new + (r->port_end - old);
1085 }
1086
Igor Sysoev85080d02004-09-22 16:18:21 +00001087 if (r->uri_ext) {
1088 r->uri_ext = new + (r->uri_ext - old);
1089 }
1090
1091 if (r->args_start) {
1092 r->args_start = new + (r->args_start - old);
1093 }
1094
1095 } else {
1096 r->header_name_start = new;
1097 r->header_name_end = new + (r->header_name_end - old);
1098 r->header_start = new + (r->header_start - old);
1099 r->header_end = new + (r->header_end - old);
1100 }
1101
1102 r->header_in = b;
1103
1104 return NGX_OK;
1105}
1106
Igor Sysoev85080d02004-09-22 16:18:21 +00001107
Igor Sysoevc1571722005-03-19 12:38:37 +00001108static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001109ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1110 ngx_uint_t offset)
1111{
1112 ngx_table_elt_t **ph;
1113
1114 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1115
1116 if (*ph == NULL) {
1117 *ph = h;
1118 }
1119
1120 return NGX_OK;
1121}
1122
1123
1124static ngx_int_t
Igor Sysoevb145b062005-06-15 18:33:41 +00001125ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1126 ngx_uint_t offset)
1127{
1128 ngx_table_elt_t **ph;
1129
1130 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1131
1132 if (*ph == NULL) {
1133 *ph = h;
1134 return NGX_OK;
1135 }
1136
1137 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1138 "client sent duplicate header line: \"%V: %V\"",
1139 &h->key, &h->value);
1140
1141 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1142
1143 return NGX_ERROR;
1144}
1145
1146
1147static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001148ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
1149 ngx_uint_t offset)
1150{
1151 ngx_table_elt_t **cookie;
1152
1153 cookie = ngx_array_push(&r->headers_in.cookies);
Igor Sysoevb145b062005-06-15 18:33:41 +00001154 if (cookie) {
1155 *cookie = h;
1156 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001157 }
1158
Igor Sysoevb145b062005-06-15 18:33:41 +00001159 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001160
Igor Sysoevb145b062005-06-15 18:33:41 +00001161 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001162}
1163
1164
1165static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001166ngx_http_process_request_header(ngx_http_request_t *r)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001167{
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001168 size_t len;
1169 u_char *ua, *user_agent, ch;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001170
1171 if (r->headers_in.host) {
1172 for (len = 0; len < r->headers_in.host->value.len; len++) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001173 ch = r->headers_in.host->value.data[len];
1174
1175 if (ch == ':') {
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001176 break;
1177 }
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001178
1179 r->headers_in.host->value.data[len] = ngx_tolower(ch);
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001180 }
Igor Sysoevc04deca2005-03-28 14:43:02 +00001181
Igor Sysoev899b44e2005-05-12 14:58:06 +00001182 if (r->headers_in.host->value.data[len - 1] == '.') {
1183 len--;
1184 }
1185
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001186 r->headers_in.host_name_len = len;
1187
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001188 ngx_http_find_virtual_server(r);
Igor Sysoev3043bfc2004-05-14 16:51:47 +00001189
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001190 } else {
1191 if (r->http_version > NGX_HTTP_VERSION_10) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001192 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1193 "client sent HTTP/1.1 request without \"Host\" header");
1194 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1195 return NGX_ERROR;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001196 }
Igor Sysoevc04deca2005-03-28 14:43:02 +00001197
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001198 r->headers_in.host_name_len = 0;
1199 }
1200
1201 if (r->headers_in.content_length) {
1202 r->headers_in.content_length_n =
Igor Sysoevc1571722005-03-19 12:38:37 +00001203 ngx_atosz(r->headers_in.content_length->value.data,
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001204 r->headers_in.content_length->value.len);
1205
1206 if (r->headers_in.content_length_n == NGX_ERROR) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001207 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1208 "client sent invalid \"Content-Length\" header");
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001209 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
Igor Sysoevc04deca2005-03-28 14:43:02 +00001210 return NGX_ERROR;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001211 }
1212 }
1213
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001214 if (r->method == NGX_HTTP_POST && r->headers_in.content_length_n == -1) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001215 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1216 "client sent POST method without \"Content-Length\" header");
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001217 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
1218 return NGX_ERROR;
1219 }
1220
1221 if (r->headers_in.transfer_encoding
1222 && ngx_strstr(r->headers_in.transfer_encoding->value.data, "chunked"))
1223 {
1224 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1225 "client sent \"Transfer-Encoding: chunked\" header");
1226 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
Igor Sysoevc04deca2005-03-28 14:43:02 +00001227 return NGX_ERROR;
Igor Sysoev6881bfb2004-03-30 06:27:36 +00001228 }
1229
Igor Sysoevf38e0462004-07-16 17:11:43 +00001230 if (r->plain_http) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001231 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1232 "client sent plain HTTP request to HTTPS port");
1233 ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1234 return NGX_ERROR;
Igor Sysoevf38e0462004-07-16 17:11:43 +00001235 }
1236
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001237 if (r->headers_in.connection) {
1238 if (r->headers_in.connection->value.len == 5
1239 && ngx_strcasecmp(r->headers_in.connection->value.data, "close")
Igor Sysoev899b44e2005-05-12 14:58:06 +00001240 == 0)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001241 {
1242 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1243
1244 } else if (r->headers_in.connection->value.len == 10
1245 && ngx_strcasecmp(r->headers_in.connection->value.data,
Igor Sysoev899b44e2005-05-12 14:58:06 +00001246 "keep-alive") == 0)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001247 {
1248 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1249
1250 if (r->headers_in.keep_alive) {
1251 r->headers_in.keep_alive_n =
Igor Sysoevc1571722005-03-19 12:38:37 +00001252 ngx_atotm(r->headers_in.keep_alive->value.data,
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001253 r->headers_in.keep_alive->value.len);
1254 }
1255 }
1256 }
1257
Igor Sysoev2f657222004-06-16 15:32:11 +00001258 if (r->headers_in.user_agent) {
1259
1260 /*
1261 * check some widespread browsers while the headers are still
1262 * in CPU cache
1263 */
1264
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001265 user_agent = r->headers_in.user_agent->value.data;
1266
1267 ua = (u_char *) ngx_strstr(user_agent, "MSIE");
1268
1269 if (ua && ua + 8 < user_agent + r->headers_in.user_agent->value.len) {
1270
Igor Sysoev2f657222004-06-16 15:32:11 +00001271 r->headers_in.msie = 1;
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001272
Igor Sysoev2f657222004-06-16 15:32:11 +00001273 if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') {
1274 r->headers_in.msie4 = 1;
1275 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001276
1277#if 0
1278 /* MSIE ignores the SSL "close notify" alert */
Igor Sysoev42b12b32004-12-02 18:40:46 +00001279 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00001280 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00001281 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001282#endif
Igor Sysoev2f657222004-06-16 15:32:11 +00001283 }
Igor Sysoev85cccfb2004-09-15 16:00:43 +00001284
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001285 if (ngx_strstr(user_agent, "Opera")) {
Igor Sysoev85cccfb2004-09-15 16:00:43 +00001286 r->headers_in.opera = 1;
1287 r->headers_in.msie = 0;
1288 r->headers_in.msie4 = 0;
1289 }
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001290
1291 if (!r->headers_in.msie && !r->headers_in.opera) {
1292
Igor Sysoeva2c81192004-09-19 18:27:00 +00001293 if (ngx_strstr(user_agent, "Gecko/")) {
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001294 r->headers_in.gecko = 1;
1295
1296 } else if (ngx_strstr(user_agent, "Konqueror")) {
1297 r->headers_in.konqueror = 1;
1298 }
1299 }
Igor Sysoev2f657222004-06-16 15:32:11 +00001300 }
1301
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001302 return NGX_OK;
1303}
1304
1305
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001306static void
Igor Sysoevc1571722005-03-19 12:38:37 +00001307ngx_http_find_virtual_server(ngx_http_request_t *r)
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001308{
Igor Sysoev305a9d82005-12-26 17:07:48 +00001309 size_t len;
1310 u_char *host;
1311 ngx_http_virtual_names_t *vn;
1312 ngx_http_core_loc_conf_t *clcf;
1313 ngx_http_core_srv_conf_t *cscf;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001314
Igor Sysoev305a9d82005-12-26 17:07:48 +00001315 vn = r->virtual_names;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001316
Igor Sysoev305a9d82005-12-26 17:07:48 +00001317 if (vn == NULL) {
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001318 return;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001319 }
1320
Igor Sysoev305a9d82005-12-26 17:07:48 +00001321 host = r->headers_in.host->value.data;
1322 len = r->headers_in.host_name_len;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001323
Igor Sysoev305a9d82005-12-26 17:07:48 +00001324 /* STUB: ngx_hash_key() here is STUB */
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001325
Igor Sysoev305a9d82005-12-26 17:07:48 +00001326 if (vn->hash.buckets) {
1327 cscf = ngx_hash_find(&vn->hash, ngx_hash_key(host, len), host, len);
1328 if (cscf) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001329 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001330 }
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001331 }
1332
Igor Sysoev305a9d82005-12-26 17:07:48 +00001333 if (vn->dns_wildcards && vn->dns_wildcards->hash.buckets) {
1334 cscf = ngx_hash_find_wildcard(vn->dns_wildcards, host, len);
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001335
Igor Sysoev305a9d82005-12-26 17:07:48 +00001336 if (cscf) {
1337 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001338 }
1339 }
1340
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001341 return;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001342
Igor Sysoev899b44e2005-05-12 14:58:06 +00001343found:
1344
Igor Sysoev305a9d82005-12-26 17:07:48 +00001345 r->server_name.len = len;
1346 r->server_name.data = host;
1347
1348 r->srv_conf = cscf->ctx->srv_conf;
1349 r->loc_conf = cscf->ctx->loc_conf;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001350
1351 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1352 r->connection->log->file = clcf->err_log->file;
1353
1354 if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1355 r->connection->log->log_level = clcf->err_log->log_level;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001356 }
1357
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001358 return;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001359}
1360
1361
Igor Sysoev899b44e2005-05-12 14:58:06 +00001362static void
1363ngx_http_request_handler(ngx_event_t *ev)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001364{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001365 ngx_connection_t *c;
1366 ngx_http_request_t *r;
1367
1368 c = ev->data;
1369 r = c->data;
1370
1371 if (ev->write) {
1372 r->write_event_handler(r);
1373
1374 } else {
1375 r->read_event_handler(r);
1376 }
1377}
1378
1379
1380void
1381ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1382{
1383 ngx_http_request_t *pr;
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001384 ngx_http_core_loc_conf_t *clcf;
1385
Igor Sysoev899b44e2005-05-12 14:58:06 +00001386 if (rc == NGX_DONE) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001387 /* the request pool may be already destroyed */
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001388 return;
1389 }
1390
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001391 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1392 "http finalize request: %d, \"%V?%V\"",
1393 rc, &r->uri, &r->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001394
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001395 if (rc == NGX_ERROR
1396 || rc == NGX_HTTP_REQUEST_TIME_OUT
1397 || r->connection->error)
1398 {
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001399 if (ngx_http_post_action(r) == NGX_OK) {
1400 return;
1401 }
1402
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001403 ngx_http_close_request(r, 0);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001404 return;
1405 }
1406
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001407 if (rc >= NGX_HTTP_SPECIAL_RESPONSE || rc == NGX_HTTP_NO_CONTENT) {
1408
Igor Sysoevcdc46302005-12-07 14:51:31 +00001409 if (rc == NGX_HTTP_CLOSE) {
1410 ngx_http_close_request(r, rc);
1411 return;
1412 }
1413
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001414 if (r == r->main) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001415 if (r->connection->read->timer_set) {
1416 ngx_del_timer(r->connection->read);
1417 }
1418
1419 if (r->connection->write->timer_set) {
1420 ngx_del_timer(r->connection->write);
1421 }
1422 }
1423
1424 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
1425
1426 return;
1427 }
1428
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001429 if (r != r->main || rc == NGX_AGAIN) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001430 if (ngx_http_set_write_handler(r) != NGX_OK) {
1431 return;
1432 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001433 }
1434
1435 r->done = 1;
1436
1437 if (r != r->connection->data) {
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001438 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1439 "http finalize non-active request: \"%V?%V\"",
1440 &r->uri, &r->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001441 return;
1442 }
1443
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001444 if (r != r->main) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001445
1446 pr = r->parent;
1447
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001448 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1449 "http parent request: \"%V?%V\"", &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001450
Igor Sysoev899b44e2005-05-12 14:58:06 +00001451 if (rc != NGX_AGAIN) {
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001452 r->connection->data = pr;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001453 }
1454
1455 if (pr->postponed) {
1456
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001457 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1458 "http request: \"%V?%V\" has postponed",
1459 &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001460
Igor Sysoev899b44e2005-05-12 14:58:06 +00001461 if (rc != NGX_AGAIN && pr->postponed->request == r) {
1462 pr->postponed = pr->postponed->next;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001463 }
1464
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001465 if (r->fast_subrequest) {
1466 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1467 "http fast subrequest: \"%V?%V\" done",
1468 &r->uri, &r->args);
1469 return;
1470 }
1471
1472 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1473 "http wake parent request: \"%V?%V\"",
1474 &pr->uri, &pr->args);
1475
1476 pr->write_event_handler(pr);
1477
1478#if 0
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001479 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1480 "http request: \"%V?%V\" still has postponed",
1481 &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001482
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001483 if (pr->done || pr->postponed->out) {
1484 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1485 "http wake parent request: \"%V?%V\"",
1486 &pr->uri, &pr->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001487
1488 pr->write_event_handler(pr);
1489 }
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001490#endif
1491
Igor Sysoev899b44e2005-05-12 14:58:06 +00001492 }
1493
1494 return;
1495 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001496
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001497 if (rc == NGX_AGAIN) {
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001498 return;
Igor Sysoev5192b362005-07-08 14:34:20 +00001499 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001500
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001501 if (r->connection->buffered) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001502 (void) ngx_http_set_write_handler(r);
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001503 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001504 }
1505
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001506 if (ngx_http_post_action(r) == NGX_OK) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001507 return;
1508 }
1509
Igor Sysoev0a280a32003-10-12 16:49:16 +00001510 if (r->connection->read->timer_set) {
1511 ngx_del_timer(r->connection->read);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001512 }
1513
Igor Sysoev0a280a32003-10-12 16:49:16 +00001514 if (r->connection->write->timer_set) {
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001515 r->connection->write->delayed = 0;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001516 ngx_del_timer(r->connection->write);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001517 }
1518
Igor Sysoev24025022005-12-16 15:07:08 +00001519 if (r->connection->destroyed) {
1520 return;
1521 }
1522
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001523 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001524
Igor Sysoevc5991982004-01-16 06:15:48 +00001525 if (!ngx_terminate
Igor Sysoev3f4685f2004-04-25 20:13:21 +00001526 && !ngx_exiting
Igor Sysoevc5991982004-01-16 06:15:48 +00001527 && r->keepalive != 0
1528 && clcf->keepalive_timeout > 0)
1529 {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001530 ngx_http_set_keepalive(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001531 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001532
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001533 } else if (r->lingering_close && clcf->lingering_timeout > 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001534 ngx_http_set_lingering_close(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001535 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001536 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001537
Igor Sysoevc5991982004-01-16 06:15:48 +00001538 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001539}
1540
1541
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001542static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001543ngx_http_set_write_handler(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001544{
Igor Sysoevd581fd52003-05-13 16:02:32 +00001545 ngx_event_t *wev;
Igor Sysoeva9830112003-05-19 16:39:14 +00001546 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001547
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001548 r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
1549
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001550 r->write_event_handler = ngx_http_writer;
1551
Igor Sysoev899b44e2005-05-12 14:58:06 +00001552 wev = r->connection->write;
1553
Igor Sysoevef066482004-06-21 15:59:32 +00001554 if (wev->ready && wev->delayed) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001555 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001556 }
1557
Igor Sysoev899b44e2005-05-12 14:58:06 +00001558 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001559 if (!wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001560 ngx_add_timer(wev, clcf->send_timeout);
1561 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001562
Igor Sysoev924bd792004-10-11 15:07:03 +00001563 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001564 ngx_http_close_request(r, 0);
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001565 return NGX_ERROR;
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001566 }
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001567
1568 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001569}
1570
1571
Igor Sysoev899b44e2005-05-12 14:58:06 +00001572static void
1573ngx_http_writer(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001574{
1575 int rc;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001576 ngx_event_t *wev;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001577 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001578 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001579
Igor Sysoev899b44e2005-05-12 14:58:06 +00001580 c = r->connection;
1581 wev = c->write;
Igor Sysoev160d7742003-11-19 16:26:41 +00001582
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001583 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1584 "http writer handler: \"%V?%V\"", &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001585
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001586 if (wev->timedout) {
Igor Sysoevef066482004-06-21 15:59:32 +00001587 if (!wev->delayed) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001588 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
1589 "client timed out");
1590 c->timedout = 1;
Igor Sysoev055951d2005-10-21 19:12:18 +00001591
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001592 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001593 return;
1594 }
1595
1596 wev->timedout = 0;
Igor Sysoevef066482004-06-21 15:59:32 +00001597 wev->delayed = 0;
Igor Sysoev73a73b52004-06-20 19:54:15 +00001598
1599 if (!wev->ready) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001600 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001601 ngx_add_timer(wev, clcf->send_timeout);
1602
Igor Sysoev924bd792004-10-11 15:07:03 +00001603 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001604 ngx_http_close_request(r, 0);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001605 }
1606
1607 return;
1608 }
1609
1610 } else {
Igor Sysoevef066482004-06-21 15:59:32 +00001611 if (wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001612 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1613 "http writer delayed");
Igor Sysoevef066482004-06-21 15:59:32 +00001614
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001615 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001616
Igor Sysoev924bd792004-10-11 15:07:03 +00001617 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001618 ngx_http_close_request(r, 0);
Igor Sysoevef066482004-06-21 15:59:32 +00001619 }
1620
Igor Sysoev73a73b52004-06-20 19:54:15 +00001621 return;
1622 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001623 }
1624
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001625 rc = ngx_http_output_filter(r, NULL);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001626
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001627 if (c->destroyed) {
1628 return;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001629 }
1630
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001631 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
1632 "http writer output filter: %d, \"%V?%V\"",
1633 rc, &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001634
1635 if (rc == NGX_AGAIN) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001636 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001637 if (!wev->ready && !wev->delayed) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001638 ngx_add_timer(wev, clcf->send_timeout);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001639 }
1640
Igor Sysoev924bd792004-10-11 15:07:03 +00001641 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001642 ngx_http_close_request(r, 0);
Igor Sysoev0a280a32003-10-12 16:49:16 +00001643 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001644
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001645 if (r == r->main) {
1646 return;
1647 }
1648
1649 rc = NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001650 }
1651
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001652 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1653 "http writer done: \"%V?%V\"", &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001654
Igor Sysoev0a280a32003-10-12 16:49:16 +00001655 ngx_http_finalize_request(r, rc);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001656}
1657
1658
Igor Sysoev899b44e2005-05-12 14:58:06 +00001659static void
1660ngx_http_block_read(ngx_http_request_t *r)
1661{
1662 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1663 "http read blocked");
Igor Sysoev42feecb2002-12-15 06:25:09 +00001664
Igor Sysoev73009772003-02-06 17:21:13 +00001665 /* aio does not call this handler */
1666
Igor Sysoev899b44e2005-05-12 14:58:06 +00001667 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
1668 && r->connection->read->active)
1669 {
1670 if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0)
1671 == NGX_ERROR)
1672 {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001673 ngx_http_close_request(r, 0);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001674 }
Igor Sysoev73009772003-02-06 17:21:13 +00001675 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001676}
1677
1678
Igor Sysoevc1571722005-03-19 12:38:37 +00001679ngx_int_t
1680ngx_http_discard_body(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001681{
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001682 ssize_t size;
1683 ngx_event_t *rev;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001684
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001685 if (r != r->main) {
Igor Sysoev7b190b42005-06-07 15:56:31 +00001686 return NGX_OK;
1687 }
1688
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001689 rev = r->connection->read;
Igor Sysoev9b25d692003-01-26 21:08:14 +00001690
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001691 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body");
Igor Sysoev9b25d692003-01-26 21:08:14 +00001692
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001693 if (rev->timer_set) {
1694 ngx_del_timer(rev);
Igor Sysoev9b25d692003-01-26 21:08:14 +00001695 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001696
Igor Sysoev0a280a32003-10-12 16:49:16 +00001697 if (r->headers_in.content_length_n <= 0) {
1698 return NGX_OK;
1699 }
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001700
Igor Sysoeve5035392005-08-30 10:55:07 +00001701 r->discard_body = 1;
1702
Igor Sysoev0a280a32003-10-12 16:49:16 +00001703 size = r->header_in->last - r->header_in->pos;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001704
Igor Sysoev0a280a32003-10-12 16:49:16 +00001705 if (size) {
1706 if (r->headers_in.content_length_n > size) {
1707 r->headers_in.content_length_n -= size;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001708
Igor Sysoev0a280a32003-10-12 16:49:16 +00001709 } else {
1710 r->header_in->pos += r->headers_in.content_length_n;
1711 r->headers_in.content_length_n = 0;
1712 return NGX_OK;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001713 }
Igor Sysoev73009772003-02-06 17:21:13 +00001714 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001715
Igor Sysoev899b44e2005-05-12 14:58:06 +00001716 r->read_event_handler = ngx_http_read_discarded_body_handler;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001717
Igor Sysoev899b44e2005-05-12 14:58:06 +00001718 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001719 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1720 }
1721
1722 return ngx_http_read_discarded_body(r);
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001723}
1724
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001725
Igor Sysoevc1571722005-03-19 12:38:37 +00001726static void
Igor Sysoev899b44e2005-05-12 14:58:06 +00001727ngx_http_read_discarded_body_handler(ngx_http_request_t *r)
Igor Sysoev42feecb2002-12-15 06:25:09 +00001728{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001729 ngx_int_t rc;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001730
1731 rc = ngx_http_read_discarded_body(r);
1732
Igor Sysoev0a280a32003-10-12 16:49:16 +00001733 if (rc == NGX_AGAIN) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001734 if (ngx_handle_read_event(r->connection->read, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001735 ngx_http_close_request(r, rc);
Igor Sysoev0a280a32003-10-12 16:49:16 +00001736 return;
1737 }
1738 }
1739
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001740 if (rc != NGX_OK) {
1741 ngx_http_close_request(r, rc);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001742 }
1743}
1744
1745
Igor Sysoevc1571722005-03-19 12:38:37 +00001746static ngx_int_t
1747ngx_http_read_discarded_body(ngx_http_request_t *r)
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001748{
Igor Sysoevf7abd722004-09-23 06:32:00 +00001749 ssize_t size, n;
1750 u_char buffer[NGX_HTTP_DISCARD_BUFFER_SIZE];
Igor Sysoev42feecb2002-12-15 06:25:09 +00001751
Igor Sysoeve04084c2004-01-26 08:52:49 +00001752 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1753 "http read discarded body");
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001754
Igor Sysoev0a280a32003-10-12 16:49:16 +00001755 if (r->headers_in.content_length_n == 0) {
1756 return NGX_OK;
1757 }
1758
Igor Sysoev42feecb2002-12-15 06:25:09 +00001759
Igor Sysoeva09f08d2003-04-25 14:43:13 +00001760 size = r->headers_in.content_length_n;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001761
Igor Sysoevf7abd722004-09-23 06:32:00 +00001762 if (size > NGX_HTTP_DISCARD_BUFFER_SIZE) {
1763 size = NGX_HTTP_DISCARD_BUFFER_SIZE;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001764 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001765
Igor Sysoevf7abd722004-09-23 06:32:00 +00001766 n = r->connection->recv(r->connection, buffer, size);
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001767
Igor Sysoevdc479b42003-03-20 16:09:44 +00001768 if (n == NGX_ERROR) {
Igor Sysoev89690bf2004-03-23 06:01:52 +00001769
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001770 r->connection->error = 1;
Igor Sysoev89690bf2004-03-23 06:01:52 +00001771
1772 /*
Igor Sysoevf7abd722004-09-23 06:32:00 +00001773 * if a client request body is discarded then we already set
Igor Sysoev89690bf2004-03-23 06:01:52 +00001774 * some HTTP response code for client and we can ignore the error
1775 */
1776
1777 return NGX_OK;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001778 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001779
Igor Sysoevdc479b42003-03-20 16:09:44 +00001780 if (n == NGX_AGAIN) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001781 return NGX_AGAIN;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001782 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001783
Igor Sysoeva09f08d2003-04-25 14:43:13 +00001784 r->headers_in.content_length_n -= n;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001785
Igor Sysoev42feecb2002-12-15 06:25:09 +00001786 return NGX_OK;
1787}
1788
1789
Igor Sysoevc1571722005-03-19 12:38:37 +00001790static void
1791ngx_http_set_keepalive(ngx_http_request_t *r)
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001792{
Igor Sysoev924bd792004-10-11 15:07:03 +00001793 int tcp_nodelay;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001794 ngx_int_t i;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001795 ngx_buf_t *b, *f;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001796 ngx_event_t *rev, *wev;
1797 ngx_connection_t *c;
Igor Sysoevdd888c42004-09-21 05:38:28 +00001798 ngx_http_connection_t *hc;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001799 ngx_http_core_srv_conf_t *cscf;
1800 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001801
Igor Sysoev6253ca12003-05-27 12:18:54 +00001802 c = r->connection;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001803 rev = c->read;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001804
Igor Sysoeve04084c2004-01-26 08:52:49 +00001805 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001806
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001807 c->log->action = "closing request";
Igor Sysoevdd888c42004-09-21 05:38:28 +00001808
1809 hc = r->http_connection;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001810 b = r->header_in;
1811
Igor Sysoev236e0452004-09-23 16:39:34 +00001812 if (b->pos < b->last) {
Igor Sysoevf7abd722004-09-23 06:32:00 +00001813
Igor Sysoev236e0452004-09-23 16:39:34 +00001814 /* the pipelined request */
Igor Sysoevf7abd722004-09-23 06:32:00 +00001815
1816 if (b != c->buffer) {
1817
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001818 /*
1819 * If the large header buffers were allocated while the previous
1820 * request processing then we do not use c->buffer for
1821 * the pipelined request (see ngx_http_init_request()).
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001822 *
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001823 * Now we would move the large header buffers to the free list.
1824 */
Igor Sysoevf7abd722004-09-23 06:32:00 +00001825
1826 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1827
1828 if (hc->free == NULL) {
1829 hc->free = ngx_palloc(c->pool,
1830 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev236e0452004-09-23 16:39:34 +00001831
Igor Sysoevf7abd722004-09-23 06:32:00 +00001832 if (hc->free == NULL) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001833 ngx_http_close_request(r, 0);
Igor Sysoevf7abd722004-09-23 06:32:00 +00001834 return;
1835 }
1836 }
1837
1838 for (i = 0; i < hc->nbusy - 1; i++) {
1839 f = hc->busy[i];
1840 hc->free[hc->nfree++] = f;
1841 f->pos = f->start;
1842 f->last = f->start;
1843 }
1844
1845 hc->busy[0] = b;
1846 hc->nbusy = 1;
1847 }
1848 }
1849
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001850 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1851
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001852 ngx_http_request_done(r, 0);
1853
Igor Sysoevdd888c42004-09-21 05:38:28 +00001854 c->data = hc;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001855
Igor Sysoevfa73aac2003-05-21 13:28:21 +00001856 ngx_add_timer(rev, clcf->keepalive_timeout);
1857
Igor Sysoev899b44e2005-05-12 14:58:06 +00001858 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001859 ngx_http_close_connection(c);
1860 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00001861 }
1862
Igor Sysoev7b6062a2004-02-12 20:57:10 +00001863 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001864 wev->handler = ngx_http_empty_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001865
Igor Sysoev369145c2004-05-28 15:49:23 +00001866 if (b->pos < b->last) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001867
Igor Sysoeve04084c2004-01-26 08:52:49 +00001868 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
Igor Sysoev6253ca12003-05-27 12:18:54 +00001869
Igor Sysoev055951d2005-10-21 19:12:18 +00001870#if (NGX_STAT_STUB)
1871 ngx_atomic_fetch_add(ngx_stat_reading, 1);
1872#endif
1873
Igor Sysoevdd888c42004-09-21 05:38:28 +00001874 hc->pipeline = 1;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001875 c->log->action = "reading client pipelined request line";
Igor Sysoev055951d2005-10-21 19:12:18 +00001876
Igor Sysoevd581fd52003-05-13 16:02:32 +00001877 ngx_http_init_request(rev);
1878 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001879 }
1880
Igor Sysoevdd888c42004-09-21 05:38:28 +00001881 hc->pipeline = 0;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001882
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001883 /*
1884 * To keep a memory footprint as small as possible for an idle
1885 * keepalive connection we try to free the ngx_http_request_t and
1886 * c->buffer's memory if they were allocated outside the c->pool.
1887 * The large header buffers are always allocated outside the c->pool and
1888 * are freed too.
1889 */
1890
Igor Sysoev236e0452004-09-23 16:39:34 +00001891 if (ngx_pfree(c->pool, r) == NGX_OK) {
1892 hc->request = NULL;
1893 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00001894
Igor Sysoev236e0452004-09-23 16:39:34 +00001895 b = c->buffer;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001896
Igor Sysoev236e0452004-09-23 16:39:34 +00001897 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001898
1899 /*
1900 * the special note for ngx_http_keepalive_handler() that
1901 * c->buffer's memory was freed
1902 */
1903
Igor Sysoev236e0452004-09-23 16:39:34 +00001904 b->pos = NULL;
1905
1906 } else {
1907 b->pos = b->start;
1908 b->last = b->start;
1909 }
1910
Igor Sysoev1b735832004-11-11 14:07:14 +00001911 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00001912 hc->free, hc->nfree);
1913
1914 if (hc->free) {
1915 for (i = 0; i < hc->nfree; i++) {
1916 ngx_pfree(c->pool, hc->free[i]);
1917 hc->free[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001918 }
1919
Igor Sysoev236e0452004-09-23 16:39:34 +00001920 hc->nfree = 0;
1921 }
1922
Igor Sysoev1b735832004-11-11 14:07:14 +00001923 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00001924 hc->busy, hc->nbusy);
1925
1926 if (hc->busy) {
1927 for (i = 0; i < hc->nbusy; i++) {
1928 ngx_pfree(c->pool, hc->busy[i]);
1929 hc->busy[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001930 }
1931
Igor Sysoev236e0452004-09-23 16:39:34 +00001932 hc->nbusy = 0;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001933 }
1934
Igor Sysoev899b44e2005-05-12 14:58:06 +00001935 rev->handler = ngx_http_keepalive_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001936
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001937 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
1938 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
1939 ngx_http_close_connection(c);
1940 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001941 }
1942 }
1943
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001944 c->log->action = "keepalive";
Igor Sysoev6a644c62003-03-04 06:33:48 +00001945
Igor Sysoev67f450d2004-06-01 06:04:46 +00001946 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
Igor Sysoevc1571722005-03-19 12:38:37 +00001947 if (ngx_tcp_push(c->fd) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00001948 ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
1949 ngx_http_close_connection(c);
1950 return;
Igor Sysoev9cf78302003-06-04 17:28:33 +00001951 }
Igor Sysoev924bd792004-10-11 15:07:03 +00001952
Igor Sysoev67f450d2004-06-01 06:04:46 +00001953 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
Igor Sysoev42b12b32004-12-02 18:40:46 +00001954 tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
Igor Sysoev924bd792004-10-11 15:07:03 +00001955
1956 } else {
Igor Sysoev42b12b32004-12-02 18:40:46 +00001957 tcp_nodelay = 1;
1958 }
Igor Sysoev924bd792004-10-11 15:07:03 +00001959
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001960 if (tcp_nodelay
1961 && clcf->tcp_nodelay
1962 && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
1963 {
Igor Sysoev42b12b32004-12-02 18:40:46 +00001964 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
Igor Sysoev924bd792004-10-11 15:07:03 +00001965
Igor Sysoev42b12b32004-12-02 18:40:46 +00001966 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
1967 (const void *) &tcp_nodelay, sizeof(int)) == -1)
1968 {
1969 ngx_connection_error(c, ngx_socket_errno,
1970 "setsockopt(TCP_NODELAY) failed");
1971 ngx_http_close_connection(c);
1972 return;
Igor Sysoev924bd792004-10-11 15:07:03 +00001973 }
Igor Sysoev42b12b32004-12-02 18:40:46 +00001974
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001975 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
Igor Sysoev9cf78302003-06-04 17:28:33 +00001976 }
1977
Igor Sysoevf7abd722004-09-23 06:32:00 +00001978#if 0
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001979 /* if ngx_http_request_t was freed then we need some other place */
Igor Sysoevc83f6832004-06-24 07:53:37 +00001980 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001981#endif
Igor Sysoevc83f6832004-06-24 07:53:37 +00001982
Igor Sysoevb5faed22003-10-29 08:30:44 +00001983 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001984 ngx_http_keepalive_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00001985 }
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001986}
1987
1988
Igor Sysoevc1571722005-03-19 12:38:37 +00001989static void
1990ngx_http_keepalive_handler(ngx_event_t *rev)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001991{
Igor Sysoevc1571722005-03-19 12:38:37 +00001992 size_t size;
1993 ssize_t n;
1994 ngx_buf_t *b;
1995 ngx_connection_t *c;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001996
Igor Sysoev0ad25372004-07-16 06:33:35 +00001997 c = rev->data;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001998
Igor Sysoeve04084c2004-01-26 08:52:49 +00001999 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
Igor Sysoev1af7c822002-09-13 14:47:42 +00002000
Igor Sysoevdc479b42003-03-20 16:09:44 +00002001 if (rev->timedout) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002002 ngx_http_close_connection(c);
2003 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00002004 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002005
Igor Sysoevf6906042004-11-25 16:17:31 +00002006#if (NGX_HAVE_KQUEUE)
Igor Sysoev236e0452004-09-23 16:39:34 +00002007
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002008 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoevcdc46302005-12-07 14:51:31 +00002009 if (rev->pending_eof) {
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002010 c->log->handler = NULL;
Igor Sysoev236e0452004-09-23 16:39:34 +00002011 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
Igor Sysoev1b735832004-11-11 14:07:14 +00002012 "kevent() reported that client %V closed "
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002013 "keepalive connection", &c->addr_text);
Igor Sysoev42b12b32004-12-02 18:40:46 +00002014#if (NGX_HTTP_SSL)
2015 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00002016 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00002017 }
2018#endif
Igor Sysoev236e0452004-09-23 16:39:34 +00002019 ngx_http_close_connection(c);
2020 return;
2021 }
2022 }
2023
2024#endif
2025
Igor Sysoev236e0452004-09-23 16:39:34 +00002026 b = c->buffer;
2027 size = b->end - b->start;
2028
2029 if (b->pos == NULL) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002030
2031 /*
2032 * The c->buffer's memory was freed by ngx_http_set_keepalive().
2033 * However, the c->buffer->start and c->buffer->end were not changed
2034 * to keep the buffer size.
2035 */
2036
Igor Sysoevc1571722005-03-19 12:38:37 +00002037 b->pos = ngx_palloc(c->pool, size);
2038 if (b->pos == NULL) {
Igor Sysoev236e0452004-09-23 16:39:34 +00002039 ngx_http_close_connection(c);
2040 return;
2041 }
2042
2043 b->start = b->pos;
2044 b->last = b->pos;
2045 b->end = b->pos + size;
2046 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00002047
Igor Sysoev0a280a32003-10-12 16:49:16 +00002048 /*
2049 * MSIE closes a keepalive connection with RST flag
2050 * so we ignore ECONNRESET here.
2051 */
Igor Sysoevb7387572003-03-11 20:38:13 +00002052
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002053 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
Igor Sysoevb7387572003-03-11 20:38:13 +00002054 ngx_set_socket_errno(0);
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00002055
Igor Sysoev236e0452004-09-23 16:39:34 +00002056 n = c->recv(c, b->last, size);
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002057 c->log_error = NGX_ERROR_INFO;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002058
Igor Sysoevd581fd52003-05-13 16:02:32 +00002059 if (n == NGX_AGAIN) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002060 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002061 ngx_http_close_connection(c);
2062 }
2063
Igor Sysoevd581fd52003-05-13 16:02:32 +00002064 return;
2065 }
2066
2067 if (n == NGX_ERROR) {
2068 ngx_http_close_connection(c);
2069 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00002070 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002071
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002072 c->log->handler = NULL;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002073
2074 if (n == 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +00002075 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002076 "client %V closed keepalive connection", &c->addr_text);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002077 ngx_http_close_connection(c);
2078 return;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002079 }
2080
Igor Sysoevf7abd722004-09-23 06:32:00 +00002081 b->last += n;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002082
Igor Sysoev055951d2005-10-21 19:12:18 +00002083#if (NGX_STAT_STUB)
2084 ngx_atomic_fetch_add(ngx_stat_reading, 1);
2085#endif
2086
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002087 c->log->handler = ngx_http_log_error;
2088 c->log->action = "reading client request line";
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002089
Igor Sysoevd581fd52003-05-13 16:02:32 +00002090 ngx_http_init_request(rev);
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002091}
2092
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002093
Igor Sysoevc1571722005-03-19 12:38:37 +00002094static void
2095ngx_http_set_lingering_close(ngx_http_request_t *r)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002096{
Igor Sysoev0a280a32003-10-12 16:49:16 +00002097 ngx_event_t *rev, *wev;
Igor Sysoevb7387572003-03-11 20:38:13 +00002098 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002099 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002100
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002101 c = r->connection;
Igor Sysoev9b25d692003-01-26 21:08:14 +00002102
Igor Sysoev6253ca12003-05-27 12:18:54 +00002103 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002104
Igor Sysoev0a280a32003-10-12 16:49:16 +00002105 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002106 rev->handler = ngx_http_lingering_close_handler;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002107
Igor Sysoev208eed22005-10-07 13:30:52 +00002108 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
Igor Sysoev6253ca12003-05-27 12:18:54 +00002109 ngx_add_timer(rev, clcf->lingering_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +00002110
Igor Sysoev899b44e2005-05-12 14:58:06 +00002111 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00002112 ngx_http_close_request(r, 0);
Igor Sysoev0a280a32003-10-12 16:49:16 +00002113 return;
2114 }
2115
2116 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002117 wev->handler = ngx_http_empty_handler;
Igor Sysoev0a280a32003-10-12 16:49:16 +00002118
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002119 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2120 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
2121 ngx_http_close_request(r, 0);
2122 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00002123 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002124 }
2125
Igor Sysoevb7387572003-03-11 20:38:13 +00002126 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00002127 ngx_connection_error(c, ngx_socket_errno,
2128 ngx_shutdown_socket_n " failed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002129 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002130 return;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002131 }
2132
Igor Sysoevb5faed22003-10-29 08:30:44 +00002133 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002134 ngx_http_lingering_close_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00002135 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002136}
2137
2138
Igor Sysoevc1571722005-03-19 12:38:37 +00002139static void
2140ngx_http_lingering_close_handler(ngx_event_t *rev)
Igor Sysoev42feecb2002-12-15 06:25:09 +00002141{
Igor Sysoevdc479b42003-03-20 16:09:44 +00002142 ssize_t n;
2143 ngx_msec_t timer;
2144 ngx_connection_t *c;
2145 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002146 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002147 u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
Igor Sysoev1af7c822002-09-13 14:47:42 +00002148
Igor Sysoev6253ca12003-05-27 12:18:54 +00002149 c = rev->data;
2150 r = c->data;
Igor Sysoev86de4cb2003-01-30 07:28:09 +00002151
Igor Sysoeve04084c2004-01-26 08:52:49 +00002152 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2153 "http lingering close handler");
Igor Sysoevdc479b42003-03-20 16:09:44 +00002154
2155 if (rev->timedout) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002156 c->timedout = 1;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002157 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002158 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002159 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002160
Igor Sysoevc0247302004-06-27 18:01:57 +00002161 timer = r->lingering_time - ngx_time();
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002162 if (timer <= 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002163 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002164 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002165 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002166
Igor Sysoevdc479b42003-03-20 16:09:44 +00002167 do {
Igor Sysoevf7abd722004-09-23 06:32:00 +00002168 n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002169
Igor Sysoeve04084c2004-01-26 08:52:49 +00002170 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002171
Igor Sysoevdc479b42003-03-20 16:09:44 +00002172 if (n == NGX_ERROR || n == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002173 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002174 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002175 }
2176
2177 } while (rev->ready);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002178
Igor Sysoev899b44e2005-05-12 14:58:06 +00002179 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00002180 ngx_http_close_request(r, 0);
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002181 return;
2182 }
2183
Igor Sysoevf7abd722004-09-23 06:32:00 +00002184 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2185
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002186 timer *= 1000;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002187
Igor Sysoev6253ca12003-05-27 12:18:54 +00002188 if (timer > clcf->lingering_timeout) {
2189 timer = clcf->lingering_timeout;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002190 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002191
Igor Sysoevdc479b42003-03-20 16:09:44 +00002192 ngx_add_timer(rev, timer);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002193}
2194
Igor Sysoev2b542382002-08-20 14:48:28 +00002195
Igor Sysoevc1571722005-03-19 12:38:37 +00002196void
2197ngx_http_empty_handler(ngx_event_t *wev)
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002198{
Igor Sysoeve04084c2004-01-26 08:52:49 +00002199 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002200
2201 return;
2202}
2203
2204
Igor Sysoev899b44e2005-05-12 14:58:06 +00002205void
2206ngx_http_request_empty_handler(ngx_http_request_t *r)
2207{
2208 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002209 "http request empty handler");
Igor Sysoev899b44e2005-05-12 14:58:06 +00002210
2211 return;
2212}
2213
2214
Igor Sysoevc1571722005-03-19 12:38:37 +00002215ngx_int_t
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002216ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002217{
Igor Sysoev369145c2004-05-28 15:49:23 +00002218 ngx_buf_t *b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002219 ngx_chain_t out;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002220
Igor Sysoevc1571722005-03-19 12:38:37 +00002221 b = ngx_calloc_buf(r->pool);
2222 if (b == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +00002223 return NGX_ERROR;
2224 }
2225
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002226 if (flags & NGX_HTTP_LAST) {
2227 b->last_buf = 1;
2228 }
2229
2230 if (flags & NGX_HTTP_FLUSH) {
2231 b->flush = 1;
2232 }
2233
Igor Sysoev369145c2004-05-28 15:49:23 +00002234 out.buf = b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002235 out.next = NULL;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002236
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002237 return ngx_http_output_filter(r, &out);
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002238}
2239
2240
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002241static ngx_int_t
2242ngx_http_post_action(ngx_http_request_t *r)
2243{
2244 ngx_http_core_loc_conf_t *clcf;
2245
2246 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2247
2248 if (clcf->post_action.data == NULL) {
2249 return NGX_DECLINED;
2250 }
2251
Igor Sysoev8fea8852006-03-15 09:53:04 +00002252 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2253 "post action: \"%V\"", &clcf->post_action);
2254
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002255 r->http_version = NGX_HTTP_VERSION_9;
2256 r->header_only = 1;
2257
2258 ngx_http_internal_redirect(r, &clcf->post_action, NULL);
2259
2260 return NGX_OK;
2261}
2262
2263
2264static void
Igor Sysoev899b44e2005-05-12 14:58:06 +00002265ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error)
Igor Sysoevd581fd52003-05-13 16:02:32 +00002266{
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002267 ngx_connection_t *c;
2268 ngx_http_cleanup_t *cln;
2269
2270 c = r->connection;
2271 r = r->main;
2272
2273 for (cln = r->cleanup; cln; cln = cln->next) {
2274 if (cln->handler) {
2275 cln->handler(cln->data);
2276 }
2277 }
2278
2279 ngx_http_request_done(r, error);
2280 ngx_http_close_connection(c);
2281}
2282
2283
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002284static void
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002285ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error)
2286{
2287 ngx_log_t *log;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002288 ngx_uint_t i, n;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002289 struct linger linger;
2290 ngx_http_log_ctx_t *ctx;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002291 ngx_http_handler_pt *log_handler;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002292 ngx_http_core_loc_conf_t *clcf;
2293 ngx_http_core_main_conf_t *cmcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002294
Igor Sysoev865c1502003-11-30 20:03:18 +00002295 log = r->connection->log;
2296
2297 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002298
2299 if (r->pool == NULL) {
Igor Sysoev90c08142005-07-25 09:41:38 +00002300 ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002301 return;
2302 }
2303
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002304#if (NGX_STAT_STUB)
Igor Sysoev055951d2005-10-21 19:12:18 +00002305
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002306 if (r->stat_reading) {
Igor Sysoev78452232005-10-12 13:50:36 +00002307 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002308 }
2309
2310 if (r->stat_writing) {
Igor Sysoev78452232005-10-12 13:50:36 +00002311 ngx_atomic_fetch_add(ngx_stat_writing, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002312 }
Igor Sysoev055951d2005-10-21 19:12:18 +00002313
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002314#endif
2315
Igor Sysoev669e3312003-12-22 09:40:48 +00002316 if (error && r->headers_out.status == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002317 r->headers_out.status = error;
2318 }
2319
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002320 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2321
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002322 log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
2323 n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
2324 for (i = 0; i < n; i++) {
2325 log_handler[i](r);
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002326 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00002327
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002328 if (r->connection->timedout) {
2329 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2330
2331 if (clcf->reset_timedout_connection) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002332 linger.l_onoff = 1;
2333 linger.l_linger = 0;
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002334
2335 if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
Igor Sysoev899b44e2005-05-12 14:58:06 +00002336 (const void *) &linger, sizeof(struct linger)) == -1)
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002337 {
2338 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
2339 "setsockopt(SO_LINGER) failed");
2340 }
2341 }
2342 }
2343
Igor Sysoev899b44e2005-05-12 14:58:06 +00002344 /* the various request strings were allocated from r->pool */
Igor Sysoev865c1502003-11-30 20:03:18 +00002345 ctx = log->data;
Igor Sysoev1b735832004-11-11 14:07:14 +00002346 ctx->request = NULL;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002347
Igor Sysoevc83f6832004-06-24 07:53:37 +00002348 r->request_line.len = 0;
2349
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002350 r->connection->destroyed = 1;
2351
Igor Sysoevd581fd52003-05-13 16:02:32 +00002352 ngx_destroy_pool(r->pool);
2353}
2354
2355
Igor Sysoev90c08142005-07-25 09:41:38 +00002356static void
Igor Sysoevc1571722005-03-19 12:38:37 +00002357ngx_http_close_connection(ngx_connection_t *c)
Igor Sysoev6b863e32003-05-12 15:52:24 +00002358{
Igor Sysoev02025fd2005-01-18 13:03:58 +00002359 ngx_pool_t *pool;
2360
Igor Sysoeve04084c2004-01-26 08:52:49 +00002361 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev54498db2004-02-11 17:08:49 +00002362 "close http connection: %d", c->fd);
Igor Sysoev6b863e32003-05-12 15:52:24 +00002363
Igor Sysoevceb99292005-09-06 16:09:32 +00002364#if (NGX_HTTP_SSL)
Igor Sysoev924bd792004-10-11 15:07:03 +00002365
2366 if (c->ssl) {
2367 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002368 c->ssl->handler = ngx_http_close_connection;
Igor Sysoev924bd792004-10-11 15:07:03 +00002369 return;
2370 }
2371 }
2372
2373#endif
2374
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002375#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +00002376 ngx_atomic_fetch_add(ngx_stat_active, -1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002377#endif
2378
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002379 c->destroyed = 1;
2380
Igor Sysoev02025fd2005-01-18 13:03:58 +00002381 pool = c->pool;
2382
Igor Sysoev59cf56c2004-09-07 15:29:22 +00002383 ngx_close_connection(c);
Igor Sysoev02025fd2005-01-18 13:03:58 +00002384
Igor Sysoevc1571722005-03-19 12:38:37 +00002385 ngx_destroy_pool(pool);
Igor Sysoev2ba1ee02002-10-04 17:58:04 +00002386}
2387
2388
Igor Sysoevc1571722005-03-19 12:38:37 +00002389static u_char *
2390ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002391{
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002392 u_char *p;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002393 ngx_http_request_t *r;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002394 ngx_http_log_ctx_t *ctx;
Igor Sysoev7578ec92003-06-02 15:24:30 +00002395
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002396 if (log->action) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002397 p = ngx_snprintf(buf, len, " while %s", log->action);
Igor Sysoev1b735832004-11-11 14:07:14 +00002398 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002399 buf = p;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002400 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002401
Igor Sysoev899b44e2005-05-12 14:58:06 +00002402 ctx = log->data;
2403
Igor Sysoevc04deca2005-03-28 14:43:02 +00002404 p = ngx_snprintf(buf, len, ", client: %V", ctx->client);
Igor Sysoev899b44e2005-05-12 14:58:06 +00002405 len -= p - buf;
Igor Sysoev1b735832004-11-11 14:07:14 +00002406
Igor Sysoevc04deca2005-03-28 14:43:02 +00002407 r = ctx->request;
2408
Igor Sysoev899b44e2005-05-12 14:58:06 +00002409 if (r) {
2410 return r->log_handler(r, p, len);
Igor Sysoev1b735832004-11-11 14:07:14 +00002411 }
2412
Igor Sysoev899b44e2005-05-12 14:58:06 +00002413 return p;
2414}
2415
2416
2417static u_char *
2418ngx_http_log_error_handler(ngx_http_request_t *r, u_char *buf, size_t len)
2419{
2420 u_char *p;
Igor Sysoev1b735832004-11-11 14:07:14 +00002421
Igor Sysoevc04deca2005-03-28 14:43:02 +00002422 if (r->server_name.data) {
2423 p = ngx_snprintf(buf, len, ", server: %V", &r->server_name);
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002424 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002425 buf = p;
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002426 }
2427
Igor Sysoevc04deca2005-03-28 14:43:02 +00002428 if (r->unparsed_uri.data) {
2429 p = ngx_snprintf(buf, len, ", URL: \"%V\"", &r->unparsed_uri);
2430 len -= p - buf;
2431 buf = p;
Igor Sysoev1b735832004-11-11 14:07:14 +00002432
Igor Sysoevc04deca2005-03-28 14:43:02 +00002433 } else {
2434 if (r->request_line.data == NULL && r->request_start) {
2435 for (p = r->request_start; p < r->header_in->last; p++) {
2436 if (*p == CR || *p == LF) {
2437 break;
2438 }
2439 }
2440
2441 r->request_line.len = p - r->request_start;
2442 r->request_line.data = r->request_start;
2443 }
2444
2445 if (r->request_line.len) {
2446 p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
2447 len -= p - buf;
2448 buf = p;
2449 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002450 }
2451
Igor Sysoevc04deca2005-03-28 14:43:02 +00002452 return ngx_http_log_error_info(r, buf, len);
2453}
Igor Sysoev1b735832004-11-11 14:07:14 +00002454
Igor Sysoevc04deca2005-03-28 14:43:02 +00002455
2456u_char *
2457ngx_http_log_error_info(ngx_http_request_t *r, u_char *buf, size_t len)
2458{
2459 u_char *p;
2460
2461 if (r->headers_in.host) {
2462 p = ngx_snprintf(buf, len, ", host: \"%V\"",
2463 &r->headers_in.host->value);
2464 len -= p - buf;
2465 buf = p;
2466 }
2467
2468 if (r->headers_in.referer) {
2469 p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
2470 &r->headers_in.referer->value);
2471 buf = p;
2472 }
2473
2474 return buf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00002475}