blob: 9071ae5a4db6f51824d6b6a079d978f209e81922 [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);
33static ngx_int_t ngx_http_postponed_handler(ngx_http_request_t *r);
Igor Sysoev6b863e32003-05-12 15:52:24 +000034
Igor Sysoev899b44e2005-05-12 14:58:06 +000035static void ngx_http_block_read(ngx_http_request_t *r);
36static void ngx_http_read_discarded_body_handler(ngx_http_request_t *r);
Igor Sysoev2f657222004-06-16 15:32:11 +000037static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r);
Igor Sysoev3a40d482002-09-12 14:42:29 +000038
Igor Sysoevd581fd52003-05-13 16:02:32 +000039static void ngx_http_set_keepalive(ngx_http_request_t *r);
40static void ngx_http_keepalive_handler(ngx_event_t *ev);
41static void ngx_http_set_lingering_close(ngx_http_request_t *r);
42static void ngx_http_lingering_close_handler(ngx_event_t *ev);
Igor Sysoev90c08142005-07-25 09:41:38 +000043static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
44static 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 +000053static void ngx_http_ssl_close_handler(ngx_event_t *ev);
54#endif
55
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000056
Igor Sysoevc04deca2005-03-28 14:43:02 +000057static char *ngx_http_client_errors[] = {
Igor Sysoev0ad17c02002-08-26 15:18:19 +000058
Igor Sysoevc04deca2005-03-28 14:43:02 +000059 /* NGX_HTTP_PARSE_INVALID_METHOD */
60 "client sent invalid method",
Igor Sysoev6a644c62003-03-04 06:33:48 +000061
Igor Sysoevc04deca2005-03-28 14:43:02 +000062 /* NGX_HTTP_PARSE_INVALID_REQUEST */
63 "client sent invalid request",
64
65 /* NGX_HTTP_PARSE_INVALID_09_METHOD */
66 "client sent invalid method in HTTP/0.9 request"
Igor Sysoev016b8522002-08-29 16:59:54 +000067};
68
69
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000070ngx_http_header_t ngx_http_headers_in[] = {
Igor Sysoev899b44e2005-05-12 14:58:06 +000071 { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
Igor Sysoevb145b062005-06-15 18:33:41 +000072 ngx_http_process_unique_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000073
Igor Sysoev899b44e2005-05-12 14:58:06 +000074 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
Igor Sysoevb145b062005-06-15 18:33:41 +000075 ngx_http_process_unique_header_line },
Igor Sysoev899b44e2005-05-12 14:58:06 +000076
77 { ngx_string("If-Modified-Since"),
78 offsetof(ngx_http_headers_in_t, if_modified_since),
79 ngx_http_process_header_line },
80
81 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
82 ngx_http_process_header_line },
83
84 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
85 ngx_http_process_header_line },
86
87 { ngx_string("Content-Length"),
88 offsetof(ngx_http_headers_in_t, content_length),
Igor Sysoevb145b062005-06-15 18:33:41 +000089 ngx_http_process_unique_header_line },
Igor Sysoev899b44e2005-05-12 14:58:06 +000090
91 { ngx_string("Content-Type"),
92 offsetof(ngx_http_headers_in_t, content_type),
93 ngx_http_process_header_line },
94
95 { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
96 ngx_http_process_header_line },
97
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000098#if (NGX_HTTP_GZIP)
99 { ngx_string("Accept-Encoding"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000100 offsetof(ngx_http_headers_in_t, accept_encoding),
101 ngx_http_process_header_line },
102
103 { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
104 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000105#endif
106
107 { ngx_string("Authorization"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000108 offsetof(ngx_http_headers_in_t, authorization),
Igor Sysoevb145b062005-06-15 18:33:41 +0000109 ngx_http_process_unique_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000110
Igor Sysoev899b44e2005-05-12 14:58:06 +0000111 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
112 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000113
114#if (NGX_HTTP_PROXY)
115 { ngx_string("X-Forwarded-For"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000116 offsetof(ngx_http_headers_in_t, x_forwarded_for),
117 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000118#endif
Igor Sysoev02025fd2005-01-18 13:03:58 +0000119
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000120#if (NGX_HTTP_HEADERS)
Igor Sysoev899b44e2005-05-12 14:58:06 +0000121 { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
122 ngx_http_process_header_line },
123
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000124 { ngx_string("Accept-Language"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000125 offsetof(ngx_http_headers_in_t, accept_language),
126 ngx_http_process_header_line },
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000127#endif
128
Igor Sysoev899b44e2005-05-12 14:58:06 +0000129 { ngx_string("Cookie"), 0, ngx_http_process_cookie },
130
131 { ngx_null_string, 0, NULL }
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000132};
133
134
Igor Sysoevc1571722005-03-19 12:38:37 +0000135void
136ngx_http_init_connection(ngx_connection_t *c)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000137{
Igor Sysoev6253ca12003-05-27 12:18:54 +0000138 ngx_event_t *rev;
Igor Sysoev160d7742003-11-19 16:26:41 +0000139 ngx_http_log_ctx_t *ctx;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000140
Igor Sysoevc1571722005-03-19 12:38:37 +0000141 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
142 if (ctx == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000143 ngx_http_close_connection(c);
144 return;
145 }
146
Igor Sysoev1b735832004-11-11 14:07:14 +0000147 ctx->client = &c->addr_text;
Igor Sysoev1b735832004-11-11 14:07:14 +0000148 ctx->request = NULL;
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000149
150 c->log->connection = c->number;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000151 c->log->handler = ngx_http_log_error;
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000152 c->log->data = ctx;
153 c->log->action = "reading client request line";
154
Igor Sysoevc7a2f682004-02-10 16:23:38 +0000155 c->log_error = NGX_ERROR_INFO;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000156
Igor Sysoevdc479b42003-03-20 16:09:44 +0000157 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000158 rev->handler = ngx_http_init_request;
Igor Sysoev2ba1ee02002-10-04 17:58:04 +0000159
Igor Sysoev899b44e2005-05-12 14:58:06 +0000160 /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
Igor Sysoev7af6b162004-02-09 07:46:43 +0000161
Igor Sysoevdc479b42003-03-20 16:09:44 +0000162 if (rev->ready) {
Igor Sysoev0ab91b92004-06-06 19:49:18 +0000163 /* the deferred accept(), rtsig, aio, iocp */
Igor Sysoev709405b2004-03-31 15:26:46 +0000164
Igor Sysoev67f450d2004-06-01 06:04:46 +0000165 if (ngx_accept_mutex) {
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000166
Igor Sysoevc2068d02005-10-19 12:33:58 +0000167 ngx_post_event(rev, &ngx_posted_events);
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000168
169#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000170 ngx_atomic_fetch_add(ngx_stat_reading, 1);
Igor Sysoevd039a2e2005-02-22 14:40:13 +0000171#endif
Igor Sysoev709405b2004-03-31 15:26:46 +0000172 return;
173 }
174
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000175#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000176 ngx_atomic_fetch_add(ngx_stat_reading, 1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000177#endif
178
Igor Sysoev6b863e32003-05-12 15:52:24 +0000179 ngx_http_init_request(rev);
180 return;
Igor Sysoev016b8522002-08-29 16:59:54 +0000181 }
Igor Sysoev73009772003-02-06 17:21:13 +0000182
Igor Sysoev239baac2003-06-11 15:28:34 +0000183 ngx_add_timer(rev, c->listening->post_accept_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000184
Igor Sysoevb5faed22003-10-29 08:30:44 +0000185 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000186 ngx_http_close_connection(c);
187 return;
188 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000189
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000190#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000191 ngx_atomic_fetch_add(ngx_stat_reading, 1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000192#endif
193
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000194}
195
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000196
Igor Sysoevc1571722005-03-19 12:38:37 +0000197static
198void ngx_http_init_request(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000199{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000200 ngx_uint_t i;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000201 socklen_t len;
Igor Sysoev02025fd2005-01-18 13:03:58 +0000202 struct sockaddr_in sin;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000203 ngx_connection_t *c;
204 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000205 ngx_http_in_port_t *in_port;
206 ngx_http_in_addr_t *in_addr;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000207 ngx_http_log_ctx_t *ctx;
Igor Sysoevdd888c42004-09-21 05:38:28 +0000208 ngx_http_connection_t *hc;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000209 ngx_http_server_name_t *server_name;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000210 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev890fc962003-07-20 21:15:59 +0000211 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000212#if (NGX_HTTP_SSL)
213 ngx_http_ssl_srv_conf_t *sscf;
214#endif
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000215
Igor Sysoeva9830112003-05-19 16:39:14 +0000216 c = rev->data;
Igor Sysoeva9830112003-05-19 16:39:14 +0000217
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000218 if (rev->timedout) {
219 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000220
221#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000222 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000223#endif
224
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000225 ngx_http_close_connection(c);
226 return;
227 }
228
Igor Sysoevf7abd722004-09-23 06:32:00 +0000229 hc = c->data;
Igor Sysoevdd888c42004-09-21 05:38:28 +0000230
Igor Sysoev236e0452004-09-23 16:39:34 +0000231 if (hc) {
232
233#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000234 ngx_atomic_fetch_add(ngx_stat_reading, 1);
Igor Sysoev236e0452004-09-23 16:39:34 +0000235#endif
236
237 } else {
Igor Sysoevc1571722005-03-19 12:38:37 +0000238 hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
239 if (hc == NULL) {
Igor Sysoevdd888c42004-09-21 05:38:28 +0000240
241#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000242 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoevdd888c42004-09-21 05:38:28 +0000243#endif
244
245 ngx_http_close_connection(c);
246 return;
247 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000248 }
Igor Sysoevdd888c42004-09-21 05:38:28 +0000249
Igor Sysoevf7abd722004-09-23 06:32:00 +0000250 r = hc->request;
251
252 if (r) {
253 ngx_memzero(r, sizeof(ngx_http_request_t));
254
255 r->pipeline = hc->pipeline;
256
257 if (hc->nbusy) {
258 r->header_in = hc->busy[0];
259 }
260
Igor Sysoevf7abd722004-09-23 06:32:00 +0000261 } else {
Igor Sysoevc1571722005-03-19 12:38:37 +0000262 r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
263 if (r == NULL) {
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000264
265#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000266 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000267#endif
268
Igor Sysoev0a280a32003-10-12 16:49:16 +0000269 ngx_http_close_connection(c);
270 return;
271 }
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000272
Igor Sysoevdd888c42004-09-21 05:38:28 +0000273 hc->request = r;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000274 }
275
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000276#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000277 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000278#endif
279
Igor Sysoevdd888c42004-09-21 05:38:28 +0000280 c->data = r;
281 r->http_connection = hc;
282
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000283 c->sent = 0;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000284 r->signature = NGX_HTTP_MODULE;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000285
Igor Sysoev6253ca12003-05-27 12:18:54 +0000286 /* find the server configuration for the address:port */
287
288 /* AF_INET only */
289
290 in_port = c->servers;
291 in_addr = in_port->addrs.elts;
292
293 r->port = in_port->port;
Igor Sysoev0292cbb2004-09-13 16:18:09 +0000294 r->port_text = &in_port->port_text;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000295
296 i = 0;
297
298 if (in_port->addrs.nelts > 1) {
299
Igor Sysoev239baac2003-06-11 15:28:34 +0000300 /*
Igor Sysoevd00b3652004-08-23 19:09:29 +0000301 * There are several addresses on this port and one of them
302 * is the "*:port" wildcard so getsockname() is needed to determine
Igor Sysoev239baac2003-06-11 15:28:34 +0000303 * the server address.
Igor Sysoevd00b3652004-08-23 19:09:29 +0000304 *
Igor Sysoev239baac2003-06-11 15:28:34 +0000305 * AcceptEx() already gave this address.
306 */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000307
Igor Sysoev1b735832004-11-11 14:07:14 +0000308#if (NGX_WIN32)
Igor Sysoev239baac2003-06-11 15:28:34 +0000309 if (c->local_sockaddr) {
310 r->in_addr =
311 ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000312
Igor Sysoev02025fd2005-01-18 13:03:58 +0000313 } else
Igor Sysoev239baac2003-06-11 15:28:34 +0000314#endif
Igor Sysoev02025fd2005-01-18 13:03:58 +0000315 {
Igor Sysoev239baac2003-06-11 15:28:34 +0000316 len = sizeof(struct sockaddr_in);
Igor Sysoev02025fd2005-01-18 13:03:58 +0000317 if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000318 ngx_connection_error(c, ngx_socket_errno,
319 "getsockname() failed");
Igor Sysoev239baac2003-06-11 15:28:34 +0000320 ngx_http_close_connection(c);
321 return;
322 }
Igor Sysoev10a543a2004-03-16 07:10:12 +0000323
Igor Sysoev02025fd2005-01-18 13:03:58 +0000324 r->in_addr = sin.sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000325 }
326
Igor Sysoev6253ca12003-05-27 12:18:54 +0000327 /* the last in_port->addrs address is "*" */
328
329 for ( /* void */ ; i < in_port->addrs.nelts - 1; i++) {
330 if (in_addr[i].addr == r->in_addr) {
331 break;
332 }
333 }
334
335 } else {
336 r->in_addr = in_addr[0].addr;
337 }
338
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000339 r->virtual_names = &in_addr[i];
Igor Sysoev6253ca12003-05-27 12:18:54 +0000340
341 /* the default server configuration for the address:port */
342 cscf = in_addr[i].core_srv_conf;
343
344 r->main_conf = cscf->ctx->main_conf;
345 r->srv_conf = cscf->ctx->srv_conf;
346 r->loc_conf = cscf->ctx->loc_conf;
347
Igor Sysoev899b44e2005-05-12 14:58:06 +0000348 rev->handler = ngx_http_process_request_line;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000349
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000350#if (NGX_HTTP_SSL)
351
Igor Sysoevf38e0462004-07-16 17:11:43 +0000352 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000353 if (sscf->enable) {
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000354
355 if (c->ssl == NULL) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000356 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
Igor Sysoev02f742b2005-04-08 15:18:55 +0000357 == NGX_ERROR)
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000358 {
359 ngx_http_close_connection(c);
360 return;
361 }
362
Igor Sysoev899b44e2005-05-12 14:58:06 +0000363 rev->handler = ngx_http_ssl_handshake;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000364 }
365
Igor Sysoevd52477f2005-05-16 13:53:20 +0000366 r->main_filter_need_in_memory = 1;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000367 }
368
Igor Sysoev4aa88882004-07-14 20:07:58 +0000369#endif
370
Igor Sysoev6253ca12003-05-27 12:18:54 +0000371 server_name = cscf->server_names.elts;
Igor Sysoev723e6cc2004-10-25 15:29:23 +0000372 r->server_name = server_name->name;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000373
Igor Sysoev890fc962003-07-20 21:15:59 +0000374 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
375 c->log->file = clcf->err_log->file;
Igor Sysoevfff32322004-04-08 15:58:25 +0000376 if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
377 c->log->log_level = clcf->err_log->log_level;
378 }
Igor Sysoev890fc962003-07-20 21:15:59 +0000379
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000380 if (c->buffer == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +0000381 c->buffer = ngx_create_temp_buf(c->pool,
382 cscf->client_header_buffer_size);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000383 if (c->buffer == NULL) {
384 ngx_http_close_connection(c);
385 return;
386 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000387 }
388
Igor Sysoevf7abd722004-09-23 06:32:00 +0000389 if (r->header_in == NULL) {
390 r->header_in = c->buffer;
391 }
392
Igor Sysoevc1571722005-03-19 12:38:37 +0000393 r->pool = ngx_create_pool(cscf->request_pool_size, c->log);
394 if (r->pool == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000395 ngx_http_close_connection(c);
396 return;
397 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000398
Igor Sysoev89690bf2004-03-23 06:01:52 +0000399
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000400 if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
Igor Sysoev899b44e2005-05-12 14:58:06 +0000401 sizeof(ngx_table_elt_t)) == NGX_ERROR)
Igor Sysoev980a9242004-09-05 19:54:02 +0000402 {
403 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
404 ngx_http_close_connection(c);
405 return;
406 }
407
408
Igor Sysoev6b863e32003-05-12 15:52:24 +0000409 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
410 if (r->ctx == NULL) {
411 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
412 ngx_http_close_connection(c);
413 return;
414 }
Igor Sysoeve0268b92002-09-11 15:18:33 +0000415
Igor Sysoevc78c41c2004-07-07 06:15:04 +0000416 c->single_connection = 1;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000417 r->connection = c;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000418
Igor Sysoevf6e1fe32005-10-04 10:38:53 +0000419 r->main = r;
420
Igor Sysoev11d75322005-03-01 15:20:36 +0000421 r->start_time = ngx_time();
422
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000423 r->headers_in.content_length_n = -1;
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000424 r->headers_in.keep_alive_n = -1;
425 r->headers_out.content_length_n = -1;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000426 r->headers_out.last_modified_time = -1;
427
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000428 r->http_state = NGX_HTTP_READING_REQUEST_STATE;
429
Igor Sysoevc04deca2005-03-28 14:43:02 +0000430 ctx = c->log->data;
431 ctx->request = r;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000432 r->log_handler = ngx_http_log_error_handler;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000433
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000434#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000435 ngx_atomic_fetch_add(ngx_stat_reading, 1);
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000436 r->stat_reading = 1;
Igor Sysoev78452232005-10-12 13:50:36 +0000437 ngx_atomic_fetch_add(ngx_stat_requests, 1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000438#endif
439
Igor Sysoev899b44e2005-05-12 14:58:06 +0000440 rev->handler(rev);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000441}
442
443
444#if (NGX_HTTP_SSL)
445
Igor Sysoevc1571722005-03-19 12:38:37 +0000446static void
447ngx_http_ssl_handshake(ngx_event_t *rev)
Igor Sysoevf38e0462004-07-16 17:11:43 +0000448{
Igor Sysoevf38e0462004-07-16 17:11:43 +0000449 u_char buf[1];
Igor Sysoev1b735832004-11-11 14:07:14 +0000450 ssize_t n;
451 ngx_int_t rc;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000452 ngx_connection_t *c;
453 ngx_http_request_t *r;
454
455 c = rev->data;
456 r = c->data;
457
458 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
459 "http check ssl handshake");
460
461 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000462 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
463 c->timedout = 1;
464 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
465 ngx_http_close_connection(c);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000466 return;
467 }
468
469 n = recv(c->fd, buf, 1, MSG_PEEK);
470
471 if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
472 return;
473 }
474
475 if (n == 1) {
476 if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
477 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000478 "https ssl handshake: 0x%02Xd", buf[0]);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000479
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000480 rc = ngx_ssl_handshake(c);
481
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000482 if (rc == NGX_AGAIN) {
483 c->ssl->handler = ngx_http_ssl_handshake_handler;
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000484 return;
485 }
486
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000487 ngx_http_ssl_handshake_handler(c);
488
489 return;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000490
491 } else {
492 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
493 "plain http");
494
495 r->plain_http = 1;
496 }
497 }
498
Igor Sysoev899b44e2005-05-12 14:58:06 +0000499 rev->handler = ngx_http_process_request_line;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000500 ngx_http_process_request_line(rev);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000501}
502
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000503
504static void
505ngx_http_ssl_handshake_handler(ngx_connection_t *c)
506{
507 ngx_http_request_t *r;
508
509 if (c->ssl->handshaked) {
510
511 /*
512 * The majority of browsers do not send the "close notify" alert.
513 * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
514 * and Links. And what is more, MSIE ignores the server's alert.
515 *
516 * Opera and recent Mozilla send the alert.
517 */
518
519 c->ssl->no_wait_shutdown = 1;
520
521 c->read->handler = ngx_http_process_request_line;
522 /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
523
524 ngx_http_process_request_line(c->read);
525
526 return;
527 }
528
529 r = c->data;
530
531 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
532 ngx_http_close_connection(r->connection);
533
534 return;
535}
536
537
Igor Sysoevf38e0462004-07-16 17:11:43 +0000538#endif
539
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000540
Igor Sysoevc1571722005-03-19 12:38:37 +0000541static void
542ngx_http_process_request_line(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000543{
Igor Sysoevf7abd722004-09-23 06:32:00 +0000544 ssize_t n;
Igor Sysoevc3e47462004-09-24 16:12:19 +0000545 ngx_int_t rc, rv;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000546 ngx_connection_t *c;
547 ngx_http_request_t *r;
548 ngx_http_log_ctx_t *ctx;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000549
Igor Sysoeva9830112003-05-19 16:39:14 +0000550 c = rev->data;
551 r = c->data;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000552
Igor Sysoev2b58fbf2003-12-09 15:08:11 +0000553 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
554 "http process request line");
Igor Sysoevdc479b42003-03-20 16:09:44 +0000555
556 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000557 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
558 c->timedout = 1;
559 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
560 ngx_http_close_connection(c);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000561 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000562 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000563
Igor Sysoevf7abd722004-09-23 06:32:00 +0000564 rc = NGX_AGAIN;
Igor Sysoev016b8522002-08-29 16:59:54 +0000565
Igor Sysoevf7abd722004-09-23 06:32:00 +0000566 for ( ;; ) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000567
Igor Sysoevf7abd722004-09-23 06:32:00 +0000568 if (rc == NGX_AGAIN) {
569 n = ngx_http_read_request_header(r);
Igor Sysoevdc479b42003-03-20 16:09:44 +0000570
Igor Sysoevf7abd722004-09-23 06:32:00 +0000571 if (n == NGX_AGAIN || n == NGX_ERROR) {
Igor Sysoev865c1502003-11-30 20:03:18 +0000572 return;
573 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000574 }
575
Igor Sysoevf7abd722004-09-23 06:32:00 +0000576 rc = ngx_http_parse_request_line(r, r->header_in);
Igor Sysoeva9830112003-05-19 16:39:14 +0000577
Igor Sysoevf7abd722004-09-23 06:32:00 +0000578 if (rc == NGX_OK) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000579
Igor Sysoevf7abd722004-09-23 06:32:00 +0000580 /* the request line has been parsed successfully */
Igor Sysoev6b863e32003-05-12 15:52:24 +0000581
Igor Sysoev1b735832004-11-11 14:07:14 +0000582 r->request_line.len = r->request_end - r->request_start;
583 r->request_line.data = r->request_start;
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000584
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000585
Igor Sysoevdc479b42003-03-20 16:09:44 +0000586 if (r->args_start) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000587 r->uri.len = r->args_start - 1 - r->uri_start;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000588 } else {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000589 r->uri.len = r->uri_end - r->uri_start;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000590 }
591
Igor Sysoevf6906042004-11-25 16:17:31 +0000592
Igor Sysoev924bd792004-10-11 15:07:03 +0000593 if (r->complex_uri || r->quoted_uri) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000594
Igor Sysoevc1571722005-03-19 12:38:37 +0000595 r->uri.data = ngx_palloc(r->pool, r->uri.len + 1);
596 if (r->uri.data == NULL) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000597 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
598 ngx_http_close_connection(c);
599 return;
600 }
601
Igor Sysoevf7abd722004-09-23 06:32:00 +0000602 rc = ngx_http_parse_complex_uri(r);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000603
Igor Sysoevc04deca2005-03-28 14:43:02 +0000604 if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) {
605 ngx_log_error(NGX_LOG_INFO, c->log, 0,
606 "client sent invalid request");
607 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000608 return;
609 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000610
Igor Sysoevf7abd722004-09-23 06:32:00 +0000611 } else {
Igor Sysoev1b735832004-11-11 14:07:14 +0000612 r->uri.data = r->uri_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000613 }
614
Igor Sysoevf6906042004-11-25 16:17:31 +0000615
Igor Sysoev1b735832004-11-11 14:07:14 +0000616 r->unparsed_uri.len = r->uri_end - r->uri_start;
617 r->unparsed_uri.data = r->uri_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000618
Igor Sysoevf7abd722004-09-23 06:32:00 +0000619
Igor Sysoev899b44e2005-05-12 14:58:06 +0000620 r->method_name.len = r->method_end - r->request_start + 1;
621 r->method_name.data = r->request_line.data;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000622
Igor Sysoev1b735832004-11-11 14:07:14 +0000623
Igor Sysoev02025fd2005-01-18 13:03:58 +0000624 if (r->http_protocol.data) {
625 r->http_protocol.len = r->request_end - r->http_protocol.data;
626 }
627
628
Igor Sysoevf7abd722004-09-23 06:32:00 +0000629 if (r->uri_ext) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000630 if (r->args_start) {
631 r->exten.len = r->args_start - 1 - r->uri_ext;
632 } else {
633 r->exten.len = r->uri_end - r->uri_ext;
634 }
635
Igor Sysoev1b735832004-11-11 14:07:14 +0000636 r->exten.data = r->uri_ext;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000637 }
638
Igor Sysoev1b735832004-11-11 14:07:14 +0000639
Igor Sysoevf7abd722004-09-23 06:32:00 +0000640 if (r->args_start && r->uri_end > r->args_start) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000641 r->args.len = r->uri_end - r->args_start;
Igor Sysoev1b735832004-11-11 14:07:14 +0000642 r->args.data = r->args_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000643 }
644
Igor Sysoevf7abd722004-09-23 06:32:00 +0000645
646 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000647 "http request line: \"%V\"", &r->request_line);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000648
649 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000650 "http uri: \"%V\"", &r->uri);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000651
652 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000653 "http args: \"%V\"", &r->args);
654
655 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
656 "http exten: \"%V\"", &r->exten);
657
Igor Sysoevf7abd722004-09-23 06:32:00 +0000658 if (r->http_version < NGX_HTTP_VERSION_10) {
Igor Sysoeve5035392005-08-30 10:55:07 +0000659
660 if (rev->timer_set) {
661 ngx_del_timer(rev);
662 }
663
664#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000665 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoeve5035392005-08-30 10:55:07 +0000666 r->stat_reading = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000667 ngx_atomic_fetch_add(ngx_stat_writing, 1);
Igor Sysoeve5035392005-08-30 10:55:07 +0000668 r->stat_writing = 1;
669#endif
670
671 rev->handler = ngx_http_request_handler;
672 c->write->handler = ngx_http_request_handler;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000673 r->read_event_handler = ngx_http_block_read;
Igor Sysoeve5035392005-08-30 10:55:07 +0000674
Igor Sysoevf7abd722004-09-23 06:32:00 +0000675 ngx_http_handler(r);
Igor Sysoeve5035392005-08-30 10:55:07 +0000676
Igor Sysoev6b863e32003-05-12 15:52:24 +0000677 return;
678 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000679
Igor Sysoevdc479b42003-03-20 16:09:44 +0000680
Igor Sysoevf7abd722004-09-23 06:32:00 +0000681 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
Igor Sysoev980a9242004-09-05 19:54:02 +0000682 sizeof(ngx_table_elt_t)) == NGX_ERROR)
Igor Sysoevf7abd722004-09-23 06:32:00 +0000683 {
684 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
685 ngx_http_close_connection(c);
686 return;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000687 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000688
689
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000690 if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,
Igor Sysoevf7abd722004-09-23 06:32:00 +0000691 sizeof(ngx_table_elt_t *)) == NGX_ERROR)
692 {
693 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
694 ngx_http_close_connection(c);
695 return;
696 }
697
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000698 c->log->action = "reading client request headers";
Igor Sysoevf7abd722004-09-23 06:32:00 +0000699
Igor Sysoev899b44e2005-05-12 14:58:06 +0000700 rev->handler = ngx_http_process_request_headers;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000701 ngx_http_process_request_headers(rev);
702
703 return;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000704 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000705
Igor Sysoevc04deca2005-03-28 14:43:02 +0000706 if (rc != NGX_AGAIN) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000707
708 /* there was error while a request line parsing */
709
Igor Sysoevc04deca2005-03-28 14:43:02 +0000710 ngx_log_error(NGX_LOG_INFO, c->log, 0,
711 ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
712 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000713 return;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000714 }
715
Igor Sysoevf7abd722004-09-23 06:32:00 +0000716 /* NGX_AGAIN: a request line parsing is still incomplete */
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000717
Igor Sysoev236e0452004-09-23 16:39:34 +0000718 if (r->header_in->pos == r->header_in->end) {
Igor Sysoeva1c8a922004-01-19 18:09:14 +0000719
Igor Sysoevf7abd722004-09-23 06:32:00 +0000720 rv = ngx_http_alloc_large_header_buffer(r, 1);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000721
Igor Sysoevf7abd722004-09-23 06:32:00 +0000722 if (rv == NGX_ERROR) {
723 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
724 ngx_http_close_connection(c);
725 return;
726 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000727
Igor Sysoevf7abd722004-09-23 06:32:00 +0000728 if (rv == NGX_DECLINED) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000729 ctx = c->log->data;
730 ctx->request = r;
731
732 r->request_line.len = r->header_in->end - r->request_start;
733 r->request_line.data = r->request_start;
734
735 ngx_log_error(NGX_LOG_INFO, c->log, 0,
736 "client sent too long URI");
737 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000738 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000739 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000740 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000741 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000742}
743
Igor Sysoev1af7c822002-09-13 14:47:42 +0000744
Igor Sysoevc1571722005-03-19 12:38:37 +0000745static void
746ngx_http_process_request_headers(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000747{
Igor Sysoev02f742b2005-04-08 15:18:55 +0000748 ssize_t n;
749 ngx_int_t rc, rv;
750 ngx_uint_t key;
751 ngx_str_t header;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000752 ngx_table_elt_t *h;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000753 ngx_connection_t *c;
754 ngx_http_header_t *hh;
755 ngx_http_request_t *r;
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000756 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000757 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000758
Igor Sysoeva9830112003-05-19 16:39:14 +0000759 c = rev->data;
760 r = c->data;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000761
Igor Sysoev865c1502003-11-30 20:03:18 +0000762 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
763 "http process request header line");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000764
Igor Sysoev6b863e32003-05-12 15:52:24 +0000765 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000766 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
767 c->timedout = 1;
768 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
769 ngx_http_close_connection(c);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000770 return;
771 }
772
Igor Sysoev02f742b2005-04-08 15:18:55 +0000773 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000774 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000775 hh = (ngx_http_header_t *) cmcf->headers_in_hash.buckets;
776
Igor Sysoevd581fd52003-05-13 16:02:32 +0000777 rc = NGX_AGAIN;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000778
Igor Sysoev016b8522002-08-29 16:59:54 +0000779 for ( ;; ) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000780
Igor Sysoevd581fd52003-05-13 16:02:32 +0000781 if (rc == NGX_AGAIN) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000782
Igor Sysoev236e0452004-09-23 16:39:34 +0000783 if (r->header_in->pos == r->header_in->end) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000784
785 rv = ngx_http_alloc_large_header_buffer(r, 0);
786
787 if (rv == NGX_ERROR) {
788 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
789 ngx_http_close_connection(c);
790 return;
791 }
792
793 if (rv == NGX_DECLINED) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000794 header.len = r->header_in->end - r->header_name_start;
795 header.data = r->header_name_start;
Igor Sysoev90c08142005-07-25 09:41:38 +0000796
797 if (header.len > NGX_MAX_ERROR_STR - 300) {
798 header.len = NGX_MAX_ERROR_STR - 300;
799 header.data[header.len++] = '.';
800 header.data[header.len++] = '.';
801 header.data[header.len++] = '.';
802 }
803
Igor Sysoevc04deca2005-03-28 14:43:02 +0000804 ngx_log_error(NGX_LOG_INFO, c->log, 0,
805 "client sent too long header line: \"%V\"",
806 &header);
807 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
808 ngx_http_close_connection(c);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000809 return;
810 }
811 }
812
Igor Sysoevd581fd52003-05-13 16:02:32 +0000813 n = ngx_http_read_request_header(r);
814
815 if (n == NGX_AGAIN || n == NGX_ERROR) {
816 return;
817 }
818 }
819
Igor Sysoeve6779222003-10-03 15:50:53 +0000820 rc = ngx_http_parse_header_line(r, r->header_in);
Igor Sysoev016b8522002-08-29 16:59:54 +0000821
Igor Sysoev0dad6292003-03-05 17:30:51 +0000822 if (rc == NGX_OK) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000823
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000824 if (r->invalid_header && cscf->ignore_invalid_headers) {
Igor Sysoev4d656dc2005-03-22 16:02:46 +0000825
826 /* there was error while a header line parsing */
827
828 header.len = r->header_end - r->header_name_start;
829 header.data = r->header_name_start;
830
Igor Sysoevc04deca2005-03-28 14:43:02 +0000831 ngx_log_error(NGX_LOG_INFO, c->log, 0,
832 "client sent invalid header line: \"%V\"",
Igor Sysoev4d656dc2005-03-22 16:02:46 +0000833 &header);
834 continue;
835 }
836
Igor Sysoevd581fd52003-05-13 16:02:32 +0000837 /* a header line has been parsed successfully */
838
Igor Sysoevc1571722005-03-19 12:38:37 +0000839 h = ngx_list_push(&r->headers_in.headers);
840 if (h == NULL) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000841 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
842 ngx_http_close_connection(c);
843 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000844 }
845
Igor Sysoev02f742b2005-04-08 15:18:55 +0000846 h->hash = r->header_hash;
847
Igor Sysoevd581fd52003-05-13 16:02:32 +0000848 h->key.len = r->header_name_end - r->header_name_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000849 h->key.data = r->header_name_start;
850 h->key.data[h->key.len] = '\0';
851
Igor Sysoevd581fd52003-05-13 16:02:32 +0000852 h->value.len = r->header_end - r->header_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000853 h->value.data = r->header_start;
854 h->value.data[h->value.len] = '\0';
Igor Sysoevd581fd52003-05-13 16:02:32 +0000855
Igor Sysoev899b44e2005-05-12 14:58:06 +0000856 key = h->hash % cmcf->headers_in_hash.hash_size;
857
858 if (hh[key].name.len == h->key.len
859 && ngx_strcasecmp(hh[key].name.data, h->key.data) == 0)
Igor Sysoev967fd632004-08-27 15:40:59 +0000860 {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000861 if (hh[key].handler(r, h, hh[key].offset) != NGX_OK) {
Igor Sysoev967fd632004-08-27 15:40:59 +0000862 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000863 }
Igor Sysoevd581fd52003-05-13 16:02:32 +0000864 }
865
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000866 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000867 "http header: \"%V: %V\"",
868 &h->key, &h->value);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000869
Igor Sysoev6253ca12003-05-27 12:18:54 +0000870 continue;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000871 }
Igor Sysoev6253ca12003-05-27 12:18:54 +0000872
Igor Sysoevc04deca2005-03-28 14:43:02 +0000873 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000874
875 /* a whole header has been parsed successfully */
876
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000877 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
878 "http header done");
Igor Sysoev42feecb2002-12-15 06:25:09 +0000879
Igor Sysoev6a12fc92004-12-06 14:45:08 +0000880 r->request_length += r->header_in->pos - r->header_in->start;
881
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000882 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
883
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000884 rc = ngx_http_process_request_header(r);
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000885
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000886 if (rc != NGX_OK) {
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000887 return;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000888 }
889
Igor Sysoev425a42c2003-10-27 16:16:17 +0000890 if (rev->timer_set) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000891 ngx_del_timer(rev);
892 }
893
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000894#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000895 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000896 r->stat_reading = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000897 ngx_atomic_fetch_add(ngx_stat_writing, 1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000898 r->stat_writing = 1;
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000899#endif
900
Igor Sysoev899b44e2005-05-12 14:58:06 +0000901 rev->handler = ngx_http_request_handler;
902 c->write->handler = ngx_http_request_handler;
903 r->read_event_handler = ngx_http_block_read;
904
Igor Sysoevd581fd52003-05-13 16:02:32 +0000905 ngx_http_handler(r);
Igor Sysoeve5035392005-08-30 10:55:07 +0000906
Igor Sysoevd581fd52003-05-13 16:02:32 +0000907 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000908 }
909
Igor Sysoevc04deca2005-03-28 14:43:02 +0000910 if (rc == NGX_AGAIN) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000911
Igor Sysoevc04deca2005-03-28 14:43:02 +0000912 /* a header line parsing is still not complete */
913
914 continue;
915 }
916
917 /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
918
919 header.len = r->header_end - r->header_name_start;
920 header.data = r->header_name_start;
921 ngx_log_error(NGX_LOG_INFO, c->log, 0,
922 "client sent invalid header line: \"%V\\r...\"",
923 &header);
924 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
925 ngx_http_close_connection(c);
926 return;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000927 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000928}
929
Igor Sysoevb0869052002-12-10 18:05:12 +0000930
Igor Sysoevc1571722005-03-19 12:38:37 +0000931static ssize_t
932ngx_http_read_request_header(ngx_http_request_t *r)
Igor Sysoev6b863e32003-05-12 15:52:24 +0000933{
Igor Sysoev187fcd82003-05-23 11:53:01 +0000934 ssize_t n;
935 ngx_event_t *rev;
936 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000937
Igor Sysoev239baac2003-06-11 15:28:34 +0000938 rev = r->connection->read;
939
Igor Sysoev6b863e32003-05-12 15:52:24 +0000940 n = r->header_in->last - r->header_in->pos;
941
942 if (n > 0) {
943 return n;
944 }
945
Igor Sysoevb145b062005-06-15 18:33:41 +0000946 if (rev->ready) {
947 n = r->connection->recv(r->connection, r->header_in->last,
948 r->header_in->end - r->header_in->last);
949 } else {
950 n = NGX_AGAIN;
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000951 }
952
Igor Sysoev6b863e32003-05-12 15:52:24 +0000953 if (n == NGX_AGAIN) {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000954 if (!r->header_timeout_set) {
Igor Sysoevf38e0462004-07-16 17:11:43 +0000955 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev187fcd82003-05-23 11:53:01 +0000956 ngx_add_timer(rev, cscf->client_header_timeout);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000957 r->header_timeout_set = 1;
958 }
959
Igor Sysoevb5faed22003-10-29 08:30:44 +0000960 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000961 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
962 ngx_http_close_connection(r->connection);
963 return NGX_ERROR;
964 }
965
Igor Sysoev6b863e32003-05-12 15:52:24 +0000966 return NGX_AGAIN;
967 }
968
969 if (n == 0) {
970 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
971 "client closed prematurely connection");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000972 }
Igor Sysoev6b863e32003-05-12 15:52:24 +0000973
974 if (n == 0 || n == NGX_ERROR) {
975 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000976 ngx_http_close_connection(r->connection);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000977 return NGX_ERROR;
978 }
979
980 r->header_in->last += n;
981
982 return n;
983}
984
985
Igor Sysoevc1571722005-03-19 12:38:37 +0000986static ngx_int_t
987ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
988 ngx_uint_t request_line)
Igor Sysoev85080d02004-09-22 16:18:21 +0000989{
990 u_char *old, *new;
Igor Sysoev85080d02004-09-22 16:18:21 +0000991 ngx_buf_t *b;
992 ngx_http_connection_t *hc;
993 ngx_http_core_srv_conf_t *cscf;
994
995 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
996 "http alloc large header buffer");
997
Igor Sysoevf7abd722004-09-23 06:32:00 +0000998 if (request_line && r->state == 0) {
999
1000 /* the client fills up the buffer with "\r\n" */
1001
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001002 r->request_length += r->header_in->end - r->header_in->start;
1003
Igor Sysoevf7abd722004-09-23 06:32:00 +00001004 r->header_in->pos = r->header_in->start;
1005 r->header_in->last = r->header_in->start;
1006
1007 return NGX_OK;
1008 }
1009
Igor Sysoev85080d02004-09-22 16:18:21 +00001010 old = request_line ? r->request_start : r->header_name_start;
1011
1012 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1013
Igor Sysoevf7abd722004-09-23 06:32:00 +00001014 if (r->state != 0
1015 && (size_t) (r->header_in->pos - old)
1016 >= cscf->large_client_header_buffers.size)
1017 {
Igor Sysoev85080d02004-09-22 16:18:21 +00001018 return NGX_DECLINED;
1019 }
1020
1021 hc = r->http_connection;
1022
1023 if (hc->nfree) {
1024 b = hc->free[--hc->nfree];
1025
Igor Sysoev236e0452004-09-23 16:39:34 +00001026 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +00001027 "http large header free: %p %uz",
Igor Sysoev236e0452004-09-23 16:39:34 +00001028 b->pos, b->end - b->last);
1029
Igor Sysoevf7abd722004-09-23 06:32:00 +00001030 } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
Igor Sysoev85080d02004-09-22 16:18:21 +00001031
1032 if (hc->busy == NULL) {
1033 hc->busy = ngx_palloc(r->connection->pool,
Igor Sysoevf7abd722004-09-23 06:32:00 +00001034 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev85080d02004-09-22 16:18:21 +00001035 if (hc->busy == NULL) {
1036 return NGX_ERROR;
1037 }
1038 }
1039
1040 b = ngx_create_temp_buf(r->connection->pool,
Igor Sysoevf7abd722004-09-23 06:32:00 +00001041 cscf->large_client_header_buffers.size);
Igor Sysoev85080d02004-09-22 16:18:21 +00001042 if (b == NULL) {
1043 return NGX_ERROR;
1044 }
1045
Igor Sysoev236e0452004-09-23 16:39:34 +00001046 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +00001047 "http large header alloc: %p %uz",
Igor Sysoev236e0452004-09-23 16:39:34 +00001048 b->pos, b->end - b->last);
1049
Igor Sysoev85080d02004-09-22 16:18:21 +00001050 } else {
1051 return NGX_DECLINED;
1052 }
1053
1054 hc->busy[hc->nbusy++] = b;
1055
Igor Sysoevf7abd722004-09-23 06:32:00 +00001056 if (r->state == 0) {
1057 /*
1058 * r->state == 0 means that a header line was parsed successfully
1059 * and we do not need to copy incomplete header line and
1060 * to relocate the parser header pointers
1061 */
1062
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001063 r->request_length += r->header_in->end - r->header_in->start;
1064
Igor Sysoevf7abd722004-09-23 06:32:00 +00001065 r->header_in = b;
1066
1067 return NGX_OK;
1068 }
1069
Igor Sysoev236e0452004-09-23 16:39:34 +00001070 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1071 "http large header copy: %d", r->header_in->pos - old);
1072
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001073 r->request_length += old - r->header_in->start;
1074
Igor Sysoev85080d02004-09-22 16:18:21 +00001075 new = b->start;
1076
Igor Sysoev236e0452004-09-23 16:39:34 +00001077 ngx_memcpy(new, old, r->header_in->pos - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001078
1079 b->pos = new + (r->header_in->pos - old);
Igor Sysoev236e0452004-09-23 16:39:34 +00001080 b->last = new + (r->header_in->pos - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001081
1082 if (request_line) {
1083 r->request_start = new;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001084
1085 if (r->request_end) {
1086 r->request_end = new + (r->request_end - old);
1087 }
1088
1089 r->method_end = new + (r->method_end - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001090
1091 r->uri_start = new + (r->uri_start - old);
1092 r->uri_end = new + (r->uri_end - old);
1093
Igor Sysoevf7abd722004-09-23 06:32:00 +00001094 if (r->schema_start) {
1095 r->schema_start = new + (r->schema_start - old);
1096 r->schema_end = new + (r->schema_end - old);
1097 }
1098
1099 if (r->host_start) {
1100 r->host_start = new + (r->host_start - old);
1101 r->host_end = new + (r->host_end - old);
1102 }
1103
1104 if (r->port_start) {
1105 r->port_start = new + (r->port_start - old);
1106 r->port_end = new + (r->port_end - old);
1107 }
1108
Igor Sysoev85080d02004-09-22 16:18:21 +00001109 if (r->uri_ext) {
1110 r->uri_ext = new + (r->uri_ext - old);
1111 }
1112
1113 if (r->args_start) {
1114 r->args_start = new + (r->args_start - old);
1115 }
1116
1117 } else {
1118 r->header_name_start = new;
1119 r->header_name_end = new + (r->header_name_end - old);
1120 r->header_start = new + (r->header_start - old);
1121 r->header_end = new + (r->header_end - old);
1122 }
1123
1124 r->header_in = b;
1125
1126 return NGX_OK;
1127}
1128
Igor Sysoev85080d02004-09-22 16:18:21 +00001129
Igor Sysoevc1571722005-03-19 12:38:37 +00001130static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001131ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1132 ngx_uint_t offset)
1133{
1134 ngx_table_elt_t **ph;
1135
1136 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1137
1138 if (*ph == NULL) {
1139 *ph = h;
1140 }
1141
1142 return NGX_OK;
1143}
1144
1145
1146static ngx_int_t
Igor Sysoevb145b062005-06-15 18:33:41 +00001147ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1148 ngx_uint_t offset)
1149{
1150 ngx_table_elt_t **ph;
1151
1152 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1153
1154 if (*ph == NULL) {
1155 *ph = h;
1156 return NGX_OK;
1157 }
1158
1159 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1160 "client sent duplicate header line: \"%V: %V\"",
1161 &h->key, &h->value);
1162
1163 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1164
1165 return NGX_ERROR;
1166}
1167
1168
1169static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001170ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
1171 ngx_uint_t offset)
1172{
1173 ngx_table_elt_t **cookie;
1174
1175 cookie = ngx_array_push(&r->headers_in.cookies);
Igor Sysoevb145b062005-06-15 18:33:41 +00001176 if (cookie) {
1177 *cookie = h;
1178 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001179 }
1180
Igor Sysoevb145b062005-06-15 18:33:41 +00001181 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1182 ngx_http_close_connection(r->connection);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001183
Igor Sysoevb145b062005-06-15 18:33:41 +00001184 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001185}
1186
1187
1188static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001189ngx_http_process_request_header(ngx_http_request_t *r)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001190{
Igor Sysoevc04deca2005-03-28 14:43:02 +00001191 size_t len;
1192 u_char *ua, *user_agent, ch;
1193 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001194
1195 if (r->headers_in.host) {
1196 for (len = 0; len < r->headers_in.host->value.len; len++) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001197 ch = r->headers_in.host->value.data[len];
1198
1199 if (ch == ':') {
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001200 break;
1201 }
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001202
1203 r->headers_in.host->value.data[len] = ngx_tolower(ch);
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001204 }
Igor Sysoevc04deca2005-03-28 14:43:02 +00001205
Igor Sysoev899b44e2005-05-12 14:58:06 +00001206 if (r->headers_in.host->value.data[len - 1] == '.') {
1207 len--;
1208 }
1209
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001210 r->headers_in.host_name_len = len;
1211
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001212 if (ngx_http_find_virtual_server(r) != NGX_OK) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001213 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1214 "client sent invalid \"Host\" header");
1215
1216 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1217
1218 if (cscf->restrict_host_names == NGX_HTTP_RESTRICT_HOST_CLOSE) {
1219 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
1220 ngx_http_close_connection(r->connection);
1221 return NGX_ERROR;
1222 }
1223
1224 ngx_http_finalize_request(r, NGX_HTTP_INVALID_HOST);
1225 return NGX_ERROR;
Igor Sysoev3043bfc2004-05-14 16:51:47 +00001226 }
1227
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001228 } else {
1229 if (r->http_version > NGX_HTTP_VERSION_10) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001230 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1231 "client sent HTTP/1.1 request without \"Host\" header");
1232 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1233 return NGX_ERROR;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001234 }
Igor Sysoevc04deca2005-03-28 14:43:02 +00001235
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001236 r->headers_in.host_name_len = 0;
1237 }
1238
1239 if (r->headers_in.content_length) {
1240 r->headers_in.content_length_n =
Igor Sysoevc1571722005-03-19 12:38:37 +00001241 ngx_atosz(r->headers_in.content_length->value.data,
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001242 r->headers_in.content_length->value.len);
1243
1244 if (r->headers_in.content_length_n == NGX_ERROR) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001245 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1246 "client sent invalid \"Content-Length\" header");
1247 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1248 return NGX_ERROR;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001249 }
1250 }
1251
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001252 if (r->method == NGX_HTTP_POST && r->headers_in.content_length_n == -1) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001253 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1254 "client sent POST method without \"Content-Length\" header");
1255 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1256 return NGX_ERROR;
Igor Sysoev6881bfb2004-03-30 06:27:36 +00001257 }
1258
Igor Sysoevf38e0462004-07-16 17:11:43 +00001259 if (r->plain_http) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001260 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1261 "client sent plain HTTP request to HTTPS port");
1262 ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1263 return NGX_ERROR;
Igor Sysoevf38e0462004-07-16 17:11:43 +00001264 }
1265
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001266 if (r->headers_in.connection) {
1267 if (r->headers_in.connection->value.len == 5
1268 && ngx_strcasecmp(r->headers_in.connection->value.data, "close")
Igor Sysoev899b44e2005-05-12 14:58:06 +00001269 == 0)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001270 {
1271 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1272
1273 } else if (r->headers_in.connection->value.len == 10
1274 && ngx_strcasecmp(r->headers_in.connection->value.data,
Igor Sysoev899b44e2005-05-12 14:58:06 +00001275 "keep-alive") == 0)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001276 {
1277 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1278
1279 if (r->headers_in.keep_alive) {
1280 r->headers_in.keep_alive_n =
Igor Sysoevc1571722005-03-19 12:38:37 +00001281 ngx_atotm(r->headers_in.keep_alive->value.data,
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001282 r->headers_in.keep_alive->value.len);
1283 }
1284 }
1285 }
1286
Igor Sysoev2f657222004-06-16 15:32:11 +00001287 if (r->headers_in.user_agent) {
1288
1289 /*
1290 * check some widespread browsers while the headers are still
1291 * in CPU cache
1292 */
1293
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001294 user_agent = r->headers_in.user_agent->value.data;
1295
1296 ua = (u_char *) ngx_strstr(user_agent, "MSIE");
1297
1298 if (ua && ua + 8 < user_agent + r->headers_in.user_agent->value.len) {
1299
Igor Sysoev2f657222004-06-16 15:32:11 +00001300 r->headers_in.msie = 1;
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001301
Igor Sysoev2f657222004-06-16 15:32:11 +00001302 if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') {
1303 r->headers_in.msie4 = 1;
1304 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001305
1306#if 0
1307 /* MSIE ignores the SSL "close notify" alert */
Igor Sysoev42b12b32004-12-02 18:40:46 +00001308 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00001309 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00001310 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001311#endif
Igor Sysoev2f657222004-06-16 15:32:11 +00001312 }
Igor Sysoev85cccfb2004-09-15 16:00:43 +00001313
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001314 if (ngx_strstr(user_agent, "Opera")) {
Igor Sysoev85cccfb2004-09-15 16:00:43 +00001315 r->headers_in.opera = 1;
1316 r->headers_in.msie = 0;
1317 r->headers_in.msie4 = 0;
1318 }
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001319
1320 if (!r->headers_in.msie && !r->headers_in.opera) {
1321
Igor Sysoeva2c81192004-09-19 18:27:00 +00001322 if (ngx_strstr(user_agent, "Gecko/")) {
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001323 r->headers_in.gecko = 1;
1324
1325 } else if (ngx_strstr(user_agent, "Konqueror")) {
1326 r->headers_in.konqueror = 1;
1327 }
1328 }
Igor Sysoev2f657222004-06-16 15:32:11 +00001329 }
1330
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001331 return NGX_OK;
1332}
1333
1334
Igor Sysoevc1571722005-03-19 12:38:37 +00001335static ngx_int_t
1336ngx_http_find_virtual_server(ngx_http_request_t *r)
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001337{
1338 ngx_int_t rc;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001339 ngx_uint_t i, n, key;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001340 ngx_http_server_name_t *name;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001341 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev02f742b2005-04-08 15:18:55 +00001342 ngx_http_core_srv_conf_t *cscf;
1343 ngx_http_core_main_conf_t *cmcf;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001344
1345 if (r->virtual_names->hash) {
1346 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1347
1348 ngx_http_server_names_hash_key(key,
1349 r->headers_in.host->value.data,
1350 r->headers_in.host_name_len,
1351 cmcf->server_names_hash);
1352
1353 name = r->virtual_names->hash[key].elts;
1354 n = r->virtual_names->hash[key].nelts;
1355
1356 } else {
1357 name = r->virtual_names->names.elts;
1358 n = r->virtual_names->names.nelts;
1359 }
1360
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001361 for (i = 0; i < n; i++) {
1362
1363 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1364 "server name: %V", &name[i].name);
1365
1366 if (r->headers_in.host_name_len != name[i].name.len) {
1367 continue;
1368 }
1369
1370 rc = ngx_strncmp(r->headers_in.host->value.data,
1371 name[i].name.data, name[i].name.len);
1372
1373 if (rc == 0) {
1374 r->server_name = name[i].name;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001375 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001376 }
1377
1378 if (rc < 0) {
1379 /* the server names are lexicographically sorted */
1380 break;
1381 }
1382 }
1383
Igor Sysoev899b44e2005-05-12 14:58:06 +00001384 if (r->virtual_names->wildcards.nelts) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001385
1386 name = r->virtual_names->wildcards.elts;
1387 for (i = 0; i < r->virtual_names->wildcards.nelts; i++) {
1388
1389 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1390 "server name: %V", &name[i].name);
1391
1392 if (r->headers_in.host_name_len <= name[i].name.len) {
1393 continue;
1394 }
1395
1396 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1397 "server name: %s",
1398 r->headers_in.host->value.data
1399 + (r->headers_in.host_name_len - name[i].name.len));
1400
1401 if (ngx_strncmp(r->headers_in.host->value.data
1402 + (r->headers_in.host_name_len - name[i].name.len),
1403 name[i].name.data, name[i].name.len) == 0)
1404 {
1405 r->server_name.len = r->headers_in.host_name_len;
1406 r->server_name.data = r->headers_in.host->value.data;
1407
Igor Sysoev899b44e2005-05-12 14:58:06 +00001408 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001409 }
1410 }
1411 }
1412
Igor Sysoev899b44e2005-05-12 14:58:06 +00001413 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001414
Igor Sysoev899b44e2005-05-12 14:58:06 +00001415 if (cscf->restrict_host_names == NGX_HTTP_RESTRICT_HOST_OFF) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001416 return NGX_OK;
1417 }
1418
Igor Sysoev899b44e2005-05-12 14:58:06 +00001419 return NGX_ERROR;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001420
Igor Sysoev899b44e2005-05-12 14:58:06 +00001421found:
1422
1423 r->srv_conf = name[i].core_srv_conf->ctx->srv_conf;
1424 r->loc_conf = name[i].core_srv_conf->ctx->loc_conf;
1425
1426 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1427 r->connection->log->file = clcf->err_log->file;
1428
1429 if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1430 r->connection->log->log_level = clcf->err_log->log_level;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001431 }
1432
1433 return NGX_OK;
1434}
1435
1436
Igor Sysoev899b44e2005-05-12 14:58:06 +00001437static void
1438ngx_http_request_handler(ngx_event_t *ev)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001439{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001440 ngx_connection_t *c;
1441 ngx_http_request_t *r;
1442
1443 c = ev->data;
1444 r = c->data;
1445
1446 if (ev->write) {
1447 r->write_event_handler(r);
1448
1449 } else {
1450 r->read_event_handler(r);
1451 }
1452}
1453
1454
1455void
1456ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1457{
1458 ngx_http_request_t *pr;
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001459 ngx_http_core_loc_conf_t *clcf;
1460
Igor Sysoev899b44e2005-05-12 14:58:06 +00001461 if (rc == NGX_DONE) {
1462 /* r may be already destroyed when rc == NGX_DONE */
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001463 return;
1464 }
1465
Igor Sysoev899b44e2005-05-12 14:58:06 +00001466 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1467 "http finalize request: %d, \"%V\"", rc, &r->uri);
1468
Igor Sysoev3362b8d2005-05-14 18:42:03 +00001469 if (r->parent
1470 && (rc >= NGX_HTTP_SPECIAL_RESPONSE || rc == NGX_HTTP_NO_CONTENT))
1471 {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001472 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
1473 return;
1474 }
1475
1476 if (r->parent || rc == NGX_AGAIN) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001477 if (ngx_http_set_write_handler(r) != NGX_OK) {
1478 return;
1479 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001480 }
1481
1482 r->done = 1;
1483
1484 if (r != r->connection->data) {
Igor Sysoev5192b362005-07-08 14:34:20 +00001485 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1486 "http finalize non-active request: \"%V\"", &r->uri);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001487 return;
1488 }
1489
1490 if (r->parent) {
1491
1492 pr = r->parent;
1493
Igor Sysoev5192b362005-07-08 14:34:20 +00001494 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1495 "http parent request: \"%V\"", &pr->uri);
1496
Igor Sysoev899b44e2005-05-12 14:58:06 +00001497 if (rc != NGX_AGAIN) {
1498 pr->connection->data = pr;
1499 }
1500
1501 if (pr->postponed) {
1502
Igor Sysoev5192b362005-07-08 14:34:20 +00001503 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1504 "http request: \"%V\" has postponed", &pr->uri);
1505
Igor Sysoev899b44e2005-05-12 14:58:06 +00001506 if (rc != NGX_AGAIN && pr->postponed->request == r) {
1507 pr->postponed = pr->postponed->next;
1508
1509 if (pr->postponed == NULL) {
1510 return;
1511 }
1512 }
1513
Igor Sysoev5192b362005-07-08 14:34:20 +00001514 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1515 "http request: \"%V\" still has postponed",
1516 &pr->uri);
1517
Igor Sysoev899b44e2005-05-12 14:58:06 +00001518 if (pr->done) {
1519 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev5192b362005-07-08 14:34:20 +00001520 "http wake parent request: \"%V\"", &pr->uri);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001521
1522 pr->write_event_handler(pr);
1523 }
1524 }
1525
1526 return;
1527 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001528
Igor Sysoev3362b8d2005-05-14 18:42:03 +00001529 if (rc >= NGX_HTTP_SPECIAL_RESPONSE || rc == NGX_HTTP_NO_CONTENT) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001530
Igor Sysoev0a280a32003-10-12 16:49:16 +00001531 if (r->connection->read->timer_set) {
1532 ngx_del_timer(r->connection->read);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001533 }
1534
Igor Sysoev0a280a32003-10-12 16:49:16 +00001535 if (r->connection->write->timer_set) {
1536 ngx_del_timer(r->connection->write);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001537 }
1538
Igor Sysoev5192b362005-07-08 14:34:20 +00001539 if (r->connection->closed) {
Igor Sysoev89690bf2004-03-23 06:01:52 +00001540 ngx_http_close_request(r, 0);
1541 ngx_http_close_connection(r->connection);
1542 return;
1543 }
1544
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001545 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
Igor Sysoev239baac2003-06-11 15:28:34 +00001546
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001547 return;
Igor Sysoev5192b362005-07-08 14:34:20 +00001548 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001549
Igor Sysoev5192b362005-07-08 14:34:20 +00001550 if (rc == NGX_ERROR || r->connection->closed) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001551 ngx_http_close_request(r, 0);
1552 ngx_http_close_connection(r->connection);
1553 return;
Igor Sysoev5192b362005-07-08 14:34:20 +00001554 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001555
Igor Sysoev5192b362005-07-08 14:34:20 +00001556 if (rc == NGX_AGAIN || r->out) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001557 (void) ngx_http_set_write_handler(r);
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001558 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001559 }
1560
Igor Sysoev0a280a32003-10-12 16:49:16 +00001561 if (r->connection->read->timer_set) {
1562 ngx_del_timer(r->connection->read);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001563 }
1564
Igor Sysoev0a280a32003-10-12 16:49:16 +00001565 if (r->connection->write->timer_set) {
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001566 r->connection->write->delayed = 0;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001567 ngx_del_timer(r->connection->write);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001568 }
1569
Igor Sysoev98c1cf12004-07-02 15:54:34 +00001570 if (r->connection->read->pending_eof) {
Igor Sysoev42b12b32004-12-02 18:40:46 +00001571#if (NGX_HAVE_KQUEUE)
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001572 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log,
1573 r->connection->read->kq_errno,
Igor Sysoev7af6b162004-02-09 07:46:43 +00001574 "kevent() reported about an closed connection");
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001575#endif
1576 ngx_http_close_request(r, 0);
1577 ngx_http_close_connection(r->connection);
1578 return;
1579 }
1580
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001581 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1582
Igor Sysoevc5991982004-01-16 06:15:48 +00001583 if (!ngx_terminate
Igor Sysoev3f4685f2004-04-25 20:13:21 +00001584 && !ngx_exiting
Igor Sysoevc5991982004-01-16 06:15:48 +00001585 && r->keepalive != 0
1586 && clcf->keepalive_timeout > 0)
1587 {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001588 ngx_http_set_keepalive(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001589 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001590
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001591 } else if (r->lingering_close && clcf->lingering_timeout > 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001592 ngx_http_set_lingering_close(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001593 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001594 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001595
Igor Sysoevc5991982004-01-16 06:15:48 +00001596 ngx_http_close_request(r, 0);
1597 ngx_http_close_connection(r->connection);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001598}
1599
1600
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001601static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001602ngx_http_set_write_handler(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001603{
Igor Sysoevd581fd52003-05-13 16:02:32 +00001604 ngx_event_t *wev;
Igor Sysoeva9830112003-05-19 16:39:14 +00001605 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001606
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001607 r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
1608
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001609 r->write_event_handler = ngx_http_writer;
1610
Igor Sysoev5192b362005-07-08 14:34:20 +00001611 if (r->connection->closed) {
1612 return NGX_OK;
1613 }
1614
Igor Sysoev899b44e2005-05-12 14:58:06 +00001615 wev = r->connection->write;
1616
Igor Sysoevef066482004-06-21 15:59:32 +00001617 if (wev->ready && wev->delayed) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001618 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001619 }
1620
Igor Sysoev899b44e2005-05-12 14:58:06 +00001621 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001622 if (!wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001623 ngx_add_timer(wev, clcf->send_timeout);
1624 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001625
Igor Sysoev924bd792004-10-11 15:07:03 +00001626 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001627 ngx_http_close_request(r, 0);
1628 ngx_http_close_connection(r->connection);
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001629 return NGX_ERROR;
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001630 }
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001631
1632 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001633}
1634
1635
Igor Sysoev899b44e2005-05-12 14:58:06 +00001636static void
1637ngx_http_writer(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001638{
1639 int rc;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001640 ngx_event_t *wev;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001641 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001642 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001643
Igor Sysoev899b44e2005-05-12 14:58:06 +00001644 c = r->connection;
1645 wev = c->write;
Igor Sysoev160d7742003-11-19 16:26:41 +00001646
Igor Sysoev899b44e2005-05-12 14:58:06 +00001647 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1648 "http writer handler: \"%V\"", &r->uri);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001649
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001650 if (wev->timedout) {
Igor Sysoevef066482004-06-21 15:59:32 +00001651 if (!wev->delayed) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001652 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
1653 "client timed out");
1654 c->timedout = 1;
1655 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
1656 ngx_http_close_connection(c);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001657 return;
1658 }
1659
1660 wev->timedout = 0;
Igor Sysoevef066482004-06-21 15:59:32 +00001661 wev->delayed = 0;
Igor Sysoev73a73b52004-06-20 19:54:15 +00001662
1663 if (!wev->ready) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001664 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001665 ngx_add_timer(wev, clcf->send_timeout);
1666
Igor Sysoev924bd792004-10-11 15:07:03 +00001667 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001668 ngx_http_close_request(r, 0);
1669 ngx_http_close_connection(r->connection);
1670 }
1671
1672 return;
1673 }
1674
1675 } else {
Igor Sysoevef066482004-06-21 15:59:32 +00001676 if (wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001677 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1678 "http writer delayed");
Igor Sysoevef066482004-06-21 15:59:32 +00001679
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001680 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001681
Igor Sysoev924bd792004-10-11 15:07:03 +00001682 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoevef066482004-06-21 15:59:32 +00001683 ngx_http_close_request(r, 0);
1684 ngx_http_close_connection(r->connection);
1685 }
1686
Igor Sysoev73a73b52004-06-20 19:54:15 +00001687 return;
1688 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001689 }
1690
Igor Sysoev899b44e2005-05-12 14:58:06 +00001691 if (r->postponed) {
1692 rc = ngx_http_postponed_handler(r);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001693
Igor Sysoev899b44e2005-05-12 14:58:06 +00001694 if (rc == NGX_DONE) {
1695 /* r may be already destroyed when rc == NGX_DONE */
1696 return;
1697 }
1698
1699 } else {
1700 rc = ngx_http_output_filter(r, NULL);
1701
1702 }
1703
1704 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1705 "http writer output filter: %d, \"%V\"", rc, &r->uri);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001706
1707 if (rc == NGX_AGAIN) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001708 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001709 if (!wev->ready && !wev->delayed) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001710 ngx_add_timer(wev, clcf->send_timeout);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001711 }
1712
Igor Sysoev924bd792004-10-11 15:07:03 +00001713 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001714 ngx_http_close_request(r, 0);
1715 ngx_http_close_connection(r->connection);
1716 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001717
1718 return;
1719 }
1720
Igor Sysoev899b44e2005-05-12 14:58:06 +00001721 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1722 "http writer done: \"%V\"", &r->uri);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001723
Igor Sysoev0a280a32003-10-12 16:49:16 +00001724 ngx_http_finalize_request(r, rc);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001725}
1726
1727
Igor Sysoev899b44e2005-05-12 14:58:06 +00001728static ngx_int_t
1729ngx_http_postponed_handler(ngx_http_request_t *r)
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001730{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001731 ngx_int_t rc;
1732 ngx_http_postponed_request_t *pr;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001733
Igor Sysoev899b44e2005-05-12 14:58:06 +00001734 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1735 "http postpone handler \"%V\"", &r->uri);
1736
1737 pr = r->postponed;
1738
1739 if (pr->request == NULL) {
1740 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1741 "http postponed data \"%V\" %p", &r->uri, pr->out);
1742
1743 rc = ngx_http_output_filter(r, NULL);
1744
1745 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev5192b362005-07-08 14:34:20 +00001746 "http postponed output filter: %d", rc);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001747
Igor Sysoev5192b362005-07-08 14:34:20 +00001748 /*
1749 * we treat NGX_ERROR as NGX_OK, because we need to complete
1750 * all postponed requests
1751 */
Igor Sysoev899b44e2005-05-12 14:58:06 +00001752
1753 pr = r->postponed;
1754
1755 if (pr == NULL) {
Igor Sysoev31eb8c02005-09-23 11:02:22 +00001756
1757 if (rc == NGX_AGAIN) {
1758 return NGX_AGAIN;
1759 }
1760
Igor Sysoev899b44e2005-05-12 14:58:06 +00001761 return NGX_OK;
1762 }
1763 }
1764
1765 r = pr->request;
1766 r->connection->data = r;
1767
1768 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev5192b362005-07-08 14:34:20 +00001769 "http wake child request \"%V\"", &r->uri);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001770
1771 r->write_event_handler(r);
1772
1773 return NGX_DONE;
1774}
1775
1776
1777static void
1778ngx_http_block_read(ngx_http_request_t *r)
1779{
1780 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1781 "http read blocked");
Igor Sysoev42feecb2002-12-15 06:25:09 +00001782
Igor Sysoev73009772003-02-06 17:21:13 +00001783 /* aio does not call this handler */
1784
Igor Sysoev899b44e2005-05-12 14:58:06 +00001785 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
1786 && r->connection->read->active)
1787 {
1788 if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0)
1789 == NGX_ERROR)
1790 {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001791 ngx_http_close_request(r, 0);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001792 ngx_http_close_connection(r->connection);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001793 }
Igor Sysoev73009772003-02-06 17:21:13 +00001794 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001795}
1796
1797
Igor Sysoevc1571722005-03-19 12:38:37 +00001798ngx_int_t
1799ngx_http_discard_body(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001800{
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001801 ssize_t size;
1802 ngx_event_t *rev;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001803
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001804 if (r->main != r) {
Igor Sysoev7b190b42005-06-07 15:56:31 +00001805 return NGX_OK;
1806 }
1807
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001808 rev = r->connection->read;
Igor Sysoev9b25d692003-01-26 21:08:14 +00001809
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001810 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body");
Igor Sysoev9b25d692003-01-26 21:08:14 +00001811
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001812 if (rev->timer_set) {
1813 ngx_del_timer(rev);
Igor Sysoev9b25d692003-01-26 21:08:14 +00001814 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001815
Igor Sysoev0a280a32003-10-12 16:49:16 +00001816 if (r->headers_in.content_length_n <= 0) {
1817 return NGX_OK;
1818 }
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001819
Igor Sysoeve5035392005-08-30 10:55:07 +00001820 r->discard_body = 1;
1821
Igor Sysoev0a280a32003-10-12 16:49:16 +00001822 size = r->header_in->last - r->header_in->pos;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001823
Igor Sysoev0a280a32003-10-12 16:49:16 +00001824 if (size) {
1825 if (r->headers_in.content_length_n > size) {
1826 r->headers_in.content_length_n -= size;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001827
Igor Sysoev0a280a32003-10-12 16:49:16 +00001828 } else {
1829 r->header_in->pos += r->headers_in.content_length_n;
1830 r->headers_in.content_length_n = 0;
1831 return NGX_OK;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001832 }
Igor Sysoev73009772003-02-06 17:21:13 +00001833 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001834
Igor Sysoev899b44e2005-05-12 14:58:06 +00001835 r->read_event_handler = ngx_http_read_discarded_body_handler;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001836
Igor Sysoev899b44e2005-05-12 14:58:06 +00001837 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001838 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1839 }
1840
1841 return ngx_http_read_discarded_body(r);
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001842}
1843
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001844
Igor Sysoevc1571722005-03-19 12:38:37 +00001845static void
Igor Sysoev899b44e2005-05-12 14:58:06 +00001846ngx_http_read_discarded_body_handler(ngx_http_request_t *r)
Igor Sysoev42feecb2002-12-15 06:25:09 +00001847{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001848 ngx_int_t rc;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001849
1850 rc = ngx_http_read_discarded_body(r);
1851
Igor Sysoev0a280a32003-10-12 16:49:16 +00001852 if (rc == NGX_AGAIN) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001853 if (ngx_handle_read_event(r->connection->read, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001854 ngx_http_close_request(r, rc);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001855 ngx_http_close_connection(r->connection);
Igor Sysoev0a280a32003-10-12 16:49:16 +00001856 return;
1857 }
1858 }
1859
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001860 if (rc != NGX_OK) {
1861 ngx_http_close_request(r, rc);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001862 ngx_http_close_connection(r->connection);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001863 }
1864}
1865
1866
Igor Sysoevc1571722005-03-19 12:38:37 +00001867static ngx_int_t
1868ngx_http_read_discarded_body(ngx_http_request_t *r)
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001869{
Igor Sysoevf7abd722004-09-23 06:32:00 +00001870 ssize_t size, n;
1871 u_char buffer[NGX_HTTP_DISCARD_BUFFER_SIZE];
Igor Sysoev42feecb2002-12-15 06:25:09 +00001872
Igor Sysoeve04084c2004-01-26 08:52:49 +00001873 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1874 "http read discarded body");
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001875
Igor Sysoev0a280a32003-10-12 16:49:16 +00001876 if (r->headers_in.content_length_n == 0) {
1877 return NGX_OK;
1878 }
1879
Igor Sysoev42feecb2002-12-15 06:25:09 +00001880
Igor Sysoeva09f08d2003-04-25 14:43:13 +00001881 size = r->headers_in.content_length_n;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001882
Igor Sysoevf7abd722004-09-23 06:32:00 +00001883 if (size > NGX_HTTP_DISCARD_BUFFER_SIZE) {
1884 size = NGX_HTTP_DISCARD_BUFFER_SIZE;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001885 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001886
Igor Sysoevf7abd722004-09-23 06:32:00 +00001887 n = r->connection->recv(r->connection, buffer, size);
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001888
Igor Sysoevdc479b42003-03-20 16:09:44 +00001889 if (n == NGX_ERROR) {
Igor Sysoev89690bf2004-03-23 06:01:52 +00001890
Igor Sysoev5192b362005-07-08 14:34:20 +00001891 r->connection->closed = 1;
Igor Sysoev89690bf2004-03-23 06:01:52 +00001892
1893 /*
Igor Sysoevf7abd722004-09-23 06:32:00 +00001894 * if a client request body is discarded then we already set
Igor Sysoev89690bf2004-03-23 06:01:52 +00001895 * some HTTP response code for client and we can ignore the error
1896 */
1897
1898 return NGX_OK;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001899 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001900
Igor Sysoevdc479b42003-03-20 16:09:44 +00001901 if (n == NGX_AGAIN) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001902 return NGX_AGAIN;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001903 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001904
Igor Sysoeva09f08d2003-04-25 14:43:13 +00001905 r->headers_in.content_length_n -= n;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001906
Igor Sysoev42feecb2002-12-15 06:25:09 +00001907 return NGX_OK;
1908}
1909
1910
Igor Sysoevc1571722005-03-19 12:38:37 +00001911static void
1912ngx_http_set_keepalive(ngx_http_request_t *r)
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001913{
Igor Sysoev924bd792004-10-11 15:07:03 +00001914 int tcp_nodelay;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001915 ngx_int_t i;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001916 ngx_buf_t *b, *f;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001917 ngx_event_t *rev, *wev;
1918 ngx_connection_t *c;
Igor Sysoevdd888c42004-09-21 05:38:28 +00001919 ngx_http_connection_t *hc;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001920 ngx_http_core_srv_conf_t *cscf;
1921 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001922
Igor Sysoev6253ca12003-05-27 12:18:54 +00001923 c = r->connection;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001924 rev = c->read;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001925
Igor Sysoeve04084c2004-01-26 08:52:49 +00001926 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001927
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001928 c->log->action = "closing request";
Igor Sysoevdd888c42004-09-21 05:38:28 +00001929
1930 hc = r->http_connection;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001931 b = r->header_in;
1932
Igor Sysoev236e0452004-09-23 16:39:34 +00001933 if (b->pos < b->last) {
Igor Sysoevf7abd722004-09-23 06:32:00 +00001934
Igor Sysoev236e0452004-09-23 16:39:34 +00001935 /* the pipelined request */
Igor Sysoevf7abd722004-09-23 06:32:00 +00001936
1937 if (b != c->buffer) {
1938
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001939 /*
1940 * If the large header buffers were allocated while the previous
1941 * request processing then we do not use c->buffer for
1942 * the pipelined request (see ngx_http_init_request()).
1943 *
1944 * Now we would move the large header buffers to the free list.
1945 */
Igor Sysoevf7abd722004-09-23 06:32:00 +00001946
1947 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1948
1949 if (hc->free == NULL) {
1950 hc->free = ngx_palloc(c->pool,
1951 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev236e0452004-09-23 16:39:34 +00001952
Igor Sysoevf7abd722004-09-23 06:32:00 +00001953 if (hc->free == NULL) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001954 ngx_http_close_request(r, 0);
Igor Sysoevf7abd722004-09-23 06:32:00 +00001955 ngx_http_close_connection(c);
1956 return;
1957 }
1958 }
1959
1960 for (i = 0; i < hc->nbusy - 1; i++) {
1961 f = hc->busy[i];
1962 hc->free[hc->nfree++] = f;
1963 f->pos = f->start;
1964 f->last = f->start;
1965 }
1966
1967 hc->busy[0] = b;
1968 hc->nbusy = 1;
1969 }
1970 }
1971
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001972 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1973
Igor Sysoevdc479b42003-03-20 16:09:44 +00001974 ngx_http_close_request(r, 0);
Igor Sysoevdd888c42004-09-21 05:38:28 +00001975 c->data = hc;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001976
Igor Sysoevfa73aac2003-05-21 13:28:21 +00001977 ngx_add_timer(rev, clcf->keepalive_timeout);
1978
Igor Sysoev899b44e2005-05-12 14:58:06 +00001979 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001980 ngx_http_close_connection(c);
1981 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00001982 }
1983
Igor Sysoev7b6062a2004-02-12 20:57:10 +00001984 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001985 wev->handler = ngx_http_empty_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001986
Igor Sysoev369145c2004-05-28 15:49:23 +00001987 if (b->pos < b->last) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001988
Igor Sysoeve04084c2004-01-26 08:52:49 +00001989 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
Igor Sysoev6253ca12003-05-27 12:18:54 +00001990
Igor Sysoevdd888c42004-09-21 05:38:28 +00001991 hc->pipeline = 1;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001992 c->log->action = "reading client pipelined request line";
Igor Sysoevd581fd52003-05-13 16:02:32 +00001993 ngx_http_init_request(rev);
1994 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001995 }
1996
Igor Sysoevdd888c42004-09-21 05:38:28 +00001997 hc->pipeline = 0;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001998
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001999 /*
2000 * To keep a memory footprint as small as possible for an idle
2001 * keepalive connection we try to free the ngx_http_request_t and
2002 * c->buffer's memory if they were allocated outside the c->pool.
2003 * The large header buffers are always allocated outside the c->pool and
2004 * are freed too.
2005 */
2006
Igor Sysoev236e0452004-09-23 16:39:34 +00002007 if (ngx_pfree(c->pool, r) == NGX_OK) {
2008 hc->request = NULL;
2009 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00002010
Igor Sysoev236e0452004-09-23 16:39:34 +00002011 b = c->buffer;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002012
Igor Sysoev236e0452004-09-23 16:39:34 +00002013 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002014
2015 /*
2016 * the special note for ngx_http_keepalive_handler() that
2017 * c->buffer's memory was freed
2018 */
2019
Igor Sysoev236e0452004-09-23 16:39:34 +00002020 b->pos = NULL;
2021
2022 } else {
2023 b->pos = b->start;
2024 b->last = b->start;
2025 }
2026
Igor Sysoev1b735832004-11-11 14:07:14 +00002027 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00002028 hc->free, hc->nfree);
2029
2030 if (hc->free) {
2031 for (i = 0; i < hc->nfree; i++) {
2032 ngx_pfree(c->pool, hc->free[i]);
2033 hc->free[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002034 }
2035
Igor Sysoev236e0452004-09-23 16:39:34 +00002036 hc->nfree = 0;
2037 }
2038
Igor Sysoev1b735832004-11-11 14:07:14 +00002039 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00002040 hc->busy, hc->nbusy);
2041
2042 if (hc->busy) {
2043 for (i = 0; i < hc->nbusy; i++) {
2044 ngx_pfree(c->pool, hc->busy[i]);
2045 hc->busy[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002046 }
2047
Igor Sysoev236e0452004-09-23 16:39:34 +00002048 hc->nbusy = 0;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002049 }
2050
Igor Sysoev899b44e2005-05-12 14:58:06 +00002051 rev->handler = ngx_http_keepalive_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00002052
Igor Sysoevd9d0ca12003-11-21 06:30:49 +00002053 if (wev->active) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002054 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoevd9d0ca12003-11-21 06:30:49 +00002055 if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_DISABLE_EVENT)
2056 == NGX_ERROR)
2057 {
2058 ngx_http_close_connection(c);
2059 return;
2060 }
2061
2062 } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
2063 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
2064 ngx_http_close_connection(c);
2065 return;
2066 }
Igor Sysoev3d062ad2003-03-05 06:37:42 +00002067 }
2068 }
2069
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002070 c->log->action = "keepalive";
Igor Sysoev6a644c62003-03-04 06:33:48 +00002071
Igor Sysoev67f450d2004-06-01 06:04:46 +00002072 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
Igor Sysoevc1571722005-03-19 12:38:37 +00002073 if (ngx_tcp_push(c->fd) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00002074 ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
2075 ngx_http_close_connection(c);
2076 return;
Igor Sysoev9cf78302003-06-04 17:28:33 +00002077 }
Igor Sysoev924bd792004-10-11 15:07:03 +00002078
Igor Sysoev67f450d2004-06-01 06:04:46 +00002079 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
Igor Sysoev42b12b32004-12-02 18:40:46 +00002080 tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
Igor Sysoev924bd792004-10-11 15:07:03 +00002081
2082 } else {
Igor Sysoev42b12b32004-12-02 18:40:46 +00002083 tcp_nodelay = 1;
2084 }
Igor Sysoev924bd792004-10-11 15:07:03 +00002085
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002086 if (tcp_nodelay
2087 && clcf->tcp_nodelay
2088 && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
2089 {
Igor Sysoev42b12b32004-12-02 18:40:46 +00002090 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
Igor Sysoev924bd792004-10-11 15:07:03 +00002091
Igor Sysoev42b12b32004-12-02 18:40:46 +00002092 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
2093 (const void *) &tcp_nodelay, sizeof(int)) == -1)
2094 {
2095 ngx_connection_error(c, ngx_socket_errno,
2096 "setsockopt(TCP_NODELAY) failed");
2097 ngx_http_close_connection(c);
2098 return;
Igor Sysoev924bd792004-10-11 15:07:03 +00002099 }
Igor Sysoev42b12b32004-12-02 18:40:46 +00002100
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002101 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
Igor Sysoev9cf78302003-06-04 17:28:33 +00002102 }
2103
Igor Sysoevf7abd722004-09-23 06:32:00 +00002104#if 0
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002105 /* if ngx_http_request_t was freed then we need some other place */
Igor Sysoevc83f6832004-06-24 07:53:37 +00002106 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002107#endif
Igor Sysoevc83f6832004-06-24 07:53:37 +00002108
Igor Sysoevb5faed22003-10-29 08:30:44 +00002109 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002110 ngx_http_keepalive_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00002111 }
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002112}
2113
2114
Igor Sysoevc1571722005-03-19 12:38:37 +00002115static void
2116ngx_http_keepalive_handler(ngx_event_t *rev)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002117{
Igor Sysoevc1571722005-03-19 12:38:37 +00002118 size_t size;
2119 ssize_t n;
2120 ngx_buf_t *b;
2121 ngx_connection_t *c;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002122
Igor Sysoev0ad25372004-07-16 06:33:35 +00002123 c = rev->data;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002124
Igor Sysoeve04084c2004-01-26 08:52:49 +00002125 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
Igor Sysoev1af7c822002-09-13 14:47:42 +00002126
Igor Sysoevdc479b42003-03-20 16:09:44 +00002127 if (rev->timedout) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002128 ngx_http_close_connection(c);
2129 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00002130 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002131
Igor Sysoevf6906042004-11-25 16:17:31 +00002132#if (NGX_HAVE_KQUEUE)
Igor Sysoev236e0452004-09-23 16:39:34 +00002133
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002134 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoev236e0452004-09-23 16:39:34 +00002135 if (rev->pending_eof) {
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002136 c->log->handler = NULL;
Igor Sysoev236e0452004-09-23 16:39:34 +00002137 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
Igor Sysoev1b735832004-11-11 14:07:14 +00002138 "kevent() reported that client %V closed "
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002139 "keepalive connection", &c->addr_text);
Igor Sysoev42b12b32004-12-02 18:40:46 +00002140#if (NGX_HTTP_SSL)
2141 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00002142 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00002143 }
2144#endif
Igor Sysoev236e0452004-09-23 16:39:34 +00002145 ngx_http_close_connection(c);
2146 return;
2147 }
2148 }
2149
2150#endif
2151
Igor Sysoev236e0452004-09-23 16:39:34 +00002152 b = c->buffer;
2153 size = b->end - b->start;
2154
2155 if (b->pos == NULL) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002156
2157 /*
2158 * The c->buffer's memory was freed by ngx_http_set_keepalive().
2159 * However, the c->buffer->start and c->buffer->end were not changed
2160 * to keep the buffer size.
2161 */
2162
Igor Sysoevc1571722005-03-19 12:38:37 +00002163 b->pos = ngx_palloc(c->pool, size);
2164 if (b->pos == NULL) {
Igor Sysoev236e0452004-09-23 16:39:34 +00002165 ngx_http_close_connection(c);
2166 return;
2167 }
2168
2169 b->start = b->pos;
2170 b->last = b->pos;
2171 b->end = b->pos + size;
2172 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00002173
Igor Sysoev0a280a32003-10-12 16:49:16 +00002174 /*
2175 * MSIE closes a keepalive connection with RST flag
2176 * so we ignore ECONNRESET here.
2177 */
Igor Sysoevb7387572003-03-11 20:38:13 +00002178
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002179 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
Igor Sysoevb7387572003-03-11 20:38:13 +00002180 ngx_set_socket_errno(0);
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00002181
Igor Sysoev236e0452004-09-23 16:39:34 +00002182 n = c->recv(c, b->last, size);
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002183 c->log_error = NGX_ERROR_INFO;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002184
Igor Sysoevd581fd52003-05-13 16:02:32 +00002185 if (n == NGX_AGAIN) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002186 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002187 ngx_http_close_connection(c);
2188 }
2189
Igor Sysoevd581fd52003-05-13 16:02:32 +00002190 return;
2191 }
2192
2193 if (n == NGX_ERROR) {
2194 ngx_http_close_connection(c);
2195 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00002196 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002197
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002198 c->log->handler = NULL;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002199
2200 if (n == 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +00002201 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002202 "client %V closed keepalive connection", &c->addr_text);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002203 ngx_http_close_connection(c);
2204 return;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002205 }
2206
Igor Sysoevf7abd722004-09-23 06:32:00 +00002207 b->last += n;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002208
2209 c->log->handler = ngx_http_log_error;
2210 c->log->action = "reading client request line";
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002211
Igor Sysoevd581fd52003-05-13 16:02:32 +00002212 ngx_http_init_request(rev);
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002213}
2214
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002215
Igor Sysoevc1571722005-03-19 12:38:37 +00002216static void
2217ngx_http_set_lingering_close(ngx_http_request_t *r)
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00002218{
Igor Sysoev0a280a32003-10-12 16:49:16 +00002219 ngx_event_t *rev, *wev;
Igor Sysoevb7387572003-03-11 20:38:13 +00002220 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002221 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002222
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002223 c = r->connection;
Igor Sysoev9b25d692003-01-26 21:08:14 +00002224
Igor Sysoev6253ca12003-05-27 12:18:54 +00002225 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002226
Igor Sysoev0a280a32003-10-12 16:49:16 +00002227 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002228 rev->handler = ngx_http_lingering_close_handler;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002229
Igor Sysoev208eed22005-10-07 13:30:52 +00002230 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
Igor Sysoev6253ca12003-05-27 12:18:54 +00002231 ngx_add_timer(rev, clcf->lingering_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +00002232
Igor Sysoev899b44e2005-05-12 14:58:06 +00002233 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00002234 ngx_http_close_request(r, 0);
2235 ngx_http_close_connection(c);
2236 return;
2237 }
2238
2239 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002240 wev->handler = ngx_http_empty_handler;
Igor Sysoev0a280a32003-10-12 16:49:16 +00002241
Igor Sysoevd9d0ca12003-11-21 06:30:49 +00002242 if (wev->active) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002243 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoevd9d0ca12003-11-21 06:30:49 +00002244 if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_DISABLE_EVENT)
2245 == NGX_ERROR)
2246 {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00002247 ngx_http_close_request(r, 0);
Igor Sysoevd9d0ca12003-11-21 06:30:49 +00002248 ngx_http_close_connection(c);
2249 return;
2250 }
2251
2252 } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
2253 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00002254 ngx_http_close_request(r, 0);
Igor Sysoevd9d0ca12003-11-21 06:30:49 +00002255 ngx_http_close_connection(c);
2256 return;
2257 }
Igor Sysoevb7387572003-03-11 20:38:13 +00002258 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002259 }
2260
Igor Sysoevb7387572003-03-11 20:38:13 +00002261 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00002262 ngx_connection_error(c, ngx_socket_errno,
2263 ngx_shutdown_socket_n " failed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002264 ngx_http_close_request(r, 0);
2265 ngx_http_close_connection(c);
2266 return;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002267 }
2268
Igor Sysoevb5faed22003-10-29 08:30:44 +00002269 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002270 ngx_http_lingering_close_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00002271 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002272}
2273
2274
Igor Sysoevc1571722005-03-19 12:38:37 +00002275static void
2276ngx_http_lingering_close_handler(ngx_event_t *rev)
Igor Sysoev42feecb2002-12-15 06:25:09 +00002277{
Igor Sysoevdc479b42003-03-20 16:09:44 +00002278 ssize_t n;
2279 ngx_msec_t timer;
2280 ngx_connection_t *c;
2281 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002282 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002283 u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
Igor Sysoev1af7c822002-09-13 14:47:42 +00002284
Igor Sysoev6253ca12003-05-27 12:18:54 +00002285 c = rev->data;
2286 r = c->data;
Igor Sysoev86de4cb2003-01-30 07:28:09 +00002287
Igor Sysoeve04084c2004-01-26 08:52:49 +00002288 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2289 "http lingering close handler");
Igor Sysoevdc479b42003-03-20 16:09:44 +00002290
2291 if (rev->timedout) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002292 ngx_http_close_request(r, 0);
2293 ngx_http_close_connection(c);
2294 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002295 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002296
Igor Sysoevc0247302004-06-27 18:01:57 +00002297 timer = r->lingering_time - ngx_time();
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002298 if (timer <= 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002299 ngx_http_close_request(r, 0);
2300 ngx_http_close_connection(c);
2301 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002302 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002303
Igor Sysoevdc479b42003-03-20 16:09:44 +00002304 do {
Igor Sysoevf7abd722004-09-23 06:32:00 +00002305 n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002306
Igor Sysoeve04084c2004-01-26 08:52:49 +00002307 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002308
Igor Sysoevdc479b42003-03-20 16:09:44 +00002309 if (n == NGX_ERROR || n == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002310 ngx_http_close_request(r, 0);
2311 ngx_http_close_connection(c);
2312 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002313 }
2314
2315 } while (rev->ready);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002316
Igor Sysoev899b44e2005-05-12 14:58:06 +00002317 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00002318 ngx_http_close_request(r, 0);
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002319 ngx_http_close_connection(c);
2320 return;
2321 }
2322
Igor Sysoevf7abd722004-09-23 06:32:00 +00002323 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2324
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002325 timer *= 1000;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002326
Igor Sysoev6253ca12003-05-27 12:18:54 +00002327 if (timer > clcf->lingering_timeout) {
2328 timer = clcf->lingering_timeout;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002329 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002330
Igor Sysoevdc479b42003-03-20 16:09:44 +00002331 ngx_add_timer(rev, timer);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002332}
2333
Igor Sysoev2b542382002-08-20 14:48:28 +00002334
Igor Sysoevc1571722005-03-19 12:38:37 +00002335void
2336ngx_http_empty_handler(ngx_event_t *wev)
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002337{
Igor Sysoeve04084c2004-01-26 08:52:49 +00002338 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002339
2340 return;
2341}
2342
2343
Igor Sysoev899b44e2005-05-12 14:58:06 +00002344void
2345ngx_http_request_empty_handler(ngx_http_request_t *r)
2346{
2347 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2348 "http requets empty handler");
2349
2350 return;
2351}
2352
2353
Igor Sysoevc1571722005-03-19 12:38:37 +00002354ngx_int_t
2355ngx_http_send_last(ngx_http_request_t *r)
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002356{
Igor Sysoev369145c2004-05-28 15:49:23 +00002357 ngx_buf_t *b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002358 ngx_chain_t out;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002359
Igor Sysoevc1571722005-03-19 12:38:37 +00002360 b = ngx_calloc_buf(r->pool);
2361 if (b == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +00002362 return NGX_ERROR;
2363 }
2364
2365 b->last_buf = 1;
2366 out.buf = b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002367 out.next = NULL;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002368
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002369 return ngx_http_output_filter(r, &out);
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002370}
2371
2372
Igor Sysoevc1571722005-03-19 12:38:37 +00002373void
Igor Sysoev899b44e2005-05-12 14:58:06 +00002374ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error)
Igor Sysoevd581fd52003-05-13 16:02:32 +00002375{
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002376 ngx_log_t *log;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002377 struct linger linger;
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002378 ngx_http_log_ctx_t *ctx;
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002379 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002380
Igor Sysoev865c1502003-11-30 20:03:18 +00002381 log = r->connection->log;
2382
2383 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002384
2385 if (r->pool == NULL) {
Igor Sysoev90c08142005-07-25 09:41:38 +00002386 ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002387 return;
2388 }
2389
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002390#if (NGX_STAT_STUB)
2391 if (r->stat_reading) {
Igor Sysoev78452232005-10-12 13:50:36 +00002392 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002393 }
2394
2395 if (r->stat_writing) {
Igor Sysoev78452232005-10-12 13:50:36 +00002396 ngx_atomic_fetch_add(ngx_stat_writing, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002397 }
2398#endif
2399
Igor Sysoev669e3312003-12-22 09:40:48 +00002400 if (error && r->headers_out.status == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002401 r->headers_out.status = error;
2402 }
2403
2404 ngx_http_log_handler(r);
2405
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002406 if (r->connection->timedout) {
2407 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2408
2409 if (clcf->reset_timedout_connection) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002410 linger.l_onoff = 1;
2411 linger.l_linger = 0;
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002412
2413 if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
Igor Sysoev899b44e2005-05-12 14:58:06 +00002414 (const void *) &linger, sizeof(struct linger)) == -1)
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002415 {
2416 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
2417 "setsockopt(SO_LINGER) failed");
2418 }
2419 }
2420 }
2421
Igor Sysoev899b44e2005-05-12 14:58:06 +00002422 /* the various request strings were allocated from r->pool */
Igor Sysoev865c1502003-11-30 20:03:18 +00002423 ctx = log->data;
Igor Sysoev1b735832004-11-11 14:07:14 +00002424 ctx->request = NULL;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002425
Igor Sysoevc83f6832004-06-24 07:53:37 +00002426 r->request_line.len = 0;
2427
Igor Sysoevd581fd52003-05-13 16:02:32 +00002428 ngx_destroy_pool(r->pool);
2429}
2430
2431
Igor Sysoev90c08142005-07-25 09:41:38 +00002432static void
Igor Sysoevc1571722005-03-19 12:38:37 +00002433ngx_http_close_connection(ngx_connection_t *c)
Igor Sysoev6b863e32003-05-12 15:52:24 +00002434{
Igor Sysoev02025fd2005-01-18 13:03:58 +00002435 ngx_pool_t *pool;
2436
Igor Sysoeve04084c2004-01-26 08:52:49 +00002437 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev54498db2004-02-11 17:08:49 +00002438 "close http connection: %d", c->fd);
Igor Sysoev6b863e32003-05-12 15:52:24 +00002439
Igor Sysoevceb99292005-09-06 16:09:32 +00002440#if (NGX_HTTP_SSL)
Igor Sysoev924bd792004-10-11 15:07:03 +00002441
2442 if (c->ssl) {
2443 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
Igor Sysoev90c08142005-07-25 09:41:38 +00002444 c->read->handler = ngx_http_ssl_close_handler;
2445 c->write->handler = ngx_http_ssl_close_handler;
Igor Sysoev924bd792004-10-11 15:07:03 +00002446 return;
2447 }
2448 }
2449
2450#endif
2451
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002452#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +00002453 ngx_atomic_fetch_add(ngx_stat_active, -1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002454#endif
2455
Igor Sysoev02025fd2005-01-18 13:03:58 +00002456 pool = c->pool;
2457
Igor Sysoev59cf56c2004-09-07 15:29:22 +00002458 ngx_close_connection(c);
Igor Sysoev02025fd2005-01-18 13:03:58 +00002459
Igor Sysoevc1571722005-03-19 12:38:37 +00002460 ngx_destroy_pool(pool);
Igor Sysoev2ba1ee02002-10-04 17:58:04 +00002461}
2462
2463
Igor Sysoevceb99292005-09-06 16:09:32 +00002464#if (NGX_HTTP_SSL)
2465
2466static void
2467ngx_http_ssl_close_handler(ngx_event_t *ev)
2468{
2469 ngx_connection_t *c;
2470
2471 c = ev->data;
2472
2473 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, "http ssl close handler");
2474
2475 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
2476 return;
2477 }
2478
2479 ngx_http_close_connection(c);
2480}
2481
2482#endif
2483
2484
Igor Sysoevc1571722005-03-19 12:38:37 +00002485static u_char *
2486ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002487{
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002488 u_char *p;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002489 ngx_http_request_t *r;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002490 ngx_http_log_ctx_t *ctx;
Igor Sysoev7578ec92003-06-02 15:24:30 +00002491
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002492 if (log->action) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002493 p = ngx_snprintf(buf, len, " while %s", log->action);
Igor Sysoev1b735832004-11-11 14:07:14 +00002494 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002495 buf = p;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002496 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002497
Igor Sysoev899b44e2005-05-12 14:58:06 +00002498 ctx = log->data;
2499
Igor Sysoevc04deca2005-03-28 14:43:02 +00002500 p = ngx_snprintf(buf, len, ", client: %V", ctx->client);
Igor Sysoev899b44e2005-05-12 14:58:06 +00002501 len -= p - buf;
Igor Sysoev1b735832004-11-11 14:07:14 +00002502
Igor Sysoevc04deca2005-03-28 14:43:02 +00002503 r = ctx->request;
2504
Igor Sysoev899b44e2005-05-12 14:58:06 +00002505 if (r) {
2506 return r->log_handler(r, p, len);
Igor Sysoev1b735832004-11-11 14:07:14 +00002507 }
2508
Igor Sysoev899b44e2005-05-12 14:58:06 +00002509 return p;
2510}
2511
2512
2513static u_char *
2514ngx_http_log_error_handler(ngx_http_request_t *r, u_char *buf, size_t len)
2515{
2516 u_char *p;
Igor Sysoev1b735832004-11-11 14:07:14 +00002517
Igor Sysoevc04deca2005-03-28 14:43:02 +00002518 if (r->server_name.data) {
2519 p = ngx_snprintf(buf, len, ", server: %V", &r->server_name);
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002520 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002521 buf = p;
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002522 }
2523
Igor Sysoevc04deca2005-03-28 14:43:02 +00002524 if (r->unparsed_uri.data) {
2525 p = ngx_snprintf(buf, len, ", URL: \"%V\"", &r->unparsed_uri);
2526 len -= p - buf;
2527 buf = p;
Igor Sysoev1b735832004-11-11 14:07:14 +00002528
Igor Sysoevc04deca2005-03-28 14:43:02 +00002529 } else {
2530 if (r->request_line.data == NULL && r->request_start) {
2531 for (p = r->request_start; p < r->header_in->last; p++) {
2532 if (*p == CR || *p == LF) {
2533 break;
2534 }
2535 }
2536
2537 r->request_line.len = p - r->request_start;
2538 r->request_line.data = r->request_start;
2539 }
2540
2541 if (r->request_line.len) {
2542 p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
2543 len -= p - buf;
2544 buf = p;
2545 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002546 }
2547
Igor Sysoevc04deca2005-03-28 14:43:02 +00002548 return ngx_http_log_error_info(r, buf, len);
2549}
Igor Sysoev1b735832004-11-11 14:07:14 +00002550
Igor Sysoevc04deca2005-03-28 14:43:02 +00002551
2552u_char *
2553ngx_http_log_error_info(ngx_http_request_t *r, u_char *buf, size_t len)
2554{
2555 u_char *p;
2556
2557 if (r->headers_in.host) {
2558 p = ngx_snprintf(buf, len, ", host: \"%V\"",
2559 &r->headers_in.host->value);
2560 len -= p - buf;
2561 buf = p;
2562 }
2563
2564 if (r->headers_in.referer) {
2565 p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
2566 &r->headers_in.referer->value);
2567 buf = p;
2568 }
2569
2570 return buf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00002571}