blob: 7fddde087f86add686bb5a16205eb1fa7a283f31 [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 Sysoevb1dfe472004-12-21 12:30:30 +000028static ngx_int_t 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 Sysoev90c08142005-07-25 09:41:38 +000042static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
Igor Sysoev9ac946b2005-10-24 15:09:41 +000043static void ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error);
Igor Sysoev90c08142005-07-25 09:41:38 +000044static void ngx_http_close_connection(ngx_connection_t *c);
Igor Sysoevd581fd52003-05-13 16:02:32 +000045
Igor Sysoeve5a222c2005-01-25 12:27:35 +000046static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
Igor Sysoev899b44e2005-05-12 14:58:06 +000047static u_char *ngx_http_log_error_handler(ngx_http_request_t *r, u_char *buf,
48 size_t len);
Igor Sysoev0ad17c02002-08-26 15:18:19 +000049
Igor Sysoevceb99292005-09-06 16:09:32 +000050#if (NGX_HTTP_SSL)
51static void ngx_http_ssl_handshake(ngx_event_t *rev);
Igor Sysoev9fa5a822005-09-30 14:41:25 +000052static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
Igor Sysoevceb99292005-09-06 16:09:32 +000053#endif
54
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000055
Igor Sysoevc04deca2005-03-28 14:43:02 +000056static char *ngx_http_client_errors[] = {
Igor Sysoev0ad17c02002-08-26 15:18:19 +000057
Igor Sysoevc04deca2005-03-28 14:43:02 +000058 /* NGX_HTTP_PARSE_INVALID_METHOD */
59 "client sent invalid method",
Igor Sysoev6a644c62003-03-04 06:33:48 +000060
Igor Sysoevc04deca2005-03-28 14:43:02 +000061 /* NGX_HTTP_PARSE_INVALID_REQUEST */
62 "client sent invalid request",
63
64 /* NGX_HTTP_PARSE_INVALID_09_METHOD */
65 "client sent invalid method in HTTP/0.9 request"
Igor Sysoev016b8522002-08-29 16:59:54 +000066};
67
68
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000069ngx_http_header_t ngx_http_headers_in[] = {
Igor Sysoev899b44e2005-05-12 14:58:06 +000070 { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
Igor Sysoevb145b062005-06-15 18:33:41 +000071 ngx_http_process_unique_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000072
Igor Sysoev899b44e2005-05-12 14:58:06 +000073 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
Igor Sysoevb145b062005-06-15 18:33:41 +000074 ngx_http_process_unique_header_line },
Igor Sysoev899b44e2005-05-12 14:58:06 +000075
76 { ngx_string("If-Modified-Since"),
77 offsetof(ngx_http_headers_in_t, if_modified_since),
78 ngx_http_process_header_line },
79
80 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
81 ngx_http_process_header_line },
82
83 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
84 ngx_http_process_header_line },
85
86 { ngx_string("Content-Length"),
87 offsetof(ngx_http_headers_in_t, content_length),
Igor Sysoevb145b062005-06-15 18:33:41 +000088 ngx_http_process_unique_header_line },
Igor Sysoev899b44e2005-05-12 14:58:06 +000089
90 { ngx_string("Content-Type"),
91 offsetof(ngx_http_headers_in_t, content_type),
92 ngx_http_process_header_line },
93
94 { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
95 ngx_http_process_header_line },
96
Igor Sysoevc31a9bb2005-11-26 10:11:11 +000097 { ngx_string("Transfer-Encoding"),
98 offsetof(ngx_http_headers_in_t, transfer_encoding),
99 ngx_http_process_header_line },
100
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000101#if (NGX_HTTP_GZIP)
102 { ngx_string("Accept-Encoding"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000103 offsetof(ngx_http_headers_in_t, accept_encoding),
104 ngx_http_process_header_line },
105
106 { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
107 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000108#endif
109
110 { ngx_string("Authorization"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000111 offsetof(ngx_http_headers_in_t, authorization),
Igor Sysoevb145b062005-06-15 18:33:41 +0000112 ngx_http_process_unique_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000113
Igor Sysoev899b44e2005-05-12 14:58:06 +0000114 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
115 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000116
Igor Sysoev09c684b2005-11-09 17:25:55 +0000117#if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000118 { ngx_string("X-Forwarded-For"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000119 offsetof(ngx_http_headers_in_t, x_forwarded_for),
120 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000121#endif
Igor Sysoev02025fd2005-01-18 13:03:58 +0000122
Igor Sysoev09c684b2005-11-09 17:25:55 +0000123#if (NGX_HTTP_REALIP)
124 { ngx_string("X-Real-IP"),
125 offsetof(ngx_http_headers_in_t, x_real_ip),
126 ngx_http_process_header_line },
127#endif
128
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000129#if (NGX_HTTP_HEADERS)
Igor Sysoev899b44e2005-05-12 14:58:06 +0000130 { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
131 ngx_http_process_header_line },
132
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000133 { ngx_string("Accept-Language"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000134 offsetof(ngx_http_headers_in_t, accept_language),
135 ngx_http_process_header_line },
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000136#endif
137
Igor Sysoev899b44e2005-05-12 14:58:06 +0000138 { ngx_string("Cookie"), 0, ngx_http_process_cookie },
139
140 { ngx_null_string, 0, NULL }
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000141};
142
143
Igor Sysoevc1571722005-03-19 12:38:37 +0000144void
145ngx_http_init_connection(ngx_connection_t *c)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000146{
Igor Sysoev6253ca12003-05-27 12:18:54 +0000147 ngx_event_t *rev;
Igor Sysoev160d7742003-11-19 16:26:41 +0000148 ngx_http_log_ctx_t *ctx;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000149
Igor Sysoevc1571722005-03-19 12:38:37 +0000150 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
151 if (ctx == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000152 ngx_http_close_connection(c);
153 return;
154 }
155
Igor Sysoev1b735832004-11-11 14:07:14 +0000156 ctx->client = &c->addr_text;
Igor Sysoev1b735832004-11-11 14:07:14 +0000157 ctx->request = NULL;
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000158
159 c->log->connection = c->number;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000160 c->log->handler = ngx_http_log_error;
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000161 c->log->data = ctx;
162 c->log->action = "reading client request line";
163
Igor Sysoevc7a2f682004-02-10 16:23:38 +0000164 c->log_error = NGX_ERROR_INFO;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000165
Igor Sysoevdc479b42003-03-20 16:09:44 +0000166 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000167 rev->handler = ngx_http_init_request;
Igor Sysoev9ac946b2005-10-24 15:09:41 +0000168 c->write->handler = ngx_http_empty_handler;
Igor Sysoev7af6b162004-02-09 07:46:43 +0000169
Igor Sysoev055951d2005-10-21 19:12:18 +0000170#if (NGX_STAT_STUB)
171 ngx_atomic_fetch_add(ngx_stat_reading, 1);
172#endif
173
Igor Sysoevdc479b42003-03-20 16:09:44 +0000174 if (rev->ready) {
Igor Sysoev0ab91b92004-06-06 19:49:18 +0000175 /* the deferred accept(), rtsig, aio, iocp */
Igor Sysoev709405b2004-03-31 15:26:46 +0000176
Igor Sysoev67f450d2004-06-01 06:04:46 +0000177 if (ngx_accept_mutex) {
Igor Sysoevc2068d02005-10-19 12:33:58 +0000178 ngx_post_event(rev, &ngx_posted_events);
Igor Sysoev709405b2004-03-31 15:26:46 +0000179 return;
180 }
181
Igor Sysoev6b863e32003-05-12 15:52:24 +0000182 ngx_http_init_request(rev);
183 return;
Igor Sysoev016b8522002-08-29 16:59:54 +0000184 }
Igor Sysoev73009772003-02-06 17:21:13 +0000185
Igor Sysoev239baac2003-06-11 15:28:34 +0000186 ngx_add_timer(rev, c->listening->post_accept_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000187
Igor Sysoevb5faed22003-10-29 08:30:44 +0000188 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev055951d2005-10-21 19:12:18 +0000189#if (NGX_STAT_STUB)
190 ngx_atomic_fetch_add(ngx_stat_reading, -1);
191#endif
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000192 ngx_http_close_connection(c);
193 return;
194 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000195}
196
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000197
Igor Sysoevc1571722005-03-19 12:38:37 +0000198static
199void ngx_http_init_request(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000200{
Igor Sysoev09c684b2005-11-09 17:25:55 +0000201 ngx_uint_t i;
202 socklen_t len;
203 struct sockaddr_in sin;
204 ngx_connection_t *c;
205 ngx_http_request_t *r;
Igor Sysoev305a9d82005-12-26 17:07:48 +0000206 ngx_http_in_port_t *hip;
207 ngx_http_in_addr_t *hia;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000208 ngx_http_log_ctx_t *ctx;
209 ngx_http_connection_t *hc;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000210 ngx_http_core_srv_conf_t *cscf;
211 ngx_http_core_loc_conf_t *clcf;
212 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000213#if (NGX_HTTP_SSL)
Igor Sysoev09c684b2005-11-09 17:25:55 +0000214 ngx_http_ssl_srv_conf_t *sscf;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000215#endif
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000216
Igor Sysoev055951d2005-10-21 19:12:18 +0000217#if (NGX_STAT_STUB)
218 ngx_atomic_fetch_add(ngx_stat_reading, -1);
219#endif
220
Igor Sysoeva9830112003-05-19 16:39:14 +0000221 c = rev->data;
Igor Sysoeva9830112003-05-19 16:39:14 +0000222
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000223 if (rev->timedout) {
224 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000225
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000226 ngx_http_close_connection(c);
227 return;
228 }
229
Igor Sysoevf7abd722004-09-23 06:32:00 +0000230 hc = c->data;
Igor Sysoevdd888c42004-09-21 05:38:28 +0000231
Igor Sysoev055951d2005-10-21 19:12:18 +0000232 if (hc == NULL) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000233 hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
234 if (hc == NULL) {
Igor Sysoevdd888c42004-09-21 05:38:28 +0000235 ngx_http_close_connection(c);
236 return;
237 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000238 }
Igor Sysoevdd888c42004-09-21 05:38:28 +0000239
Igor Sysoevf7abd722004-09-23 06:32:00 +0000240 r = hc->request;
241
242 if (r) {
243 ngx_memzero(r, sizeof(ngx_http_request_t));
244
245 r->pipeline = hc->pipeline;
246
247 if (hc->nbusy) {
248 r->header_in = hc->busy[0];
249 }
250
Igor Sysoevf7abd722004-09-23 06:32:00 +0000251 } else {
Igor Sysoevc1571722005-03-19 12:38:37 +0000252 r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
253 if (r == NULL) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000254 ngx_http_close_connection(c);
255 return;
256 }
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000257
Igor Sysoevdd888c42004-09-21 05:38:28 +0000258 hc->request = r;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000259 }
260
Igor Sysoevdd888c42004-09-21 05:38:28 +0000261 c->data = r;
262 r->http_connection = hc;
263
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000264 c->sent = 0;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000265 r->signature = NGX_HTTP_MODULE;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000266
Igor Sysoev6253ca12003-05-27 12:18:54 +0000267 /* find the server configuration for the address:port */
268
269 /* AF_INET only */
270
Igor Sysoev305a9d82005-12-26 17:07:48 +0000271 hip = c->servers;
272 hia = hip->addrs;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000273
Igor Sysoev305a9d82005-12-26 17:07:48 +0000274 r->port = hip->port;
275 r->port_text = &hip->port_text;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000276
277 i = 0;
278
Igor Sysoev305a9d82005-12-26 17:07:48 +0000279 if (hip->naddrs > 1) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000280
Igor Sysoev239baac2003-06-11 15:28:34 +0000281 /*
Igor Sysoevd00b3652004-08-23 19:09:29 +0000282 * There are several addresses on this port and one of them
283 * is the "*:port" wildcard so getsockname() is needed to determine
Igor Sysoev239baac2003-06-11 15:28:34 +0000284 * the server address.
Igor Sysoevd00b3652004-08-23 19:09:29 +0000285 *
Igor Sysoev239baac2003-06-11 15:28:34 +0000286 * AcceptEx() already gave this address.
287 */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000288
Igor Sysoev1b735832004-11-11 14:07:14 +0000289#if (NGX_WIN32)
Igor Sysoev239baac2003-06-11 15:28:34 +0000290 if (c->local_sockaddr) {
291 r->in_addr =
292 ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000293
Igor Sysoev02025fd2005-01-18 13:03:58 +0000294 } else
Igor Sysoev239baac2003-06-11 15:28:34 +0000295#endif
Igor Sysoev02025fd2005-01-18 13:03:58 +0000296 {
Igor Sysoev239baac2003-06-11 15:28:34 +0000297 len = sizeof(struct sockaddr_in);
Igor Sysoev02025fd2005-01-18 13:03:58 +0000298 if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000299 ngx_connection_error(c, ngx_socket_errno,
300 "getsockname() failed");
Igor Sysoev239baac2003-06-11 15:28:34 +0000301 ngx_http_close_connection(c);
302 return;
303 }
Igor Sysoev10a543a2004-03-16 07:10:12 +0000304
Igor Sysoev02025fd2005-01-18 13:03:58 +0000305 r->in_addr = sin.sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000306 }
307
Igor Sysoev6253ca12003-05-27 12:18:54 +0000308 /* the last in_port->addrs address is "*" */
309
Igor Sysoev305a9d82005-12-26 17:07:48 +0000310 for ( /* void */ ; i < hip->naddrs - 1; i++) {
311 if (hia[i].addr == r->in_addr) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000312 break;
313 }
314 }
315
316 } else {
Igor Sysoev305a9d82005-12-26 17:07:48 +0000317 r->in_addr = hia[0].addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000318 }
319
Igor Sysoev305a9d82005-12-26 17:07:48 +0000320 r->virtual_names = hia[i].virtual_names;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000321
322 /* the default server configuration for the address:port */
Igor Sysoev305a9d82005-12-26 17:07:48 +0000323 cscf = hia[i].core_srv_conf;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000324
325 r->main_conf = cscf->ctx->main_conf;
326 r->srv_conf = cscf->ctx->srv_conf;
327 r->loc_conf = cscf->ctx->loc_conf;
328
Igor Sysoev305a9d82005-12-26 17:07:48 +0000329 r->server_name = cscf->server_name;
330
Igor Sysoev899b44e2005-05-12 14:58:06 +0000331 rev->handler = ngx_http_process_request_line;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000332
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000333#if (NGX_HTTP_SSL)
334
Igor Sysoevf38e0462004-07-16 17:11:43 +0000335 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000336 if (sscf->enable) {
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000337
338 if (c->ssl == NULL) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000339 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
Igor Sysoev02f742b2005-04-08 15:18:55 +0000340 == NGX_ERROR)
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000341 {
342 ngx_http_close_connection(c);
343 return;
344 }
345
Igor Sysoev899b44e2005-05-12 14:58:06 +0000346 rev->handler = ngx_http_ssl_handshake;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000347 }
348
Igor Sysoevd52477f2005-05-16 13:53:20 +0000349 r->main_filter_need_in_memory = 1;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000350 }
351
Igor Sysoev4aa88882004-07-14 20:07:58 +0000352#endif
353
Igor Sysoev890fc962003-07-20 21:15:59 +0000354 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
355 c->log->file = clcf->err_log->file;
Igor Sysoevfff32322004-04-08 15:58:25 +0000356 if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
357 c->log->log_level = clcf->err_log->log_level;
358 }
Igor Sysoev890fc962003-07-20 21:15:59 +0000359
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000360 if (c->buffer == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +0000361 c->buffer = ngx_create_temp_buf(c->pool,
362 cscf->client_header_buffer_size);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000363 if (c->buffer == NULL) {
364 ngx_http_close_connection(c);
365 return;
366 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000367 }
368
Igor Sysoevf7abd722004-09-23 06:32:00 +0000369 if (r->header_in == NULL) {
370 r->header_in = c->buffer;
371 }
372
Igor Sysoevc1571722005-03-19 12:38:37 +0000373 r->pool = ngx_create_pool(cscf->request_pool_size, c->log);
374 if (r->pool == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000375 ngx_http_close_connection(c);
376 return;
377 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000378
Igor Sysoev89690bf2004-03-23 06:01:52 +0000379
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000380 if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000381 sizeof(ngx_table_elt_t))
382 == NGX_ERROR)
Igor Sysoev980a9242004-09-05 19:54:02 +0000383 {
384 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev980a9242004-09-05 19:54:02 +0000385 return;
386 }
387
Igor Sysoev6b863e32003-05-12 15:52:24 +0000388 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
389 if (r->ctx == NULL) {
390 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000391 return;
392 }
Igor Sysoeve0268b92002-09-11 15:18:33 +0000393
Igor Sysoev09c684b2005-11-09 17:25:55 +0000394 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
395
396 r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
397 * sizeof(ngx_http_variable_value_t));
398 if (r->variables == NULL) {
399 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
400 return;
401 }
402
Igor Sysoevc78c41c2004-07-07 06:15:04 +0000403 c->single_connection = 1;
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000404 c->destroyed = 0;
405
Igor Sysoev6b863e32003-05-12 15:52:24 +0000406 r->connection = c;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000407
Igor Sysoevf6e1fe32005-10-04 10:38:53 +0000408 r->main = r;
409
Igor Sysoev11d75322005-03-01 15:20:36 +0000410 r->start_time = ngx_time();
411
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000412 r->headers_in.content_length_n = -1;
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000413 r->headers_in.keep_alive_n = -1;
414 r->headers_out.content_length_n = -1;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000415 r->headers_out.last_modified_time = -1;
416
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000417 r->http_state = NGX_HTTP_READING_REQUEST_STATE;
418
Igor Sysoevc04deca2005-03-28 14:43:02 +0000419 ctx = c->log->data;
420 ctx->request = r;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000421 r->log_handler = ngx_http_log_error_handler;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000422
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000423#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000424 ngx_atomic_fetch_add(ngx_stat_reading, 1);
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000425 r->stat_reading = 1;
Igor Sysoev78452232005-10-12 13:50:36 +0000426 ngx_atomic_fetch_add(ngx_stat_requests, 1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000427#endif
428
Igor Sysoev899b44e2005-05-12 14:58:06 +0000429 rev->handler(rev);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000430}
431
432
433#if (NGX_HTTP_SSL)
434
Igor Sysoevc1571722005-03-19 12:38:37 +0000435static void
436ngx_http_ssl_handshake(ngx_event_t *rev)
Igor Sysoevf38e0462004-07-16 17:11:43 +0000437{
Igor Sysoevf38e0462004-07-16 17:11:43 +0000438 u_char buf[1];
Igor Sysoev1b735832004-11-11 14:07:14 +0000439 ssize_t n;
440 ngx_int_t rc;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000441 ngx_connection_t *c;
442 ngx_http_request_t *r;
443
444 c = rev->data;
445 r = c->data;
446
447 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
448 "http check ssl handshake");
449
450 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000451 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
452 c->timedout = 1;
453 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000454 return;
455 }
456
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000457 n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000458
459 if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
460 return;
461 }
462
463 if (n == 1) {
464 if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
465 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000466 "https ssl handshake: 0x%02Xd", buf[0]);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000467
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000468 rc = ngx_ssl_handshake(c);
469
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000470 if (rc == NGX_AGAIN) {
471 c->ssl->handler = ngx_http_ssl_handshake_handler;
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000472 return;
473 }
474
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000475 ngx_http_ssl_handshake_handler(c);
476
477 return;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000478
479 } else {
480 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
481 "plain http");
482
483 r->plain_http = 1;
484 }
485 }
486
Igor Sysoev899b44e2005-05-12 14:58:06 +0000487 rev->handler = ngx_http_process_request_line;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000488 ngx_http_process_request_line(rev);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000489}
490
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000491
492static void
493ngx_http_ssl_handshake_handler(ngx_connection_t *c)
494{
495 ngx_http_request_t *r;
496
497 if (c->ssl->handshaked) {
498
499 /*
500 * The majority of browsers do not send the "close notify" alert.
501 * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
502 * and Links. And what is more, MSIE ignores the server's alert.
503 *
504 * Opera and recent Mozilla send the alert.
505 */
506
507 c->ssl->no_wait_shutdown = 1;
508
509 c->read->handler = ngx_http_process_request_line;
510 /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
511
512 ngx_http_process_request_line(c->read);
513
514 return;
515 }
516
517 r = c->data;
518
519 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000520
521 return;
522}
523
524
Igor Sysoevf38e0462004-07-16 17:11:43 +0000525#endif
526
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000527
Igor Sysoevc1571722005-03-19 12:38:37 +0000528static void
529ngx_http_process_request_line(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000530{
Igor Sysoevf7abd722004-09-23 06:32:00 +0000531 ssize_t n;
Igor Sysoevc3e47462004-09-24 16:12:19 +0000532 ngx_int_t rc, rv;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000533 ngx_connection_t *c;
534 ngx_http_request_t *r;
535 ngx_http_log_ctx_t *ctx;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000536
Igor Sysoeva9830112003-05-19 16:39:14 +0000537 c = rev->data;
538 r = c->data;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000539
Igor Sysoev2b58fbf2003-12-09 15:08:11 +0000540 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
541 "http process request line");
Igor Sysoevdc479b42003-03-20 16:09:44 +0000542
543 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000544 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
545 c->timedout = 1;
546 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000547 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000548 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000549
Igor Sysoevf7abd722004-09-23 06:32:00 +0000550 rc = NGX_AGAIN;
Igor Sysoev016b8522002-08-29 16:59:54 +0000551
Igor Sysoevf7abd722004-09-23 06:32:00 +0000552 for ( ;; ) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000553
Igor Sysoevf7abd722004-09-23 06:32:00 +0000554 if (rc == NGX_AGAIN) {
555 n = ngx_http_read_request_header(r);
Igor Sysoevdc479b42003-03-20 16:09:44 +0000556
Igor Sysoevf7abd722004-09-23 06:32:00 +0000557 if (n == NGX_AGAIN || n == NGX_ERROR) {
Igor Sysoev865c1502003-11-30 20:03:18 +0000558 return;
559 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000560 }
561
Igor Sysoevf7abd722004-09-23 06:32:00 +0000562 rc = ngx_http_parse_request_line(r, r->header_in);
Igor Sysoeva9830112003-05-19 16:39:14 +0000563
Igor Sysoevf7abd722004-09-23 06:32:00 +0000564 if (rc == NGX_OK) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000565
Igor Sysoevf7abd722004-09-23 06:32:00 +0000566 /* the request line has been parsed successfully */
Igor Sysoev6b863e32003-05-12 15:52:24 +0000567
Igor Sysoev1b735832004-11-11 14:07:14 +0000568 r->request_line.len = r->request_end - r->request_start;
569 r->request_line.data = r->request_start;
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000570
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000571
Igor Sysoevdc479b42003-03-20 16:09:44 +0000572 if (r->args_start) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000573 r->uri.len = r->args_start - 1 - r->uri_start;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000574 } else {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000575 r->uri.len = r->uri_end - r->uri_start;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000576 }
577
Igor Sysoevf6906042004-11-25 16:17:31 +0000578
Igor Sysoev924bd792004-10-11 15:07:03 +0000579 if (r->complex_uri || r->quoted_uri) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000580
Igor Sysoevc1571722005-03-19 12:38:37 +0000581 r->uri.data = ngx_palloc(r->pool, r->uri.len + 1);
582 if (r->uri.data == NULL) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000583 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev1b735832004-11-11 14:07:14 +0000584 return;
585 }
586
Igor Sysoevf7abd722004-09-23 06:32:00 +0000587 rc = ngx_http_parse_complex_uri(r);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000588
Igor Sysoevc04deca2005-03-28 14:43:02 +0000589 if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) {
590 ngx_log_error(NGX_LOG_INFO, c->log, 0,
591 "client sent invalid request");
592 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000593 return;
594 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000595
Igor Sysoevf7abd722004-09-23 06:32:00 +0000596 } else {
Igor Sysoev1b735832004-11-11 14:07:14 +0000597 r->uri.data = r->uri_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000598 }
599
Igor Sysoevf6906042004-11-25 16:17:31 +0000600
Igor Sysoev1b735832004-11-11 14:07:14 +0000601 r->unparsed_uri.len = r->uri_end - r->uri_start;
602 r->unparsed_uri.data = r->uri_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000603
Igor Sysoevf7abd722004-09-23 06:32:00 +0000604
Igor Sysoev899b44e2005-05-12 14:58:06 +0000605 r->method_name.len = r->method_end - r->request_start + 1;
606 r->method_name.data = r->request_line.data;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000607
Igor Sysoev1b735832004-11-11 14:07:14 +0000608
Igor Sysoev02025fd2005-01-18 13:03:58 +0000609 if (r->http_protocol.data) {
610 r->http_protocol.len = r->request_end - r->http_protocol.data;
611 }
612
613
Igor Sysoevf7abd722004-09-23 06:32:00 +0000614 if (r->uri_ext) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000615 if (r->args_start) {
616 r->exten.len = r->args_start - 1 - r->uri_ext;
617 } else {
618 r->exten.len = r->uri_end - r->uri_ext;
619 }
620
Igor Sysoev1b735832004-11-11 14:07:14 +0000621 r->exten.data = r->uri_ext;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000622 }
623
Igor Sysoev1b735832004-11-11 14:07:14 +0000624
Igor Sysoevf7abd722004-09-23 06:32:00 +0000625 if (r->args_start && r->uri_end > r->args_start) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000626 r->args.len = r->uri_end - r->args_start;
Igor Sysoev1b735832004-11-11 14:07:14 +0000627 r->args.data = r->args_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000628 }
629
Igor Sysoevf7abd722004-09-23 06:32:00 +0000630
631 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000632 "http request line: \"%V\"", &r->request_line);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000633
634 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000635 "http uri: \"%V\"", &r->uri);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000636
637 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000638 "http args: \"%V\"", &r->args);
639
640 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
641 "http exten: \"%V\"", &r->exten);
642
Igor Sysoevf7abd722004-09-23 06:32:00 +0000643 if (r->http_version < NGX_HTTP_VERSION_10) {
Igor Sysoeve5035392005-08-30 10:55:07 +0000644
645 if (rev->timer_set) {
646 ngx_del_timer(rev);
647 }
648
649#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000650 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoeve5035392005-08-30 10:55:07 +0000651 r->stat_reading = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000652 ngx_atomic_fetch_add(ngx_stat_writing, 1);
Igor Sysoeve5035392005-08-30 10:55:07 +0000653 r->stat_writing = 1;
654#endif
655
656 rev->handler = ngx_http_request_handler;
657 c->write->handler = ngx_http_request_handler;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000658 r->read_event_handler = ngx_http_block_read;
Igor Sysoeve5035392005-08-30 10:55:07 +0000659
Igor Sysoevf7abd722004-09-23 06:32:00 +0000660 ngx_http_handler(r);
Igor Sysoeve5035392005-08-30 10:55:07 +0000661
Igor Sysoev6b863e32003-05-12 15:52:24 +0000662 return;
663 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000664
Igor Sysoevdc479b42003-03-20 16:09:44 +0000665
Igor Sysoevf7abd722004-09-23 06:32:00 +0000666 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000667 sizeof(ngx_table_elt_t))
668 == NGX_ERROR)
Igor Sysoevf7abd722004-09-23 06:32:00 +0000669 {
670 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000671 return;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000672 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000673
674
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000675 if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000676 sizeof(ngx_table_elt_t *))
677 == NGX_ERROR)
Igor Sysoevf7abd722004-09-23 06:32:00 +0000678 {
679 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000680 return;
681 }
682
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000683 c->log->action = "reading client request headers";
Igor Sysoevf7abd722004-09-23 06:32:00 +0000684
Igor Sysoev899b44e2005-05-12 14:58:06 +0000685 rev->handler = ngx_http_process_request_headers;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000686 ngx_http_process_request_headers(rev);
687
688 return;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000689 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000690
Igor Sysoevc04deca2005-03-28 14:43:02 +0000691 if (rc != NGX_AGAIN) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000692
693 /* there was error while a request line parsing */
694
Igor Sysoevc04deca2005-03-28 14:43:02 +0000695 ngx_log_error(NGX_LOG_INFO, c->log, 0,
696 ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
697 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000698 return;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000699 }
700
Igor Sysoevf7abd722004-09-23 06:32:00 +0000701 /* NGX_AGAIN: a request line parsing is still incomplete */
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000702
Igor Sysoev236e0452004-09-23 16:39:34 +0000703 if (r->header_in->pos == r->header_in->end) {
Igor Sysoeva1c8a922004-01-19 18:09:14 +0000704
Igor Sysoevf7abd722004-09-23 06:32:00 +0000705 rv = ngx_http_alloc_large_header_buffer(r, 1);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000706
Igor Sysoevf7abd722004-09-23 06:32:00 +0000707 if (rv == NGX_ERROR) {
708 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000709 return;
710 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000711
Igor Sysoevf7abd722004-09-23 06:32:00 +0000712 if (rv == NGX_DECLINED) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000713 ctx = c->log->data;
714 ctx->request = r;
715
716 r->request_line.len = r->header_in->end - r->request_start;
717 r->request_line.data = r->request_start;
718
719 ngx_log_error(NGX_LOG_INFO, c->log, 0,
720 "client sent too long URI");
721 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000722 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000723 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000724 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000725 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000726}
727
Igor Sysoev1af7c822002-09-13 14:47:42 +0000728
Igor Sysoevc1571722005-03-19 12:38:37 +0000729static void
730ngx_http_process_request_headers(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000731{
Igor Sysoev02f742b2005-04-08 15:18:55 +0000732 ssize_t n;
733 ngx_int_t rc, rv;
734 ngx_uint_t key;
735 ngx_str_t header;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000736 ngx_table_elt_t *h;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000737 ngx_connection_t *c;
738 ngx_http_header_t *hh;
739 ngx_http_request_t *r;
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000740 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000741 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000742
Igor Sysoeva9830112003-05-19 16:39:14 +0000743 c = rev->data;
744 r = c->data;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000745
Igor Sysoev865c1502003-11-30 20:03:18 +0000746 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
747 "http process request header line");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000748
Igor Sysoev6b863e32003-05-12 15:52:24 +0000749 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000750 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
751 c->timedout = 1;
752 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000753 return;
754 }
755
Igor Sysoev02f742b2005-04-08 15:18:55 +0000756 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000757 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000758 hh = (ngx_http_header_t *) cmcf->headers_in_hash.buckets;
759
Igor Sysoevd581fd52003-05-13 16:02:32 +0000760 rc = NGX_AGAIN;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000761
Igor Sysoev016b8522002-08-29 16:59:54 +0000762 for ( ;; ) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000763
Igor Sysoevd581fd52003-05-13 16:02:32 +0000764 if (rc == NGX_AGAIN) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000765
Igor Sysoev236e0452004-09-23 16:39:34 +0000766 if (r->header_in->pos == r->header_in->end) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000767
768 rv = ngx_http_alloc_large_header_buffer(r, 0);
769
770 if (rv == NGX_ERROR) {
771 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000772 return;
773 }
774
775 if (rv == NGX_DECLINED) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000776 header.len = r->header_in->end - r->header_name_start;
777 header.data = r->header_name_start;
Igor Sysoev90c08142005-07-25 09:41:38 +0000778
779 if (header.len > NGX_MAX_ERROR_STR - 300) {
780 header.len = NGX_MAX_ERROR_STR - 300;
781 header.data[header.len++] = '.';
782 header.data[header.len++] = '.';
783 header.data[header.len++] = '.';
784 }
785
Igor Sysoevc04deca2005-03-28 14:43:02 +0000786 ngx_log_error(NGX_LOG_INFO, c->log, 0,
787 "client sent too long header line: \"%V\"",
788 &header);
789 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000790 return;
791 }
792 }
793
Igor Sysoevd581fd52003-05-13 16:02:32 +0000794 n = ngx_http_read_request_header(r);
795
796 if (n == NGX_AGAIN || n == NGX_ERROR) {
797 return;
798 }
799 }
800
Igor Sysoeve6779222003-10-03 15:50:53 +0000801 rc = ngx_http_parse_header_line(r, r->header_in);
Igor Sysoev016b8522002-08-29 16:59:54 +0000802
Igor Sysoev0dad6292003-03-05 17:30:51 +0000803 if (rc == NGX_OK) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000804
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000805 if (r->invalid_header && cscf->ignore_invalid_headers) {
Igor Sysoev4d656dc2005-03-22 16:02:46 +0000806
807 /* there was error while a header line parsing */
808
809 header.len = r->header_end - r->header_name_start;
810 header.data = r->header_name_start;
811
Igor Sysoevc04deca2005-03-28 14:43:02 +0000812 ngx_log_error(NGX_LOG_INFO, c->log, 0,
813 "client sent invalid header line: \"%V\"",
Igor Sysoev4d656dc2005-03-22 16:02:46 +0000814 &header);
815 continue;
816 }
817
Igor Sysoevd581fd52003-05-13 16:02:32 +0000818 /* a header line has been parsed successfully */
819
Igor Sysoevc1571722005-03-19 12:38:37 +0000820 h = ngx_list_push(&r->headers_in.headers);
821 if (h == NULL) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000822 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000823 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000824 }
825
Igor Sysoev02f742b2005-04-08 15:18:55 +0000826 h->hash = r->header_hash;
827
Igor Sysoevd581fd52003-05-13 16:02:32 +0000828 h->key.len = r->header_name_end - r->header_name_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000829 h->key.data = r->header_name_start;
830 h->key.data[h->key.len] = '\0';
831
Igor Sysoevd581fd52003-05-13 16:02:32 +0000832 h->value.len = r->header_end - r->header_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000833 h->value.data = r->header_start;
834 h->value.data[h->value.len] = '\0';
Igor Sysoevd581fd52003-05-13 16:02:32 +0000835
Igor Sysoev899b44e2005-05-12 14:58:06 +0000836 key = h->hash % cmcf->headers_in_hash.hash_size;
837
838 if (hh[key].name.len == h->key.len
839 && ngx_strcasecmp(hh[key].name.data, h->key.data) == 0)
Igor Sysoev967fd632004-08-27 15:40:59 +0000840 {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000841 if (hh[key].handler(r, h, hh[key].offset) != NGX_OK) {
Igor Sysoev967fd632004-08-27 15:40:59 +0000842 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000843 }
Igor Sysoevd581fd52003-05-13 16:02:32 +0000844 }
845
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000846 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000847 "http header: \"%V: %V\"",
848 &h->key, &h->value);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000849
Igor Sysoev6253ca12003-05-27 12:18:54 +0000850 continue;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000851 }
Igor Sysoev6253ca12003-05-27 12:18:54 +0000852
Igor Sysoevc04deca2005-03-28 14:43:02 +0000853 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000854
855 /* a whole header has been parsed successfully */
856
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000857 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
858 "http header done");
Igor Sysoev42feecb2002-12-15 06:25:09 +0000859
Igor Sysoev6a12fc92004-12-06 14:45:08 +0000860 r->request_length += r->header_in->pos - r->header_in->start;
861
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000862 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
863
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000864 rc = ngx_http_process_request_header(r);
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000865
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000866 if (rc != NGX_OK) {
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000867 return;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000868 }
869
Igor Sysoev425a42c2003-10-27 16:16:17 +0000870 if (rev->timer_set) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000871 ngx_del_timer(rev);
872 }
873
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000874#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000875 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000876 r->stat_reading = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000877 ngx_atomic_fetch_add(ngx_stat_writing, 1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000878 r->stat_writing = 1;
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000879#endif
880
Igor Sysoev899b44e2005-05-12 14:58:06 +0000881 rev->handler = ngx_http_request_handler;
882 c->write->handler = ngx_http_request_handler;
883 r->read_event_handler = ngx_http_block_read;
884
Igor Sysoevd581fd52003-05-13 16:02:32 +0000885 ngx_http_handler(r);
Igor Sysoeve5035392005-08-30 10:55:07 +0000886
Igor Sysoevd581fd52003-05-13 16:02:32 +0000887 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000888 }
889
Igor Sysoevc04deca2005-03-28 14:43:02 +0000890 if (rc == NGX_AGAIN) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000891
Igor Sysoevc04deca2005-03-28 14:43:02 +0000892 /* a header line parsing is still not complete */
893
894 continue;
895 }
896
897 /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
898
899 header.len = r->header_end - r->header_name_start;
900 header.data = r->header_name_start;
901 ngx_log_error(NGX_LOG_INFO, c->log, 0,
902 "client sent invalid header line: \"%V\\r...\"",
903 &header);
904 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevc04deca2005-03-28 14:43:02 +0000905 return;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000906 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000907}
908
Igor Sysoevb0869052002-12-10 18:05:12 +0000909
Igor Sysoevc1571722005-03-19 12:38:37 +0000910static ssize_t
911ngx_http_read_request_header(ngx_http_request_t *r)
Igor Sysoev6b863e32003-05-12 15:52:24 +0000912{
Igor Sysoev187fcd82003-05-23 11:53:01 +0000913 ssize_t n;
914 ngx_event_t *rev;
915 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000916
Igor Sysoev239baac2003-06-11 15:28:34 +0000917 rev = r->connection->read;
918
Igor Sysoev6b863e32003-05-12 15:52:24 +0000919 n = r->header_in->last - r->header_in->pos;
920
921 if (n > 0) {
922 return n;
923 }
924
Igor Sysoevb145b062005-06-15 18:33:41 +0000925 if (rev->ready) {
926 n = r->connection->recv(r->connection, r->header_in->last,
927 r->header_in->end - r->header_in->last);
928 } else {
929 n = NGX_AGAIN;
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000930 }
931
Igor Sysoev6b863e32003-05-12 15:52:24 +0000932 if (n == NGX_AGAIN) {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000933 if (!r->header_timeout_set) {
Igor Sysoevf38e0462004-07-16 17:11:43 +0000934 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev187fcd82003-05-23 11:53:01 +0000935 ngx_add_timer(rev, cscf->client_header_timeout);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000936 r->header_timeout_set = 1;
937 }
938
Igor Sysoevb5faed22003-10-29 08:30:44 +0000939 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000940 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000941 return NGX_ERROR;
942 }
943
Igor Sysoev6b863e32003-05-12 15:52:24 +0000944 return NGX_AGAIN;
945 }
946
947 if (n == 0) {
948 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
949 "client closed prematurely connection");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000950 }
Igor Sysoev6b863e32003-05-12 15:52:24 +0000951
952 if (n == 0 || n == NGX_ERROR) {
953 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000954 return NGX_ERROR;
955 }
956
957 r->header_in->last += n;
958
959 return n;
960}
961
962
Igor Sysoevc1571722005-03-19 12:38:37 +0000963static ngx_int_t
964ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
965 ngx_uint_t request_line)
Igor Sysoev85080d02004-09-22 16:18:21 +0000966{
967 u_char *old, *new;
Igor Sysoev85080d02004-09-22 16:18:21 +0000968 ngx_buf_t *b;
969 ngx_http_connection_t *hc;
970 ngx_http_core_srv_conf_t *cscf;
971
972 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
973 "http alloc large header buffer");
974
Igor Sysoevf7abd722004-09-23 06:32:00 +0000975 if (request_line && r->state == 0) {
976
977 /* the client fills up the buffer with "\r\n" */
978
Igor Sysoev6a12fc92004-12-06 14:45:08 +0000979 r->request_length += r->header_in->end - r->header_in->start;
980
Igor Sysoevf7abd722004-09-23 06:32:00 +0000981 r->header_in->pos = r->header_in->start;
982 r->header_in->last = r->header_in->start;
983
984 return NGX_OK;
985 }
986
Igor Sysoev85080d02004-09-22 16:18:21 +0000987 old = request_line ? r->request_start : r->header_name_start;
988
989 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
990
Igor Sysoevf7abd722004-09-23 06:32:00 +0000991 if (r->state != 0
992 && (size_t) (r->header_in->pos - old)
993 >= cscf->large_client_header_buffers.size)
994 {
Igor Sysoev85080d02004-09-22 16:18:21 +0000995 return NGX_DECLINED;
996 }
997
998 hc = r->http_connection;
999
1000 if (hc->nfree) {
1001 b = hc->free[--hc->nfree];
1002
Igor Sysoev236e0452004-09-23 16:39:34 +00001003 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +00001004 "http large header free: %p %uz",
Igor Sysoev236e0452004-09-23 16:39:34 +00001005 b->pos, b->end - b->last);
1006
Igor Sysoevf7abd722004-09-23 06:32:00 +00001007 } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
Igor Sysoev85080d02004-09-22 16:18:21 +00001008
1009 if (hc->busy == NULL) {
1010 hc->busy = ngx_palloc(r->connection->pool,
Igor Sysoevf7abd722004-09-23 06:32:00 +00001011 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev85080d02004-09-22 16:18:21 +00001012 if (hc->busy == NULL) {
1013 return NGX_ERROR;
1014 }
1015 }
1016
1017 b = ngx_create_temp_buf(r->connection->pool,
Igor Sysoevf7abd722004-09-23 06:32:00 +00001018 cscf->large_client_header_buffers.size);
Igor Sysoev85080d02004-09-22 16:18:21 +00001019 if (b == NULL) {
1020 return NGX_ERROR;
1021 }
1022
Igor Sysoev236e0452004-09-23 16:39:34 +00001023 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +00001024 "http large header alloc: %p %uz",
Igor Sysoev236e0452004-09-23 16:39:34 +00001025 b->pos, b->end - b->last);
1026
Igor Sysoev85080d02004-09-22 16:18:21 +00001027 } else {
1028 return NGX_DECLINED;
1029 }
1030
1031 hc->busy[hc->nbusy++] = b;
1032
Igor Sysoevf7abd722004-09-23 06:32:00 +00001033 if (r->state == 0) {
1034 /*
1035 * r->state == 0 means that a header line was parsed successfully
1036 * and we do not need to copy incomplete header line and
1037 * to relocate the parser header pointers
1038 */
1039
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001040 r->request_length += r->header_in->end - r->header_in->start;
1041
Igor Sysoevf7abd722004-09-23 06:32:00 +00001042 r->header_in = b;
1043
1044 return NGX_OK;
1045 }
1046
Igor Sysoev236e0452004-09-23 16:39:34 +00001047 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1048 "http large header copy: %d", r->header_in->pos - old);
1049
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001050 r->request_length += old - r->header_in->start;
1051
Igor Sysoev85080d02004-09-22 16:18:21 +00001052 new = b->start;
1053
Igor Sysoev236e0452004-09-23 16:39:34 +00001054 ngx_memcpy(new, old, r->header_in->pos - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001055
1056 b->pos = new + (r->header_in->pos - old);
Igor Sysoev236e0452004-09-23 16:39:34 +00001057 b->last = new + (r->header_in->pos - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001058
1059 if (request_line) {
1060 r->request_start = new;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001061
1062 if (r->request_end) {
1063 r->request_end = new + (r->request_end - old);
1064 }
1065
1066 r->method_end = new + (r->method_end - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001067
1068 r->uri_start = new + (r->uri_start - old);
1069 r->uri_end = new + (r->uri_end - old);
1070
Igor Sysoevf7abd722004-09-23 06:32:00 +00001071 if (r->schema_start) {
1072 r->schema_start = new + (r->schema_start - old);
1073 r->schema_end = new + (r->schema_end - old);
1074 }
1075
1076 if (r->host_start) {
1077 r->host_start = new + (r->host_start - old);
1078 r->host_end = new + (r->host_end - old);
1079 }
1080
1081 if (r->port_start) {
1082 r->port_start = new + (r->port_start - old);
1083 r->port_end = new + (r->port_end - old);
1084 }
1085
Igor Sysoev85080d02004-09-22 16:18:21 +00001086 if (r->uri_ext) {
1087 r->uri_ext = new + (r->uri_ext - old);
1088 }
1089
1090 if (r->args_start) {
1091 r->args_start = new + (r->args_start - old);
1092 }
1093
1094 } else {
1095 r->header_name_start = new;
1096 r->header_name_end = new + (r->header_name_end - old);
1097 r->header_start = new + (r->header_start - old);
1098 r->header_end = new + (r->header_end - old);
1099 }
1100
1101 r->header_in = b;
1102
1103 return NGX_OK;
1104}
1105
Igor Sysoev85080d02004-09-22 16:18:21 +00001106
Igor Sysoevc1571722005-03-19 12:38:37 +00001107static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001108ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1109 ngx_uint_t offset)
1110{
1111 ngx_table_elt_t **ph;
1112
1113 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1114
1115 if (*ph == NULL) {
1116 *ph = h;
1117 }
1118
1119 return NGX_OK;
1120}
1121
1122
1123static ngx_int_t
Igor Sysoevb145b062005-06-15 18:33:41 +00001124ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1125 ngx_uint_t offset)
1126{
1127 ngx_table_elt_t **ph;
1128
1129 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1130
1131 if (*ph == NULL) {
1132 *ph = h;
1133 return NGX_OK;
1134 }
1135
1136 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1137 "client sent duplicate header line: \"%V: %V\"",
1138 &h->key, &h->value);
1139
1140 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1141
1142 return NGX_ERROR;
1143}
1144
1145
1146static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001147ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
1148 ngx_uint_t offset)
1149{
1150 ngx_table_elt_t **cookie;
1151
1152 cookie = ngx_array_push(&r->headers_in.cookies);
Igor Sysoevb145b062005-06-15 18:33:41 +00001153 if (cookie) {
1154 *cookie = h;
1155 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001156 }
1157
Igor Sysoevb145b062005-06-15 18:33:41 +00001158 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001159
Igor Sysoevb145b062005-06-15 18:33:41 +00001160 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001161}
1162
1163
1164static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001165ngx_http_process_request_header(ngx_http_request_t *r)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001166{
Igor Sysoevc04deca2005-03-28 14:43:02 +00001167 size_t len;
1168 u_char *ua, *user_agent, ch;
1169 ngx_http_core_srv_conf_t *cscf;
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 Sysoevb1dfe472004-12-21 12:30:30 +00001188 if (ngx_http_find_virtual_server(r) != NGX_OK) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001189 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1190 "client sent invalid \"Host\" header");
1191
1192 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1193
1194 if (cscf->restrict_host_names == NGX_HTTP_RESTRICT_HOST_CLOSE) {
1195 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevc04deca2005-03-28 14:43:02 +00001196 return NGX_ERROR;
1197 }
1198
1199 ngx_http_finalize_request(r, NGX_HTTP_INVALID_HOST);
1200 return NGX_ERROR;
Igor Sysoev3043bfc2004-05-14 16:51:47 +00001201 }
1202
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001203 } else {
1204 if (r->http_version > NGX_HTTP_VERSION_10) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001205 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1206 "client sent HTTP/1.1 request without \"Host\" header");
1207 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1208 return NGX_ERROR;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001209 }
Igor Sysoevc04deca2005-03-28 14:43:02 +00001210
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001211 r->headers_in.host_name_len = 0;
1212 }
1213
1214 if (r->headers_in.content_length) {
1215 r->headers_in.content_length_n =
Igor Sysoevc1571722005-03-19 12:38:37 +00001216 ngx_atosz(r->headers_in.content_length->value.data,
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001217 r->headers_in.content_length->value.len);
1218
1219 if (r->headers_in.content_length_n == NGX_ERROR) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001220 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1221 "client sent invalid \"Content-Length\" header");
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001222 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
Igor Sysoevc04deca2005-03-28 14:43:02 +00001223 return NGX_ERROR;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001224 }
1225 }
1226
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001227 if (r->method == NGX_HTTP_POST && r->headers_in.content_length_n == -1) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001228 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1229 "client sent POST method without \"Content-Length\" header");
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001230 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
1231 return NGX_ERROR;
1232 }
1233
1234 if (r->headers_in.transfer_encoding
1235 && ngx_strstr(r->headers_in.transfer_encoding->value.data, "chunked"))
1236 {
1237 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1238 "client sent \"Transfer-Encoding: chunked\" header");
1239 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
Igor Sysoevc04deca2005-03-28 14:43:02 +00001240 return NGX_ERROR;
Igor Sysoev6881bfb2004-03-30 06:27:36 +00001241 }
1242
Igor Sysoevf38e0462004-07-16 17:11:43 +00001243 if (r->plain_http) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001244 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1245 "client sent plain HTTP request to HTTPS port");
1246 ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1247 return NGX_ERROR;
Igor Sysoevf38e0462004-07-16 17:11:43 +00001248 }
1249
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001250 if (r->headers_in.connection) {
1251 if (r->headers_in.connection->value.len == 5
1252 && ngx_strcasecmp(r->headers_in.connection->value.data, "close")
Igor Sysoev899b44e2005-05-12 14:58:06 +00001253 == 0)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001254 {
1255 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1256
1257 } else if (r->headers_in.connection->value.len == 10
1258 && ngx_strcasecmp(r->headers_in.connection->value.data,
Igor Sysoev899b44e2005-05-12 14:58:06 +00001259 "keep-alive") == 0)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001260 {
1261 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1262
1263 if (r->headers_in.keep_alive) {
1264 r->headers_in.keep_alive_n =
Igor Sysoevc1571722005-03-19 12:38:37 +00001265 ngx_atotm(r->headers_in.keep_alive->value.data,
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001266 r->headers_in.keep_alive->value.len);
1267 }
1268 }
1269 }
1270
Igor Sysoev2f657222004-06-16 15:32:11 +00001271 if (r->headers_in.user_agent) {
1272
1273 /*
1274 * check some widespread browsers while the headers are still
1275 * in CPU cache
1276 */
1277
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001278 user_agent = r->headers_in.user_agent->value.data;
1279
1280 ua = (u_char *) ngx_strstr(user_agent, "MSIE");
1281
1282 if (ua && ua + 8 < user_agent + r->headers_in.user_agent->value.len) {
1283
Igor Sysoev2f657222004-06-16 15:32:11 +00001284 r->headers_in.msie = 1;
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001285
Igor Sysoev2f657222004-06-16 15:32:11 +00001286 if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') {
1287 r->headers_in.msie4 = 1;
1288 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001289
1290#if 0
1291 /* MSIE ignores the SSL "close notify" alert */
Igor Sysoev42b12b32004-12-02 18:40:46 +00001292 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00001293 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00001294 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001295#endif
Igor Sysoev2f657222004-06-16 15:32:11 +00001296 }
Igor Sysoev85cccfb2004-09-15 16:00:43 +00001297
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001298 if (ngx_strstr(user_agent, "Opera")) {
Igor Sysoev85cccfb2004-09-15 16:00:43 +00001299 r->headers_in.opera = 1;
1300 r->headers_in.msie = 0;
1301 r->headers_in.msie4 = 0;
1302 }
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001303
1304 if (!r->headers_in.msie && !r->headers_in.opera) {
1305
Igor Sysoeva2c81192004-09-19 18:27:00 +00001306 if (ngx_strstr(user_agent, "Gecko/")) {
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001307 r->headers_in.gecko = 1;
1308
1309 } else if (ngx_strstr(user_agent, "Konqueror")) {
1310 r->headers_in.konqueror = 1;
1311 }
1312 }
Igor Sysoev2f657222004-06-16 15:32:11 +00001313 }
1314
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001315 return NGX_OK;
1316}
1317
1318
Igor Sysoevc1571722005-03-19 12:38:37 +00001319static ngx_int_t
1320ngx_http_find_virtual_server(ngx_http_request_t *r)
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001321{
Igor Sysoev305a9d82005-12-26 17:07:48 +00001322 size_t len;
1323 u_char *host;
1324 ngx_http_virtual_names_t *vn;
1325 ngx_http_core_loc_conf_t *clcf;
1326 ngx_http_core_srv_conf_t *cscf;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001327
Igor Sysoev305a9d82005-12-26 17:07:48 +00001328 vn = r->virtual_names;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001329
Igor Sysoev305a9d82005-12-26 17:07:48 +00001330 if (vn == NULL) {
1331 return NGX_OK;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001332 }
1333
Igor Sysoev305a9d82005-12-26 17:07:48 +00001334 host = r->headers_in.host->value.data;
1335 len = r->headers_in.host_name_len;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001336
Igor Sysoev305a9d82005-12-26 17:07:48 +00001337 /* STUB: ngx_hash_key() here is STUB */
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001338
Igor Sysoev305a9d82005-12-26 17:07:48 +00001339 if (vn->hash.buckets) {
1340 cscf = ngx_hash_find(&vn->hash, ngx_hash_key(host, len), host, len);
1341 if (cscf) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001342 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001343 }
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001344 }
1345
Igor Sysoev305a9d82005-12-26 17:07:48 +00001346 if (vn->dns_wildcards && vn->dns_wildcards->hash.buckets) {
1347 cscf = ngx_hash_find_wildcard(vn->dns_wildcards, host, len);
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001348
Igor Sysoev305a9d82005-12-26 17:07:48 +00001349 if (cscf) {
1350 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001351 }
1352 }
1353
Igor Sysoev899b44e2005-05-12 14:58:06 +00001354 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001355
Igor Sysoev899b44e2005-05-12 14:58:06 +00001356 if (cscf->restrict_host_names == NGX_HTTP_RESTRICT_HOST_OFF) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001357 return NGX_OK;
1358 }
1359
Igor Sysoev899b44e2005-05-12 14:58:06 +00001360 return NGX_ERROR;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001361
Igor Sysoev899b44e2005-05-12 14:58:06 +00001362found:
1363
Igor Sysoev305a9d82005-12-26 17:07:48 +00001364 r->server_name.len = len;
1365 r->server_name.data = host;
1366
1367 r->srv_conf = cscf->ctx->srv_conf;
1368 r->loc_conf = cscf->ctx->loc_conf;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001369
1370 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1371 r->connection->log->file = clcf->err_log->file;
1372
1373 if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1374 r->connection->log->log_level = clcf->err_log->log_level;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001375 }
1376
1377 return NGX_OK;
1378}
1379
1380
Igor Sysoev899b44e2005-05-12 14:58:06 +00001381static void
1382ngx_http_request_handler(ngx_event_t *ev)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001383{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001384 ngx_connection_t *c;
1385 ngx_http_request_t *r;
1386
1387 c = ev->data;
1388 r = c->data;
1389
1390 if (ev->write) {
1391 r->write_event_handler(r);
1392
1393 } else {
1394 r->read_event_handler(r);
1395 }
1396}
1397
1398
1399void
1400ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1401{
1402 ngx_http_request_t *pr;
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001403 ngx_http_core_loc_conf_t *clcf;
1404
Igor Sysoev899b44e2005-05-12 14:58:06 +00001405 if (rc == NGX_DONE) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001406 /* the request pool may be already destroyed */
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001407 return;
1408 }
1409
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001410 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1411 "http finalize request: %d, \"%V?%V\"",
1412 rc, &r->uri, &r->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001413
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001414 if (rc == NGX_ERROR || r->connection->error) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001415 ngx_http_close_request(r, 0);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001416 return;
1417 }
1418
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001419 if (rc >= NGX_HTTP_SPECIAL_RESPONSE || rc == NGX_HTTP_NO_CONTENT) {
1420
Igor Sysoevcdc46302005-12-07 14:51:31 +00001421 if (rc == NGX_HTTP_CLOSE) {
1422 ngx_http_close_request(r, rc);
1423 return;
1424 }
1425
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001426 if (r == r->main) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001427 if (r->connection->read->timer_set) {
1428 ngx_del_timer(r->connection->read);
1429 }
1430
1431 if (r->connection->write->timer_set) {
1432 ngx_del_timer(r->connection->write);
1433 }
1434 }
1435
1436 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
1437
1438 return;
1439 }
1440
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001441 if (r != r->main || rc == NGX_AGAIN) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001442 if (ngx_http_set_write_handler(r) != NGX_OK) {
1443 return;
1444 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001445 }
1446
1447 r->done = 1;
1448
1449 if (r != r->connection->data) {
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001450 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1451 "http finalize non-active request: \"%V?%V\"",
1452 &r->uri, &r->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001453 return;
1454 }
1455
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001456 if (r != r->main) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001457
1458 pr = r->parent;
1459
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001460 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1461 "http parent request: \"%V?%V\"", &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001462
Igor Sysoev899b44e2005-05-12 14:58:06 +00001463 if (rc != NGX_AGAIN) {
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001464 r->connection->data = pr;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001465 }
1466
1467 if (pr->postponed) {
1468
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001469 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1470 "http request: \"%V?%V\" has postponed",
1471 &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001472
Igor Sysoev899b44e2005-05-12 14:58:06 +00001473 if (rc != NGX_AGAIN && pr->postponed->request == r) {
1474 pr->postponed = pr->postponed->next;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001475 }
1476
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001477 if (r->fast_subrequest) {
1478 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1479 "http fast subrequest: \"%V?%V\" done",
1480 &r->uri, &r->args);
1481 return;
1482 }
1483
1484 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1485 "http wake parent request: \"%V?%V\"",
1486 &pr->uri, &pr->args);
1487
1488 pr->write_event_handler(pr);
1489
1490#if 0
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001491 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1492 "http request: \"%V?%V\" still has postponed",
1493 &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001494
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001495 if (pr->done || pr->postponed->out) {
1496 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1497 "http wake parent request: \"%V?%V\"",
1498 &pr->uri, &pr->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001499
1500 pr->write_event_handler(pr);
1501 }
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001502#endif
1503
Igor Sysoev899b44e2005-05-12 14:58:06 +00001504 }
1505
1506 return;
1507 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001508
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001509 if (rc == NGX_AGAIN) {
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001510 return;
Igor Sysoev5192b362005-07-08 14:34:20 +00001511 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001512
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001513 if (r->connection->buffered) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001514 (void) ngx_http_set_write_handler(r);
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001515 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001516 }
1517
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001518 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1519
1520 if (clcf->post_action.data) {
1521 ngx_http_internal_redirect(r, &clcf->post_action, NULL);
1522 return;
1523 }
1524
Igor Sysoev0a280a32003-10-12 16:49:16 +00001525 if (r->connection->read->timer_set) {
1526 ngx_del_timer(r->connection->read);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001527 }
1528
Igor Sysoev0a280a32003-10-12 16:49:16 +00001529 if (r->connection->write->timer_set) {
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001530 r->connection->write->delayed = 0;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001531 ngx_del_timer(r->connection->write);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001532 }
1533
Igor Sysoev24025022005-12-16 15:07:08 +00001534 if (r->connection->destroyed) {
1535 return;
1536 }
1537
Igor Sysoevcdc46302005-12-07 14:51:31 +00001538#if 0
Igor Sysoev98c1cf12004-07-02 15:54:34 +00001539 if (r->connection->read->pending_eof) {
Igor Sysoev42b12b32004-12-02 18:40:46 +00001540#if (NGX_HAVE_KQUEUE)
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001541 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log,
1542 r->connection->read->kq_errno,
Igor Sysoev7af6b162004-02-09 07:46:43 +00001543 "kevent() reported about an closed connection");
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001544#endif
1545 ngx_http_close_request(r, 0);
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001546 return;
1547 }
Igor Sysoevcdc46302005-12-07 14:51:31 +00001548#endif
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001549
Igor Sysoevc5991982004-01-16 06:15:48 +00001550 if (!ngx_terminate
Igor Sysoev3f4685f2004-04-25 20:13:21 +00001551 && !ngx_exiting
Igor Sysoevc5991982004-01-16 06:15:48 +00001552 && r->keepalive != 0
1553 && clcf->keepalive_timeout > 0)
1554 {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001555 ngx_http_set_keepalive(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001556 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001557
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001558 } else if (r->lingering_close && clcf->lingering_timeout > 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001559 ngx_http_set_lingering_close(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001560 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001561 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001562
Igor Sysoevc5991982004-01-16 06:15:48 +00001563 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001564}
1565
1566
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001567static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001568ngx_http_set_write_handler(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001569{
Igor Sysoevd581fd52003-05-13 16:02:32 +00001570 ngx_event_t *wev;
Igor Sysoeva9830112003-05-19 16:39:14 +00001571 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001572
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001573 r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
1574
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001575 r->write_event_handler = ngx_http_writer;
1576
Igor Sysoev899b44e2005-05-12 14:58:06 +00001577 wev = r->connection->write;
1578
Igor Sysoevef066482004-06-21 15:59:32 +00001579 if (wev->ready && wev->delayed) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001580 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001581 }
1582
Igor Sysoev899b44e2005-05-12 14:58:06 +00001583 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001584 if (!wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001585 ngx_add_timer(wev, clcf->send_timeout);
1586 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001587
Igor Sysoev924bd792004-10-11 15:07:03 +00001588 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001589 ngx_http_close_request(r, 0);
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001590 return NGX_ERROR;
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001591 }
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001592
1593 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001594}
1595
1596
Igor Sysoev899b44e2005-05-12 14:58:06 +00001597static void
1598ngx_http_writer(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001599{
1600 int rc;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001601 ngx_event_t *wev;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001602 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001603 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001604
Igor Sysoev899b44e2005-05-12 14:58:06 +00001605 c = r->connection;
1606 wev = c->write;
Igor Sysoev160d7742003-11-19 16:26:41 +00001607
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001608 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1609 "http writer handler: \"%V?%V\"", &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001610
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001611 if (wev->timedout) {
Igor Sysoevef066482004-06-21 15:59:32 +00001612 if (!wev->delayed) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001613 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
1614 "client timed out");
1615 c->timedout = 1;
Igor Sysoev055951d2005-10-21 19:12:18 +00001616
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001617 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001618 return;
1619 }
1620
1621 wev->timedout = 0;
Igor Sysoevef066482004-06-21 15:59:32 +00001622 wev->delayed = 0;
Igor Sysoev73a73b52004-06-20 19:54:15 +00001623
1624 if (!wev->ready) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001625 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001626 ngx_add_timer(wev, clcf->send_timeout);
1627
Igor Sysoev924bd792004-10-11 15:07:03 +00001628 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001629 ngx_http_close_request(r, 0);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001630 }
1631
1632 return;
1633 }
1634
1635 } else {
Igor Sysoevef066482004-06-21 15:59:32 +00001636 if (wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001637 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1638 "http writer delayed");
Igor Sysoevef066482004-06-21 15:59:32 +00001639
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001640 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001641
Igor Sysoev924bd792004-10-11 15:07:03 +00001642 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001643 ngx_http_close_request(r, 0);
Igor Sysoevef066482004-06-21 15:59:32 +00001644 }
1645
Igor Sysoev73a73b52004-06-20 19:54:15 +00001646 return;
1647 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001648 }
1649
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001650 rc = ngx_http_output_filter(r, NULL);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001651
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001652 if (c->destroyed) {
1653 return;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001654 }
1655
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001656 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
1657 "http writer output filter: %d, \"%V?%V\"",
1658 rc, &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001659
1660 if (rc == NGX_AGAIN) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001661 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001662 if (!wev->ready && !wev->delayed) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001663 ngx_add_timer(wev, clcf->send_timeout);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001664 }
1665
Igor Sysoev924bd792004-10-11 15:07:03 +00001666 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001667 ngx_http_close_request(r, 0);
Igor Sysoev0a280a32003-10-12 16:49:16 +00001668 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001669
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001670 if (r == r->main) {
1671 return;
1672 }
1673
1674 rc = NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001675 }
1676
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001677 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1678 "http writer done: \"%V?%V\"", &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001679
Igor Sysoev0a280a32003-10-12 16:49:16 +00001680 ngx_http_finalize_request(r, rc);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001681}
1682
1683
Igor Sysoev899b44e2005-05-12 14:58:06 +00001684static void
1685ngx_http_block_read(ngx_http_request_t *r)
1686{
1687 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1688 "http read blocked");
Igor Sysoev42feecb2002-12-15 06:25:09 +00001689
Igor Sysoev73009772003-02-06 17:21:13 +00001690 /* aio does not call this handler */
1691
Igor Sysoev899b44e2005-05-12 14:58:06 +00001692 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
1693 && r->connection->read->active)
1694 {
1695 if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0)
1696 == NGX_ERROR)
1697 {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001698 ngx_http_close_request(r, 0);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001699 }
Igor Sysoev73009772003-02-06 17:21:13 +00001700 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001701}
1702
1703
Igor Sysoevc1571722005-03-19 12:38:37 +00001704ngx_int_t
1705ngx_http_discard_body(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001706{
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001707 ssize_t size;
1708 ngx_event_t *rev;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001709
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001710 if (r != r->main) {
Igor Sysoev7b190b42005-06-07 15:56:31 +00001711 return NGX_OK;
1712 }
1713
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001714 rev = r->connection->read;
Igor Sysoev9b25d692003-01-26 21:08:14 +00001715
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001716 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body");
Igor Sysoev9b25d692003-01-26 21:08:14 +00001717
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001718 if (rev->timer_set) {
1719 ngx_del_timer(rev);
Igor Sysoev9b25d692003-01-26 21:08:14 +00001720 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001721
Igor Sysoev0a280a32003-10-12 16:49:16 +00001722 if (r->headers_in.content_length_n <= 0) {
1723 return NGX_OK;
1724 }
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001725
Igor Sysoeve5035392005-08-30 10:55:07 +00001726 r->discard_body = 1;
1727
Igor Sysoev0a280a32003-10-12 16:49:16 +00001728 size = r->header_in->last - r->header_in->pos;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001729
Igor Sysoev0a280a32003-10-12 16:49:16 +00001730 if (size) {
1731 if (r->headers_in.content_length_n > size) {
1732 r->headers_in.content_length_n -= size;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001733
Igor Sysoev0a280a32003-10-12 16:49:16 +00001734 } else {
1735 r->header_in->pos += r->headers_in.content_length_n;
1736 r->headers_in.content_length_n = 0;
1737 return NGX_OK;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001738 }
Igor Sysoev73009772003-02-06 17:21:13 +00001739 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001740
Igor Sysoev899b44e2005-05-12 14:58:06 +00001741 r->read_event_handler = ngx_http_read_discarded_body_handler;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001742
Igor Sysoev899b44e2005-05-12 14:58:06 +00001743 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001744 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1745 }
1746
1747 return ngx_http_read_discarded_body(r);
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001748}
1749
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001750
Igor Sysoevc1571722005-03-19 12:38:37 +00001751static void
Igor Sysoev899b44e2005-05-12 14:58:06 +00001752ngx_http_read_discarded_body_handler(ngx_http_request_t *r)
Igor Sysoev42feecb2002-12-15 06:25:09 +00001753{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001754 ngx_int_t rc;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001755
1756 rc = ngx_http_read_discarded_body(r);
1757
Igor Sysoev0a280a32003-10-12 16:49:16 +00001758 if (rc == NGX_AGAIN) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001759 if (ngx_handle_read_event(r->connection->read, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001760 ngx_http_close_request(r, rc);
Igor Sysoev0a280a32003-10-12 16:49:16 +00001761 return;
1762 }
1763 }
1764
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001765 if (rc != NGX_OK) {
1766 ngx_http_close_request(r, rc);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001767 }
1768}
1769
1770
Igor Sysoevc1571722005-03-19 12:38:37 +00001771static ngx_int_t
1772ngx_http_read_discarded_body(ngx_http_request_t *r)
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001773{
Igor Sysoevf7abd722004-09-23 06:32:00 +00001774 ssize_t size, n;
1775 u_char buffer[NGX_HTTP_DISCARD_BUFFER_SIZE];
Igor Sysoev42feecb2002-12-15 06:25:09 +00001776
Igor Sysoeve04084c2004-01-26 08:52:49 +00001777 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1778 "http read discarded body");
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001779
Igor Sysoev0a280a32003-10-12 16:49:16 +00001780 if (r->headers_in.content_length_n == 0) {
1781 return NGX_OK;
1782 }
1783
Igor Sysoev42feecb2002-12-15 06:25:09 +00001784
Igor Sysoeva09f08d2003-04-25 14:43:13 +00001785 size = r->headers_in.content_length_n;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001786
Igor Sysoevf7abd722004-09-23 06:32:00 +00001787 if (size > NGX_HTTP_DISCARD_BUFFER_SIZE) {
1788 size = NGX_HTTP_DISCARD_BUFFER_SIZE;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001789 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001790
Igor Sysoevf7abd722004-09-23 06:32:00 +00001791 n = r->connection->recv(r->connection, buffer, size);
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001792
Igor Sysoevdc479b42003-03-20 16:09:44 +00001793 if (n == NGX_ERROR) {
Igor Sysoev89690bf2004-03-23 06:01:52 +00001794
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001795 r->connection->error = 1;
Igor Sysoev89690bf2004-03-23 06:01:52 +00001796
1797 /*
Igor Sysoevf7abd722004-09-23 06:32:00 +00001798 * if a client request body is discarded then we already set
Igor Sysoev89690bf2004-03-23 06:01:52 +00001799 * some HTTP response code for client and we can ignore the error
1800 */
1801
1802 return NGX_OK;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001803 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001804
Igor Sysoevdc479b42003-03-20 16:09:44 +00001805 if (n == NGX_AGAIN) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001806 return NGX_AGAIN;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001807 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001808
Igor Sysoeva09f08d2003-04-25 14:43:13 +00001809 r->headers_in.content_length_n -= n;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001810
Igor Sysoev42feecb2002-12-15 06:25:09 +00001811 return NGX_OK;
1812}
1813
1814
Igor Sysoevc1571722005-03-19 12:38:37 +00001815static void
1816ngx_http_set_keepalive(ngx_http_request_t *r)
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001817{
Igor Sysoev924bd792004-10-11 15:07:03 +00001818 int tcp_nodelay;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001819 ngx_int_t i;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001820 ngx_buf_t *b, *f;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001821 ngx_event_t *rev, *wev;
1822 ngx_connection_t *c;
Igor Sysoevdd888c42004-09-21 05:38:28 +00001823 ngx_http_connection_t *hc;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001824 ngx_http_core_srv_conf_t *cscf;
1825 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001826
Igor Sysoev6253ca12003-05-27 12:18:54 +00001827 c = r->connection;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001828 rev = c->read;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001829
Igor Sysoeve04084c2004-01-26 08:52:49 +00001830 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001831
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001832 c->log->action = "closing request";
Igor Sysoevdd888c42004-09-21 05:38:28 +00001833
1834 hc = r->http_connection;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001835 b = r->header_in;
1836
Igor Sysoev236e0452004-09-23 16:39:34 +00001837 if (b->pos < b->last) {
Igor Sysoevf7abd722004-09-23 06:32:00 +00001838
Igor Sysoev236e0452004-09-23 16:39:34 +00001839 /* the pipelined request */
Igor Sysoevf7abd722004-09-23 06:32:00 +00001840
1841 if (b != c->buffer) {
1842
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001843 /*
1844 * If the large header buffers were allocated while the previous
1845 * request processing then we do not use c->buffer for
1846 * the pipelined request (see ngx_http_init_request()).
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001847 *
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001848 * Now we would move the large header buffers to the free list.
1849 */
Igor Sysoevf7abd722004-09-23 06:32:00 +00001850
1851 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1852
1853 if (hc->free == NULL) {
1854 hc->free = ngx_palloc(c->pool,
1855 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev236e0452004-09-23 16:39:34 +00001856
Igor Sysoevf7abd722004-09-23 06:32:00 +00001857 if (hc->free == NULL) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001858 ngx_http_close_request(r, 0);
Igor Sysoevf7abd722004-09-23 06:32:00 +00001859 return;
1860 }
1861 }
1862
1863 for (i = 0; i < hc->nbusy - 1; i++) {
1864 f = hc->busy[i];
1865 hc->free[hc->nfree++] = f;
1866 f->pos = f->start;
1867 f->last = f->start;
1868 }
1869
1870 hc->busy[0] = b;
1871 hc->nbusy = 1;
1872 }
1873 }
1874
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001875 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1876
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001877 ngx_http_request_done(r, 0);
1878
Igor Sysoevdd888c42004-09-21 05:38:28 +00001879 c->data = hc;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001880
Igor Sysoevfa73aac2003-05-21 13:28:21 +00001881 ngx_add_timer(rev, clcf->keepalive_timeout);
1882
Igor Sysoev899b44e2005-05-12 14:58:06 +00001883 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001884 ngx_http_close_connection(c);
1885 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00001886 }
1887
Igor Sysoev7b6062a2004-02-12 20:57:10 +00001888 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001889 wev->handler = ngx_http_empty_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001890
Igor Sysoev369145c2004-05-28 15:49:23 +00001891 if (b->pos < b->last) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001892
Igor Sysoeve04084c2004-01-26 08:52:49 +00001893 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
Igor Sysoev6253ca12003-05-27 12:18:54 +00001894
Igor Sysoev055951d2005-10-21 19:12:18 +00001895#if (NGX_STAT_STUB)
1896 ngx_atomic_fetch_add(ngx_stat_reading, 1);
1897#endif
1898
Igor Sysoevdd888c42004-09-21 05:38:28 +00001899 hc->pipeline = 1;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001900 c->log->action = "reading client pipelined request line";
Igor Sysoev055951d2005-10-21 19:12:18 +00001901
Igor Sysoevd581fd52003-05-13 16:02:32 +00001902 ngx_http_init_request(rev);
1903 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001904 }
1905
Igor Sysoevdd888c42004-09-21 05:38:28 +00001906 hc->pipeline = 0;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001907
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001908 /*
1909 * To keep a memory footprint as small as possible for an idle
1910 * keepalive connection we try to free the ngx_http_request_t and
1911 * c->buffer's memory if they were allocated outside the c->pool.
1912 * The large header buffers are always allocated outside the c->pool and
1913 * are freed too.
1914 */
1915
Igor Sysoev236e0452004-09-23 16:39:34 +00001916 if (ngx_pfree(c->pool, r) == NGX_OK) {
1917 hc->request = NULL;
1918 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00001919
Igor Sysoev236e0452004-09-23 16:39:34 +00001920 b = c->buffer;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001921
Igor Sysoev236e0452004-09-23 16:39:34 +00001922 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001923
1924 /*
1925 * the special note for ngx_http_keepalive_handler() that
1926 * c->buffer's memory was freed
1927 */
1928
Igor Sysoev236e0452004-09-23 16:39:34 +00001929 b->pos = NULL;
1930
1931 } else {
1932 b->pos = b->start;
1933 b->last = b->start;
1934 }
1935
Igor Sysoev1b735832004-11-11 14:07:14 +00001936 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00001937 hc->free, hc->nfree);
1938
1939 if (hc->free) {
1940 for (i = 0; i < hc->nfree; i++) {
1941 ngx_pfree(c->pool, hc->free[i]);
1942 hc->free[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001943 }
1944
Igor Sysoev236e0452004-09-23 16:39:34 +00001945 hc->nfree = 0;
1946 }
1947
Igor Sysoev1b735832004-11-11 14:07:14 +00001948 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00001949 hc->busy, hc->nbusy);
1950
1951 if (hc->busy) {
1952 for (i = 0; i < hc->nbusy; i++) {
1953 ngx_pfree(c->pool, hc->busy[i]);
1954 hc->busy[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001955 }
1956
Igor Sysoev236e0452004-09-23 16:39:34 +00001957 hc->nbusy = 0;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001958 }
1959
Igor Sysoev899b44e2005-05-12 14:58:06 +00001960 rev->handler = ngx_http_keepalive_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001961
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001962 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
1963 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
1964 ngx_http_close_connection(c);
1965 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001966 }
1967 }
1968
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001969 c->log->action = "keepalive";
Igor Sysoev6a644c62003-03-04 06:33:48 +00001970
Igor Sysoev67f450d2004-06-01 06:04:46 +00001971 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
Igor Sysoevc1571722005-03-19 12:38:37 +00001972 if (ngx_tcp_push(c->fd) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00001973 ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
1974 ngx_http_close_connection(c);
1975 return;
Igor Sysoev9cf78302003-06-04 17:28:33 +00001976 }
Igor Sysoev924bd792004-10-11 15:07:03 +00001977
Igor Sysoev67f450d2004-06-01 06:04:46 +00001978 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
Igor Sysoev42b12b32004-12-02 18:40:46 +00001979 tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
Igor Sysoev924bd792004-10-11 15:07:03 +00001980
1981 } else {
Igor Sysoev42b12b32004-12-02 18:40:46 +00001982 tcp_nodelay = 1;
1983 }
Igor Sysoev924bd792004-10-11 15:07:03 +00001984
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001985 if (tcp_nodelay
1986 && clcf->tcp_nodelay
1987 && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
1988 {
Igor Sysoev42b12b32004-12-02 18:40:46 +00001989 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
Igor Sysoev924bd792004-10-11 15:07:03 +00001990
Igor Sysoev42b12b32004-12-02 18:40:46 +00001991 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
1992 (const void *) &tcp_nodelay, sizeof(int)) == -1)
1993 {
1994 ngx_connection_error(c, ngx_socket_errno,
1995 "setsockopt(TCP_NODELAY) failed");
1996 ngx_http_close_connection(c);
1997 return;
Igor Sysoev924bd792004-10-11 15:07:03 +00001998 }
Igor Sysoev42b12b32004-12-02 18:40:46 +00001999
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002000 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
Igor Sysoev9cf78302003-06-04 17:28:33 +00002001 }
2002
Igor Sysoevf7abd722004-09-23 06:32:00 +00002003#if 0
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002004 /* if ngx_http_request_t was freed then we need some other place */
Igor Sysoevc83f6832004-06-24 07:53:37 +00002005 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002006#endif
Igor Sysoevc83f6832004-06-24 07:53:37 +00002007
Igor Sysoevb5faed22003-10-29 08:30:44 +00002008 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002009 ngx_http_keepalive_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00002010 }
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002011}
2012
2013
Igor Sysoevc1571722005-03-19 12:38:37 +00002014static void
2015ngx_http_keepalive_handler(ngx_event_t *rev)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002016{
Igor Sysoevc1571722005-03-19 12:38:37 +00002017 size_t size;
2018 ssize_t n;
2019 ngx_buf_t *b;
2020 ngx_connection_t *c;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002021
Igor Sysoev0ad25372004-07-16 06:33:35 +00002022 c = rev->data;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002023
Igor Sysoeve04084c2004-01-26 08:52:49 +00002024 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
Igor Sysoev1af7c822002-09-13 14:47:42 +00002025
Igor Sysoevdc479b42003-03-20 16:09:44 +00002026 if (rev->timedout) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002027 ngx_http_close_connection(c);
2028 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00002029 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002030
Igor Sysoevf6906042004-11-25 16:17:31 +00002031#if (NGX_HAVE_KQUEUE)
Igor Sysoev236e0452004-09-23 16:39:34 +00002032
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002033 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoevcdc46302005-12-07 14:51:31 +00002034 if (rev->pending_eof) {
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002035 c->log->handler = NULL;
Igor Sysoev236e0452004-09-23 16:39:34 +00002036 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
Igor Sysoev1b735832004-11-11 14:07:14 +00002037 "kevent() reported that client %V closed "
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002038 "keepalive connection", &c->addr_text);
Igor Sysoev42b12b32004-12-02 18:40:46 +00002039#if (NGX_HTTP_SSL)
2040 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00002041 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00002042 }
2043#endif
Igor Sysoev236e0452004-09-23 16:39:34 +00002044 ngx_http_close_connection(c);
2045 return;
2046 }
2047 }
2048
2049#endif
2050
Igor Sysoev236e0452004-09-23 16:39:34 +00002051 b = c->buffer;
2052 size = b->end - b->start;
2053
2054 if (b->pos == NULL) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002055
2056 /*
2057 * The c->buffer's memory was freed by ngx_http_set_keepalive().
2058 * However, the c->buffer->start and c->buffer->end were not changed
2059 * to keep the buffer size.
2060 */
2061
Igor Sysoevc1571722005-03-19 12:38:37 +00002062 b->pos = ngx_palloc(c->pool, size);
2063 if (b->pos == NULL) {
Igor Sysoev236e0452004-09-23 16:39:34 +00002064 ngx_http_close_connection(c);
2065 return;
2066 }
2067
2068 b->start = b->pos;
2069 b->last = b->pos;
2070 b->end = b->pos + size;
2071 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00002072
Igor Sysoev0a280a32003-10-12 16:49:16 +00002073 /*
2074 * MSIE closes a keepalive connection with RST flag
2075 * so we ignore ECONNRESET here.
2076 */
Igor Sysoevb7387572003-03-11 20:38:13 +00002077
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002078 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
Igor Sysoevb7387572003-03-11 20:38:13 +00002079 ngx_set_socket_errno(0);
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00002080
Igor Sysoev236e0452004-09-23 16:39:34 +00002081 n = c->recv(c, b->last, size);
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002082 c->log_error = NGX_ERROR_INFO;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002083
Igor Sysoevd581fd52003-05-13 16:02:32 +00002084 if (n == NGX_AGAIN) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002085 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002086 ngx_http_close_connection(c);
2087 }
2088
Igor Sysoevd581fd52003-05-13 16:02:32 +00002089 return;
2090 }
2091
2092 if (n == NGX_ERROR) {
2093 ngx_http_close_connection(c);
2094 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00002095 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002096
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002097 c->log->handler = NULL;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002098
2099 if (n == 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +00002100 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002101 "client %V closed keepalive connection", &c->addr_text);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002102 ngx_http_close_connection(c);
2103 return;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002104 }
2105
Igor Sysoevf7abd722004-09-23 06:32:00 +00002106 b->last += n;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002107
Igor Sysoev055951d2005-10-21 19:12:18 +00002108#if (NGX_STAT_STUB)
2109 ngx_atomic_fetch_add(ngx_stat_reading, 1);
2110#endif
2111
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002112 c->log->handler = ngx_http_log_error;
2113 c->log->action = "reading client request line";
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002114
Igor Sysoevd581fd52003-05-13 16:02:32 +00002115 ngx_http_init_request(rev);
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002116}
2117
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002118
Igor Sysoevc1571722005-03-19 12:38:37 +00002119static void
2120ngx_http_set_lingering_close(ngx_http_request_t *r)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002121{
Igor Sysoev0a280a32003-10-12 16:49:16 +00002122 ngx_event_t *rev, *wev;
Igor Sysoevb7387572003-03-11 20:38:13 +00002123 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002124 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002125
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002126 c = r->connection;
Igor Sysoev9b25d692003-01-26 21:08:14 +00002127
Igor Sysoev6253ca12003-05-27 12:18:54 +00002128 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002129
Igor Sysoev0a280a32003-10-12 16:49:16 +00002130 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002131 rev->handler = ngx_http_lingering_close_handler;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002132
Igor Sysoev208eed22005-10-07 13:30:52 +00002133 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
Igor Sysoev6253ca12003-05-27 12:18:54 +00002134 ngx_add_timer(rev, clcf->lingering_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +00002135
Igor Sysoev899b44e2005-05-12 14:58:06 +00002136 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00002137 ngx_http_close_request(r, 0);
Igor Sysoev0a280a32003-10-12 16:49:16 +00002138 return;
2139 }
2140
2141 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002142 wev->handler = ngx_http_empty_handler;
Igor Sysoev0a280a32003-10-12 16:49:16 +00002143
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002144 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2145 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
2146 ngx_http_close_request(r, 0);
2147 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00002148 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002149 }
2150
Igor Sysoevb7387572003-03-11 20:38:13 +00002151 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00002152 ngx_connection_error(c, ngx_socket_errno,
2153 ngx_shutdown_socket_n " failed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002154 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002155 return;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002156 }
2157
Igor Sysoevb5faed22003-10-29 08:30:44 +00002158 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002159 ngx_http_lingering_close_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00002160 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002161}
2162
2163
Igor Sysoevc1571722005-03-19 12:38:37 +00002164static void
2165ngx_http_lingering_close_handler(ngx_event_t *rev)
Igor Sysoev42feecb2002-12-15 06:25:09 +00002166{
Igor Sysoevdc479b42003-03-20 16:09:44 +00002167 ssize_t n;
2168 ngx_msec_t timer;
2169 ngx_connection_t *c;
2170 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002171 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002172 u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
Igor Sysoev1af7c822002-09-13 14:47:42 +00002173
Igor Sysoev6253ca12003-05-27 12:18:54 +00002174 c = rev->data;
2175 r = c->data;
Igor Sysoev86de4cb2003-01-30 07:28:09 +00002176
Igor Sysoeve04084c2004-01-26 08:52:49 +00002177 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2178 "http lingering close handler");
Igor Sysoevdc479b42003-03-20 16:09:44 +00002179
2180 if (rev->timedout) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002181 c->timedout = 1;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002182 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002183 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002184 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002185
Igor Sysoevc0247302004-06-27 18:01:57 +00002186 timer = r->lingering_time - ngx_time();
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002187 if (timer <= 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002188 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002189 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002190 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002191
Igor Sysoevdc479b42003-03-20 16:09:44 +00002192 do {
Igor Sysoevf7abd722004-09-23 06:32:00 +00002193 n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002194
Igor Sysoeve04084c2004-01-26 08:52:49 +00002195 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002196
Igor Sysoevdc479b42003-03-20 16:09:44 +00002197 if (n == NGX_ERROR || n == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002198 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002199 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002200 }
2201
2202 } while (rev->ready);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002203
Igor Sysoev899b44e2005-05-12 14:58:06 +00002204 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00002205 ngx_http_close_request(r, 0);
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002206 return;
2207 }
2208
Igor Sysoevf7abd722004-09-23 06:32:00 +00002209 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2210
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002211 timer *= 1000;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002212
Igor Sysoev6253ca12003-05-27 12:18:54 +00002213 if (timer > clcf->lingering_timeout) {
2214 timer = clcf->lingering_timeout;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002215 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002216
Igor Sysoevdc479b42003-03-20 16:09:44 +00002217 ngx_add_timer(rev, timer);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002218}
2219
Igor Sysoev2b542382002-08-20 14:48:28 +00002220
Igor Sysoevc1571722005-03-19 12:38:37 +00002221void
2222ngx_http_empty_handler(ngx_event_t *wev)
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002223{
Igor Sysoeve04084c2004-01-26 08:52:49 +00002224 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002225
2226 return;
2227}
2228
2229
Igor Sysoev899b44e2005-05-12 14:58:06 +00002230void
2231ngx_http_request_empty_handler(ngx_http_request_t *r)
2232{
2233 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002234 "http request empty handler");
Igor Sysoev899b44e2005-05-12 14:58:06 +00002235
2236 return;
2237}
2238
2239
Igor Sysoevc1571722005-03-19 12:38:37 +00002240ngx_int_t
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002241ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002242{
Igor Sysoev369145c2004-05-28 15:49:23 +00002243 ngx_buf_t *b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002244 ngx_chain_t out;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002245
Igor Sysoevc1571722005-03-19 12:38:37 +00002246 b = ngx_calloc_buf(r->pool);
2247 if (b == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +00002248 return NGX_ERROR;
2249 }
2250
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002251 if (flags & NGX_HTTP_LAST) {
2252 b->last_buf = 1;
2253 }
2254
2255 if (flags & NGX_HTTP_FLUSH) {
2256 b->flush = 1;
2257 }
2258
Igor Sysoev369145c2004-05-28 15:49:23 +00002259 out.buf = b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002260 out.next = NULL;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002261
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002262 return ngx_http_output_filter(r, &out);
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002263}
2264
2265
Igor Sysoevc1571722005-03-19 12:38:37 +00002266void
Igor Sysoev899b44e2005-05-12 14:58:06 +00002267ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error)
Igor Sysoevd581fd52003-05-13 16:02:32 +00002268{
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002269 ngx_connection_t *c;
2270 ngx_http_cleanup_t *cln;
2271
2272 c = r->connection;
2273 r = r->main;
2274
2275 for (cln = r->cleanup; cln; cln = cln->next) {
2276 if (cln->handler) {
2277 cln->handler(cln->data);
2278 }
2279 }
2280
2281 ngx_http_request_done(r, error);
2282 ngx_http_close_connection(c);
2283}
2284
2285
2286void
2287ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error)
2288{
2289 ngx_log_t *log;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002290 ngx_uint_t i, n;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002291 struct linger linger;
2292 ngx_http_log_ctx_t *ctx;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002293 ngx_http_handler_pt *log_handler;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002294 ngx_http_core_loc_conf_t *clcf;
2295 ngx_http_core_main_conf_t *cmcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002296
Igor Sysoev865c1502003-11-30 20:03:18 +00002297 log = r->connection->log;
2298
2299 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002300
2301 if (r->pool == NULL) {
Igor Sysoev90c08142005-07-25 09:41:38 +00002302 ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002303 return;
2304 }
2305
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002306#if (NGX_STAT_STUB)
Igor Sysoev055951d2005-10-21 19:12:18 +00002307
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002308 if (r->stat_reading) {
Igor Sysoev78452232005-10-12 13:50:36 +00002309 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002310 }
2311
2312 if (r->stat_writing) {
Igor Sysoev78452232005-10-12 13:50:36 +00002313 ngx_atomic_fetch_add(ngx_stat_writing, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002314 }
Igor Sysoev055951d2005-10-21 19:12:18 +00002315
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002316#endif
2317
Igor Sysoev669e3312003-12-22 09:40:48 +00002318 if (error && r->headers_out.status == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002319 r->headers_out.status = error;
2320 }
2321
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002322 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2323
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002324 log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
2325 n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
2326 for (i = 0; i < n; i++) {
2327 log_handler[i](r);
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002328 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00002329
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002330 if (r->connection->timedout) {
2331 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2332
2333 if (clcf->reset_timedout_connection) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002334 linger.l_onoff = 1;
2335 linger.l_linger = 0;
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002336
2337 if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
Igor Sysoev899b44e2005-05-12 14:58:06 +00002338 (const void *) &linger, sizeof(struct linger)) == -1)
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002339 {
2340 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
2341 "setsockopt(SO_LINGER) failed");
2342 }
2343 }
2344 }
2345
Igor Sysoev899b44e2005-05-12 14:58:06 +00002346 /* the various request strings were allocated from r->pool */
Igor Sysoev865c1502003-11-30 20:03:18 +00002347 ctx = log->data;
Igor Sysoev1b735832004-11-11 14:07:14 +00002348 ctx->request = NULL;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002349
Igor Sysoevc83f6832004-06-24 07:53:37 +00002350 r->request_line.len = 0;
2351
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002352 r->connection->destroyed = 1;
2353
Igor Sysoevd581fd52003-05-13 16:02:32 +00002354 ngx_destroy_pool(r->pool);
2355}
2356
2357
Igor Sysoev90c08142005-07-25 09:41:38 +00002358static void
Igor Sysoevc1571722005-03-19 12:38:37 +00002359ngx_http_close_connection(ngx_connection_t *c)
Igor Sysoev6b863e32003-05-12 15:52:24 +00002360{
Igor Sysoev02025fd2005-01-18 13:03:58 +00002361 ngx_pool_t *pool;
2362
Igor Sysoeve04084c2004-01-26 08:52:49 +00002363 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev54498db2004-02-11 17:08:49 +00002364 "close http connection: %d", c->fd);
Igor Sysoev6b863e32003-05-12 15:52:24 +00002365
Igor Sysoevceb99292005-09-06 16:09:32 +00002366#if (NGX_HTTP_SSL)
Igor Sysoev924bd792004-10-11 15:07:03 +00002367
2368 if (c->ssl) {
2369 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002370 c->ssl->handler = ngx_http_close_connection;
Igor Sysoev924bd792004-10-11 15:07:03 +00002371 return;
2372 }
2373 }
2374
2375#endif
2376
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002377#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +00002378 ngx_atomic_fetch_add(ngx_stat_active, -1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002379#endif
2380
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002381 c->destroyed = 1;
2382
Igor Sysoev02025fd2005-01-18 13:03:58 +00002383 pool = c->pool;
2384
Igor Sysoev59cf56c2004-09-07 15:29:22 +00002385 ngx_close_connection(c);
Igor Sysoev02025fd2005-01-18 13:03:58 +00002386
Igor Sysoevc1571722005-03-19 12:38:37 +00002387 ngx_destroy_pool(pool);
Igor Sysoev2ba1ee02002-10-04 17:58:04 +00002388}
2389
2390
Igor Sysoevc1571722005-03-19 12:38:37 +00002391static u_char *
2392ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002393{
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002394 u_char *p;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002395 ngx_http_request_t *r;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002396 ngx_http_log_ctx_t *ctx;
Igor Sysoev7578ec92003-06-02 15:24:30 +00002397
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002398 if (log->action) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002399 p = ngx_snprintf(buf, len, " while %s", log->action);
Igor Sysoev1b735832004-11-11 14:07:14 +00002400 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002401 buf = p;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002402 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002403
Igor Sysoev899b44e2005-05-12 14:58:06 +00002404 ctx = log->data;
2405
Igor Sysoevc04deca2005-03-28 14:43:02 +00002406 p = ngx_snprintf(buf, len, ", client: %V", ctx->client);
Igor Sysoev899b44e2005-05-12 14:58:06 +00002407 len -= p - buf;
Igor Sysoev1b735832004-11-11 14:07:14 +00002408
Igor Sysoevc04deca2005-03-28 14:43:02 +00002409 r = ctx->request;
2410
Igor Sysoev899b44e2005-05-12 14:58:06 +00002411 if (r) {
2412 return r->log_handler(r, p, len);
Igor Sysoev1b735832004-11-11 14:07:14 +00002413 }
2414
Igor Sysoev899b44e2005-05-12 14:58:06 +00002415 return p;
2416}
2417
2418
2419static u_char *
2420ngx_http_log_error_handler(ngx_http_request_t *r, u_char *buf, size_t len)
2421{
2422 u_char *p;
Igor Sysoev1b735832004-11-11 14:07:14 +00002423
Igor Sysoevc04deca2005-03-28 14:43:02 +00002424 if (r->server_name.data) {
2425 p = ngx_snprintf(buf, len, ", server: %V", &r->server_name);
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002426 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002427 buf = p;
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002428 }
2429
Igor Sysoevc04deca2005-03-28 14:43:02 +00002430 if (r->unparsed_uri.data) {
2431 p = ngx_snprintf(buf, len, ", URL: \"%V\"", &r->unparsed_uri);
2432 len -= p - buf;
2433 buf = p;
Igor Sysoev1b735832004-11-11 14:07:14 +00002434
Igor Sysoevc04deca2005-03-28 14:43:02 +00002435 } else {
2436 if (r->request_line.data == NULL && r->request_start) {
2437 for (p = r->request_start; p < r->header_in->last; p++) {
2438 if (*p == CR || *p == LF) {
2439 break;
2440 }
2441 }
2442
2443 r->request_line.len = p - r->request_start;
2444 r->request_line.data = r->request_start;
2445 }
2446
2447 if (r->request_line.len) {
2448 p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
2449 len -= p - buf;
2450 buf = p;
2451 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002452 }
2453
Igor Sysoevc04deca2005-03-28 14:43:02 +00002454 return ngx_http_log_error_info(r, buf, len);
2455}
Igor Sysoev1b735832004-11-11 14:07:14 +00002456
Igor Sysoevc04deca2005-03-28 14:43:02 +00002457
2458u_char *
2459ngx_http_log_error_info(ngx_http_request_t *r, u_char *buf, size_t len)
2460{
2461 u_char *p;
2462
2463 if (r->headers_in.host) {
2464 p = ngx_snprintf(buf, len, ", host: \"%V\"",
2465 &r->headers_in.host->value);
2466 len -= p - buf;
2467 buf = p;
2468 }
2469
2470 if (r->headers_in.referer) {
2471 p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
2472 &r->headers_in.referer->value);
2473 buf = p;
2474 }
2475
2476 return buf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00002477}