blob: 113c5e894cc8d4d1dcfa94e8b304a735191313d9 [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 Sysoev5fd09312008-05-15 14:44:47 +000024static ngx_int_t ngx_http_process_host(ngx_http_request_t *r,
25 ngx_table_elt_t *h, ngx_uint_t offset);
Igor Sysoevec67b192007-09-09 18:28:49 +000026static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
27 ngx_table_elt_t *h, ngx_uint_t offset);
Igor Sysoevbc5fb292008-05-13 09:18:58 +000028static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r,
29 ngx_table_elt_t *h, ngx_uint_t offset);
Igor Sysoev899b44e2005-05-12 14:58:06 +000030static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r,
31 ngx_table_elt_t *h, ngx_uint_t offset);
32
Igor Sysoev2f657222004-06-16 15:32:11 +000033static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
Igor Sysoev62864d12007-06-04 20:40:03 +000034static void ngx_http_process_request(ngx_http_request_t *r);
Igor Sysoev5fd09312008-05-15 14:44:47 +000035static ssize_t ngx_http_validate_host(u_char *host, size_t len);
36static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r,
37 u_char *host, size_t len);
Igor Sysoev6b863e32003-05-12 15:52:24 +000038
Igor Sysoev899b44e2005-05-12 14:58:06 +000039static void ngx_http_request_handler(ngx_event_t *ev);
Igor Sysoev85ef94b2005-06-23 13:41:06 +000040static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
Igor Sysoev899b44e2005-05-12 14:58:06 +000041static void ngx_http_writer(ngx_http_request_t *r);
Igor Sysoev6b863e32003-05-12 15:52:24 +000042
Igor Sysoev7ab4d9c2007-08-06 15:22:40 +000043static void ngx_http_test_reading(ngx_http_request_t *r);
Igor Sysoevd581fd52003-05-13 16:02:32 +000044static void ngx_http_set_keepalive(ngx_http_request_t *r);
45static void ngx_http_keepalive_handler(ngx_event_t *ev);
46static void ngx_http_set_lingering_close(ngx_http_request_t *r);
47static void ngx_http_lingering_close_handler(ngx_event_t *ev);
Igor Sysoevc2807ec2006-02-16 15:26:46 +000048static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
Igor Sysoev90c08142005-07-25 09:41:38 +000049static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
Igor Sysoev9ac946b2005-10-24 15:09:41 +000050static void ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error);
Igor Sysoev90c08142005-07-25 09:41:38 +000051static void ngx_http_close_connection(ngx_connection_t *c);
Igor Sysoevd581fd52003-05-13 16:02:32 +000052
Igor Sysoeve5a222c2005-01-25 12:27:35 +000053static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
Igor Sysoevbb28b6d2006-07-11 13:20:19 +000054static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
55 ngx_http_request_t *sr, u_char *buf, size_t len);
Igor Sysoev0ad17c02002-08-26 15:18:19 +000056
Igor Sysoevceb99292005-09-06 16:09:32 +000057#if (NGX_HTTP_SSL)
58static void ngx_http_ssl_handshake(ngx_event_t *rev);
Igor Sysoev9fa5a822005-09-30 14:41:25 +000059static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
Igor Sysoevceb99292005-09-06 16:09:32 +000060#endif
61
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000062
Igor Sysoevc04deca2005-03-28 14:43:02 +000063static char *ngx_http_client_errors[] = {
Igor Sysoev0ad17c02002-08-26 15:18:19 +000064
Igor Sysoevc04deca2005-03-28 14:43:02 +000065 /* NGX_HTTP_PARSE_INVALID_METHOD */
66 "client sent invalid method",
Igor Sysoev6a644c62003-03-04 06:33:48 +000067
Igor Sysoevc04deca2005-03-28 14:43:02 +000068 /* NGX_HTTP_PARSE_INVALID_REQUEST */
69 "client sent invalid request",
70
71 /* NGX_HTTP_PARSE_INVALID_09_METHOD */
72 "client sent invalid method in HTTP/0.9 request"
Igor Sysoev016b8522002-08-29 16:59:54 +000073};
74
75
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000076ngx_http_header_t ngx_http_headers_in[] = {
Igor Sysoevcbc7c612008-08-19 19:40:45 +000077 { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
78 ngx_http_process_host },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000079
Igor Sysoevcbc7c612008-08-19 19:40:45 +000080 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
81 ngx_http_process_connection },
Igor Sysoev899b44e2005-05-12 14:58:06 +000082
83 { ngx_string("If-Modified-Since"),
84 offsetof(ngx_http_headers_in_t, if_modified_since),
Igor Sysoev4f62b732007-08-29 15:32:49 +000085 ngx_http_process_unique_header_line },
Igor Sysoev899b44e2005-05-12 14:58:06 +000086
Igor Sysoevcbc7c612008-08-19 19:40:45 +000087 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
88 ngx_http_process_user_agent },
Igor Sysoev899b44e2005-05-12 14:58:06 +000089
90 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
91 ngx_http_process_header_line },
92
93 { ngx_string("Content-Length"),
94 offsetof(ngx_http_headers_in_t, content_length),
Igor Sysoevb145b062005-06-15 18:33:41 +000095 ngx_http_process_unique_header_line },
Igor Sysoev899b44e2005-05-12 14:58:06 +000096
97 { ngx_string("Content-Type"),
98 offsetof(ngx_http_headers_in_t, content_type),
99 ngx_http_process_header_line },
100
101 { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
102 ngx_http_process_header_line },
103
Igor Sysoev6c2f0522007-11-09 15:41:35 +0000104 { ngx_string("If-Range"),
105 offsetof(ngx_http_headers_in_t, if_range),
106 ngx_http_process_unique_header_line },
107
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000108 { ngx_string("Transfer-Encoding"),
109 offsetof(ngx_http_headers_in_t, transfer_encoding),
110 ngx_http_process_header_line },
111
Igor Sysoev1e1f4c82008-06-26 13:00:39 +0000112 { ngx_string("Expect"),
113 offsetof(ngx_http_headers_in_t, expect),
114 ngx_http_process_unique_header_line },
115
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000116#if (NGX_HTTP_GZIP)
117 { ngx_string("Accept-Encoding"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000118 offsetof(ngx_http_headers_in_t, accept_encoding),
119 ngx_http_process_header_line },
120
121 { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
122 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000123#endif
124
125 { ngx_string("Authorization"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000126 offsetof(ngx_http_headers_in_t, authorization),
Igor Sysoevb145b062005-06-15 18:33:41 +0000127 ngx_http_process_unique_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000128
Igor Sysoev899b44e2005-05-12 14:58:06 +0000129 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
130 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000131
Igor Sysoev09c684b2005-11-09 17:25:55 +0000132#if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000133 { ngx_string("X-Forwarded-For"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000134 offsetof(ngx_http_headers_in_t, x_forwarded_for),
135 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000136#endif
Igor Sysoev02025fd2005-01-18 13:03:58 +0000137
Igor Sysoev09c684b2005-11-09 17:25:55 +0000138#if (NGX_HTTP_REALIP)
139 { ngx_string("X-Real-IP"),
140 offsetof(ngx_http_headers_in_t, x_real_ip),
141 ngx_http_process_header_line },
142#endif
143
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000144#if (NGX_HTTP_HEADERS)
Igor Sysoev899b44e2005-05-12 14:58:06 +0000145 { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
146 ngx_http_process_header_line },
147
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000148 { ngx_string("Accept-Language"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000149 offsetof(ngx_http_headers_in_t, accept_language),
150 ngx_http_process_header_line },
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000151#endif
152
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000153#if (NGX_HTTP_DAV)
154 { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
155 ngx_http_process_header_line },
156
157 { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
158 ngx_http_process_header_line },
Igor Sysoevda173ab2006-08-30 10:39:17 +0000159
Igor Sysoev56331ba2007-01-18 21:11:23 +0000160 { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),
161 ngx_http_process_header_line },
162
Igor Sysoevda173ab2006-08-30 10:39:17 +0000163 { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
164 ngx_http_process_header_line },
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000165#endif
166
Igor Sysoev899b44e2005-05-12 14:58:06 +0000167 { ngx_string("Cookie"), 0, ngx_http_process_cookie },
168
169 { ngx_null_string, 0, NULL }
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000170};
171
172
Igor Sysoevc1571722005-03-19 12:38:37 +0000173void
174ngx_http_init_connection(ngx_connection_t *c)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000175{
Igor Sysoev6253ca12003-05-27 12:18:54 +0000176 ngx_event_t *rev;
Igor Sysoev160d7742003-11-19 16:26:41 +0000177 ngx_http_log_ctx_t *ctx;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000178
Igor Sysoevc1571722005-03-19 12:38:37 +0000179 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
180 if (ctx == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000181 ngx_http_close_connection(c);
182 return;
183 }
184
Igor Sysoevcc595672007-12-30 08:01:50 +0000185 ctx->connection = c;
Igor Sysoev1b735832004-11-11 14:07:14 +0000186 ctx->request = NULL;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +0000187 ctx->current_request = NULL;
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000188
189 c->log->connection = c->number;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000190 c->log->handler = ngx_http_log_error;
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000191 c->log->data = ctx;
192 c->log->action = "reading client request line";
193
Igor Sysoevc7a2f682004-02-10 16:23:38 +0000194 c->log_error = NGX_ERROR_INFO;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000195
Igor Sysoevdc479b42003-03-20 16:09:44 +0000196 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000197 rev->handler = ngx_http_init_request;
Igor Sysoev9ac946b2005-10-24 15:09:41 +0000198 c->write->handler = ngx_http_empty_handler;
Igor Sysoev7af6b162004-02-09 07:46:43 +0000199
Igor Sysoev055951d2005-10-21 19:12:18 +0000200#if (NGX_STAT_STUB)
201 ngx_atomic_fetch_add(ngx_stat_reading, 1);
202#endif
203
Igor Sysoevdc479b42003-03-20 16:09:44 +0000204 if (rev->ready) {
Igor Sysoev0ab91b92004-06-06 19:49:18 +0000205 /* the deferred accept(), rtsig, aio, iocp */
Igor Sysoev709405b2004-03-31 15:26:46 +0000206
Igor Sysoevffe71442006-02-08 15:33:12 +0000207 if (ngx_use_accept_mutex) {
Igor Sysoevc2068d02005-10-19 12:33:58 +0000208 ngx_post_event(rev, &ngx_posted_events);
Igor Sysoev709405b2004-03-31 15:26:46 +0000209 return;
210 }
211
Igor Sysoev6b863e32003-05-12 15:52:24 +0000212 ngx_http_init_request(rev);
213 return;
Igor Sysoev016b8522002-08-29 16:59:54 +0000214 }
Igor Sysoev73009772003-02-06 17:21:13 +0000215
Igor Sysoev239baac2003-06-11 15:28:34 +0000216 ngx_add_timer(rev, c->listening->post_accept_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000217
Igor Sysoevb5faed22003-10-29 08:30:44 +0000218 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev055951d2005-10-21 19:12:18 +0000219#if (NGX_STAT_STUB)
220 ngx_atomic_fetch_add(ngx_stat_reading, -1);
221#endif
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000222 ngx_http_close_connection(c);
223 return;
224 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000225}
226
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000227
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000228static void
229ngx_http_init_request(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000230{
Igor Sysoevb4ccb9f2007-04-21 07:50:19 +0000231 ngx_time_t *tp;
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000232 ngx_uint_t i;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000233 ngx_connection_t *c;
234 ngx_http_request_t *r;
Igor Sysoev305a9d82005-12-26 17:07:48 +0000235 ngx_http_in_port_t *hip;
236 ngx_http_in_addr_t *hia;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000237 ngx_http_log_ctx_t *ctx;
238 ngx_http_connection_t *hc;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000239 ngx_http_core_srv_conf_t *cscf;
240 ngx_http_core_loc_conf_t *clcf;
241 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000242
Igor Sysoev055951d2005-10-21 19:12:18 +0000243#if (NGX_STAT_STUB)
244 ngx_atomic_fetch_add(ngx_stat_reading, -1);
245#endif
246
Igor Sysoeva9830112003-05-19 16:39:14 +0000247 c = rev->data;
Igor Sysoeva9830112003-05-19 16:39:14 +0000248
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000249 if (rev->timedout) {
250 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000251
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000252 ngx_http_close_connection(c);
253 return;
254 }
255
Igor Sysoevf7abd722004-09-23 06:32:00 +0000256 hc = c->data;
Igor Sysoevdd888c42004-09-21 05:38:28 +0000257
Igor Sysoev055951d2005-10-21 19:12:18 +0000258 if (hc == NULL) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000259 hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
260 if (hc == NULL) {
Igor Sysoevdd888c42004-09-21 05:38:28 +0000261 ngx_http_close_connection(c);
262 return;
263 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000264 }
Igor Sysoevdd888c42004-09-21 05:38:28 +0000265
Igor Sysoevf7abd722004-09-23 06:32:00 +0000266 r = hc->request;
267
268 if (r) {
269 ngx_memzero(r, sizeof(ngx_http_request_t));
270
271 r->pipeline = hc->pipeline;
272
273 if (hc->nbusy) {
274 r->header_in = hc->busy[0];
275 }
276
Igor Sysoevf7abd722004-09-23 06:32:00 +0000277 } else {
Igor Sysoevc1571722005-03-19 12:38:37 +0000278 r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
279 if (r == NULL) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000280 ngx_http_close_connection(c);
281 return;
282 }
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000283
Igor Sysoevdd888c42004-09-21 05:38:28 +0000284 hc->request = r;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000285 }
286
Igor Sysoevdd888c42004-09-21 05:38:28 +0000287 c->data = r;
288 r->http_connection = hc;
289
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000290 c->sent = 0;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000291 r->signature = NGX_HTTP_MODULE;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000292
Igor Sysoev6253ca12003-05-27 12:18:54 +0000293 /* find the server configuration for the address:port */
294
295 /* AF_INET only */
296
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000297 hip = c->listening->servers;
Igor Sysoev305a9d82005-12-26 17:07:48 +0000298 hia = hip->addrs;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000299
Igor Sysoev305a9d82005-12-26 17:07:48 +0000300 r->port = hip->port;
301 r->port_text = &hip->port_text;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000302
303 i = 0;
304
Igor Sysoevc7a9b7a2007-12-29 16:00:34 +0000305 r->connection = c;
306
Igor Sysoev305a9d82005-12-26 17:07:48 +0000307 if (hip->naddrs > 1) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000308
Igor Sysoev239baac2003-06-11 15:28:34 +0000309 /*
Igor Sysoevd00b3652004-08-23 19:09:29 +0000310 * There are several addresses on this port and one of them
311 * is the "*:port" wildcard so getsockname() is needed to determine
Igor Sysoev239baac2003-06-11 15:28:34 +0000312 * the server address.
Igor Sysoevd00b3652004-08-23 19:09:29 +0000313 *
Igor Sysoevc7a9b7a2007-12-29 16:00:34 +0000314 * AcceptEx() already has given this address.
Igor Sysoev239baac2003-06-11 15:28:34 +0000315 */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000316
Igor Sysoev1b735832004-11-11 14:07:14 +0000317#if (NGX_WIN32)
Igor Sysoev239baac2003-06-11 15:28:34 +0000318 if (c->local_sockaddr) {
319 r->in_addr =
320 ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000321
Igor Sysoev02025fd2005-01-18 13:03:58 +0000322 } else
Igor Sysoev239baac2003-06-11 15:28:34 +0000323#endif
Igor Sysoev02025fd2005-01-18 13:03:58 +0000324 {
Igor Sysoevc7a9b7a2007-12-29 16:00:34 +0000325 if (ngx_http_server_addr(r, NULL) != NGX_OK) {
Igor Sysoev239baac2003-06-11 15:28:34 +0000326 ngx_http_close_connection(c);
327 return;
328 }
Igor Sysoev6253ca12003-05-27 12:18:54 +0000329 }
330
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000331 /* the last address is "*" */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000332
Igor Sysoev305a9d82005-12-26 17:07:48 +0000333 for ( /* void */ ; i < hip->naddrs - 1; i++) {
334 if (hia[i].addr == r->in_addr) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000335 break;
336 }
337 }
338
339 } else {
Igor Sysoev305a9d82005-12-26 17:07:48 +0000340 r->in_addr = hia[0].addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000341 }
342
Igor Sysoev305a9d82005-12-26 17:07:48 +0000343 r->virtual_names = hia[i].virtual_names;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000344
345 /* the default server configuration for the address:port */
Igor Sysoev305a9d82005-12-26 17:07:48 +0000346 cscf = hia[i].core_srv_conf;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000347
348 r->main_conf = cscf->ctx->main_conf;
349 r->srv_conf = cscf->ctx->srv_conf;
350 r->loc_conf = cscf->ctx->loc_conf;
351
Igor Sysoev899b44e2005-05-12 14:58:06 +0000352 rev->handler = ngx_http_process_request_line;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000353
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000354#if (NGX_HTTP_SSL)
355
Igor Sysoev86ef6aa2007-12-10 12:09:51 +0000356 {
357 ngx_http_ssl_srv_conf_t *sscf;
358
Igor Sysoevf38e0462004-07-16 17:11:43 +0000359 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
Igor Sysoevf100c782008-09-01 14:19:01 +0000360 if (sscf->enable || hia[i].ssl) {
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000361
362 if (c->ssl == NULL) {
Igor Sysoevf100c782008-09-01 14:19:01 +0000363
364 c->log->action = "SSL handshaking";
365
366 if (hia[i].ssl && sscf->ssl.ctx == NULL) {
367 ngx_log_error(NGX_LOG_ERR, c->log, 0,
368 "no \"ssl_certificate\" is defined "
369 "in server listening on SSL port");
370 ngx_http_close_connection(c);
371 return;
372 }
373
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000374 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
Igor Sysoev02f742b2005-04-08 15:18:55 +0000375 == NGX_ERROR)
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000376 {
377 ngx_http_close_connection(c);
378 return;
379 }
380
Igor Sysoev899b44e2005-05-12 14:58:06 +0000381 rev->handler = ngx_http_ssl_handshake;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000382 }
383
Igor Sysoevd52477f2005-05-16 13:53:20 +0000384 r->main_filter_need_in_memory = 1;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000385 }
Igor Sysoev86ef6aa2007-12-10 12:09:51 +0000386 }
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000387
Igor Sysoev4aa88882004-07-14 20:07:58 +0000388#endif
389
Igor Sysoev890fc962003-07-20 21:15:59 +0000390 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
391 c->log->file = clcf->err_log->file;
Igor Sysoevfff32322004-04-08 15:58:25 +0000392 if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
393 c->log->log_level = clcf->err_log->log_level;
394 }
Igor Sysoev890fc962003-07-20 21:15:59 +0000395
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000396 if (c->buffer == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +0000397 c->buffer = ngx_create_temp_buf(c->pool,
398 cscf->client_header_buffer_size);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000399 if (c->buffer == NULL) {
400 ngx_http_close_connection(c);
401 return;
402 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000403 }
404
Igor Sysoevf7abd722004-09-23 06:32:00 +0000405 if (r->header_in == NULL) {
406 r->header_in = c->buffer;
407 }
408
Igor Sysoevc1571722005-03-19 12:38:37 +0000409 r->pool = ngx_create_pool(cscf->request_pool_size, c->log);
410 if (r->pool == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000411 ngx_http_close_connection(c);
412 return;
413 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000414
Igor Sysoev89690bf2004-03-23 06:01:52 +0000415
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000416 if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000417 sizeof(ngx_table_elt_t))
418 == NGX_ERROR)
Igor Sysoev980a9242004-09-05 19:54:02 +0000419 {
420 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev980a9242004-09-05 19:54:02 +0000421 return;
422 }
423
Igor Sysoev6b863e32003-05-12 15:52:24 +0000424 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
425 if (r->ctx == NULL) {
426 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000427 return;
428 }
Igor Sysoeve0268b92002-09-11 15:18:33 +0000429
Igor Sysoev09c684b2005-11-09 17:25:55 +0000430 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
431
432 r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
433 * sizeof(ngx_http_variable_value_t));
434 if (r->variables == NULL) {
435 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
436 return;
437 }
438
Igor Sysoevc78c41c2004-07-07 06:15:04 +0000439 c->single_connection = 1;
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000440 c->destroyed = 0;
441
Igor Sysoevf6e1fe32005-10-04 10:38:53 +0000442 r->main = r;
443
Igor Sysoevb4ccb9f2007-04-21 07:50:19 +0000444 tp = ngx_timeofday();
445 r->start_sec = tp->sec;
446 r->start_msec = tp->msec;
Igor Sysoev11d75322005-03-01 15:20:36 +0000447
Igor Sysoev94e32ce2006-04-07 14:08:04 +0000448 r->method = NGX_HTTP_UNKNOWN;
449
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000450 r->headers_in.content_length_n = -1;
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000451 r->headers_in.keep_alive_n = -1;
452 r->headers_out.content_length_n = -1;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000453 r->headers_out.last_modified_time = -1;
454
Igor Sysoevef316432006-08-16 13:09:33 +0000455 r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
456 r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;
457
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000458 r->http_state = NGX_HTTP_READING_REQUEST_STATE;
459
Igor Sysoevc04deca2005-03-28 14:43:02 +0000460 ctx = c->log->data;
461 ctx->request = r;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +0000462 ctx->current_request = r;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000463 r->log_handler = ngx_http_log_error_handler;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000464
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000465#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000466 ngx_atomic_fetch_add(ngx_stat_reading, 1);
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000467 r->stat_reading = 1;
Igor Sysoev78452232005-10-12 13:50:36 +0000468 ngx_atomic_fetch_add(ngx_stat_requests, 1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000469#endif
470
Igor Sysoev899b44e2005-05-12 14:58:06 +0000471 rev->handler(rev);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000472}
473
474
475#if (NGX_HTTP_SSL)
476
Igor Sysoevc1571722005-03-19 12:38:37 +0000477static void
478ngx_http_ssl_handshake(ngx_event_t *rev)
Igor Sysoevf38e0462004-07-16 17:11:43 +0000479{
Igor Sysoevf38e0462004-07-16 17:11:43 +0000480 u_char buf[1];
Igor Sysoev1b735832004-11-11 14:07:14 +0000481 ssize_t n;
482 ngx_int_t rc;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000483 ngx_connection_t *c;
484 ngx_http_request_t *r;
485
486 c = rev->data;
487 r = c->data;
488
489 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
490 "http check ssl handshake");
491
492 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000493 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
494 c->timedout = 1;
495 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000496 return;
497 }
498
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000499 n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000500
501 if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
Igor Sysoevbd68d512008-01-08 20:51:06 +0000502
503 if (!rev->timer_set) {
504 ngx_add_timer(rev, c->listening->post_accept_timeout);
505 }
506
Igor Sysoev57b088d2008-01-09 08:21:57 +0000507 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
508 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
509 }
510
Igor Sysoevf38e0462004-07-16 17:11:43 +0000511 return;
512 }
513
514 if (n == 1) {
515 if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
516 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000517 "https ssl handshake: 0x%02Xd", buf[0]);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000518
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000519 rc = ngx_ssl_handshake(c);
520
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000521 if (rc == NGX_AGAIN) {
Igor Sysoev7b8ed422008-01-04 09:32:12 +0000522
523 if (!rev->timer_set) {
524 ngx_add_timer(rev, c->listening->post_accept_timeout);
525 }
526
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000527 c->ssl->handler = ngx_http_ssl_handshake_handler;
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000528 return;
529 }
530
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000531 ngx_http_ssl_handshake_handler(c);
532
533 return;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000534
535 } else {
536 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
537 "plain http");
538
539 r->plain_http = 1;
540 }
541 }
542
Igor Sysoevf100c782008-09-01 14:19:01 +0000543 c->log->action = "reading client request line";
544
Igor Sysoev899b44e2005-05-12 14:58:06 +0000545 rev->handler = ngx_http_process_request_line;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000546 ngx_http_process_request_line(rev);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000547}
548
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000549
550static void
551ngx_http_ssl_handshake_handler(ngx_connection_t *c)
552{
553 ngx_http_request_t *r;
554
555 if (c->ssl->handshaked) {
556
557 /*
558 * The majority of browsers do not send the "close notify" alert.
559 * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
560 * and Links. And what is more, MSIE ignores the server's alert.
561 *
562 * Opera and recent Mozilla send the alert.
563 */
564
565 c->ssl->no_wait_shutdown = 1;
566
567 c->read->handler = ngx_http_process_request_line;
568 /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
569
570 ngx_http_process_request_line(c->read);
571
572 return;
573 }
574
575 r = c->data;
576
577 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000578
579 return;
580}
581
Igor Sysoeve60303c2007-05-29 15:21:09 +0000582#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
583
584int
585ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
586{
Igor Sysoevb29426d2008-08-21 12:56:10 +0000587 size_t len;
Igor Sysoeve60303c2007-05-29 15:21:09 +0000588 const char *servername;
589 ngx_connection_t *c;
590 ngx_http_request_t *r;
591 ngx_http_ssl_srv_conf_t *sscf;
592
593 servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
594
595 if (servername == NULL) {
596 return SSL_TLSEXT_ERR_NOACK;
597 }
598
599 c = ngx_ssl_get_connection(ssl_conn);
600
601 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
602 "SSL server name: \"%s\"", servername);
603
Igor Sysoevb29426d2008-08-21 12:56:10 +0000604 len = ngx_strlen(servername);
605
606 if (len == 0) {
607 return SSL_TLSEXT_ERR_NOACK;
608 }
609
Igor Sysoeve60303c2007-05-29 15:21:09 +0000610 r = c->data;
611
Igor Sysoevb29426d2008-08-21 12:56:10 +0000612 if (ngx_http_find_virtual_server(r, (u_char *) servername, len) != NGX_OK) {
Igor Sysoeve60303c2007-05-29 15:21:09 +0000613 return SSL_TLSEXT_ERR_NOACK;
614 }
615
Igor Sysoeve60303c2007-05-29 15:21:09 +0000616 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
617
618 SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
619
620 return SSL_TLSEXT_ERR_OK;
621}
622
623#endif
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000624
Igor Sysoevf38e0462004-07-16 17:11:43 +0000625#endif
626
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000627
Igor Sysoevc1571722005-03-19 12:38:37 +0000628static void
629ngx_http_process_request_line(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000630{
Igor Sysoev8decab32007-10-18 11:36:58 +0000631 ssize_t n;
632 ngx_int_t rc, rv;
633 ngx_connection_t *c;
634 ngx_http_request_t *r;
635 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000636
Igor Sysoeva9830112003-05-19 16:39:14 +0000637 c = rev->data;
638 r = c->data;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000639
Igor Sysoev2b58fbf2003-12-09 15:08:11 +0000640 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
641 "http process request line");
Igor Sysoevdc479b42003-03-20 16:09:44 +0000642
643 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000644 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
645 c->timedout = 1;
646 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000647 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000648 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000649
Igor Sysoevf7abd722004-09-23 06:32:00 +0000650 rc = NGX_AGAIN;
Igor Sysoev016b8522002-08-29 16:59:54 +0000651
Igor Sysoevf7abd722004-09-23 06:32:00 +0000652 for ( ;; ) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000653
Igor Sysoevf7abd722004-09-23 06:32:00 +0000654 if (rc == NGX_AGAIN) {
655 n = ngx_http_read_request_header(r);
Igor Sysoevdc479b42003-03-20 16:09:44 +0000656
Igor Sysoevf7abd722004-09-23 06:32:00 +0000657 if (n == NGX_AGAIN || n == NGX_ERROR) {
Igor Sysoev865c1502003-11-30 20:03:18 +0000658 return;
659 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000660 }
661
Igor Sysoevf7abd722004-09-23 06:32:00 +0000662 rc = ngx_http_parse_request_line(r, r->header_in);
Igor Sysoeva9830112003-05-19 16:39:14 +0000663
Igor Sysoevf7abd722004-09-23 06:32:00 +0000664 if (rc == NGX_OK) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000665
Igor Sysoevf7abd722004-09-23 06:32:00 +0000666 /* the request line has been parsed successfully */
Igor Sysoev6b863e32003-05-12 15:52:24 +0000667
Igor Sysoev1b735832004-11-11 14:07:14 +0000668 r->request_line.len = r->request_end - r->request_start;
669 r->request_line.data = r->request_start;
Igor Sysoev42511c02008-08-04 11:10:52 +0000670 *r->request_end = '\0';
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000671
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000672
Igor Sysoevdc479b42003-03-20 16:09:44 +0000673 if (r->args_start) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000674 r->uri.len = r->args_start - 1 - r->uri_start;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000675 } else {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000676 r->uri.len = r->uri_end - r->uri_start;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000677 }
678
Igor Sysoevf6906042004-11-25 16:17:31 +0000679
Igor Sysoev924bd792004-10-11 15:07:03 +0000680 if (r->complex_uri || r->quoted_uri) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000681
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +0000682 r->uri.data = ngx_pnalloc(r->pool, r->uri.len + 1);
Igor Sysoevc1571722005-03-19 12:38:37 +0000683 if (r->uri.data == NULL) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000684 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev1b735832004-11-11 14:07:14 +0000685 return;
686 }
687
Igor Sysoev8decab32007-10-18 11:36:58 +0000688 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
689
690 rc = ngx_http_parse_complex_uri(r, cscf->merge_slashes);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000691
Igor Sysoevc04deca2005-03-28 14:43:02 +0000692 if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) {
693 ngx_log_error(NGX_LOG_INFO, c->log, 0,
694 "client sent invalid request");
695 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000696 return;
697 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000698
Igor Sysoevf7abd722004-09-23 06:32:00 +0000699 } else {
Igor Sysoev1b735832004-11-11 14:07:14 +0000700 r->uri.data = r->uri_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000701 }
702
Igor Sysoevf6906042004-11-25 16:17:31 +0000703
Igor Sysoev1b735832004-11-11 14:07:14 +0000704 r->unparsed_uri.len = r->uri_end - r->uri_start;
705 r->unparsed_uri.data = r->uri_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000706
Igor Sysoevf7abd722004-09-23 06:32:00 +0000707
Igor Sysoev899b44e2005-05-12 14:58:06 +0000708 r->method_name.len = r->method_end - r->request_start + 1;
709 r->method_name.data = r->request_line.data;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000710
Igor Sysoev1b735832004-11-11 14:07:14 +0000711
Igor Sysoev02025fd2005-01-18 13:03:58 +0000712 if (r->http_protocol.data) {
713 r->http_protocol.len = r->request_end - r->http_protocol.data;
714 }
715
716
Igor Sysoevf7abd722004-09-23 06:32:00 +0000717 if (r->uri_ext) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000718 if (r->args_start) {
719 r->exten.len = r->args_start - 1 - r->uri_ext;
720 } else {
721 r->exten.len = r->uri_end - r->uri_ext;
722 }
723
Igor Sysoev1b735832004-11-11 14:07:14 +0000724 r->exten.data = r->uri_ext;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000725 }
726
Igor Sysoev1b735832004-11-11 14:07:14 +0000727
Igor Sysoevf7abd722004-09-23 06:32:00 +0000728 if (r->args_start && r->uri_end > r->args_start) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000729 r->args.len = r->uri_end - r->args_start;
Igor Sysoev1b735832004-11-11 14:07:14 +0000730 r->args.data = r->args_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000731 }
732
Igor Sysoevf7abd722004-09-23 06:32:00 +0000733
734 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000735 "http request line: \"%V\"", &r->request_line);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000736
737 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000738 "http uri: \"%V\"", &r->uri);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000739
740 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000741 "http args: \"%V\"", &r->args);
742
743 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
744 "http exten: \"%V\"", &r->exten);
745
Igor Sysoev5fd09312008-05-15 14:44:47 +0000746 if (r->host_start && r->host_end) {
747 n = ngx_http_validate_host(r->host_start,
748 r->host_end - r->host_start);
749
750 if (n <= 0) {
751 ngx_log_error(NGX_LOG_INFO, c->log, 0,
752 "client sent invalid host in request line");
753 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
754 return;
755 }
756
757 r->headers_in.server.len = n;
758 r->headers_in.server.data = r->host_start;
759 }
760
Igor Sysoevf7abd722004-09-23 06:32:00 +0000761 if (r->http_version < NGX_HTTP_VERSION_10) {
Igor Sysoev5fd09312008-05-15 14:44:47 +0000762
763 if (ngx_http_find_virtual_server(r, r->headers_in.server.data,
764 r->headers_in.server.len)
765 == NGX_ERROR)
766 {
767 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
768 return;
769 }
770
Igor Sysoev62864d12007-06-04 20:40:03 +0000771 ngx_http_process_request(r);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000772 return;
773 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000774
Igor Sysoevdc479b42003-03-20 16:09:44 +0000775
Igor Sysoevf7abd722004-09-23 06:32:00 +0000776 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000777 sizeof(ngx_table_elt_t))
778 == NGX_ERROR)
Igor Sysoevf7abd722004-09-23 06:32:00 +0000779 {
780 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000781 return;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000782 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000783
784
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000785 if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000786 sizeof(ngx_table_elt_t *))
787 == NGX_ERROR)
Igor Sysoevf7abd722004-09-23 06:32:00 +0000788 {
789 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000790 return;
791 }
792
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000793 c->log->action = "reading client request headers";
Igor Sysoevf7abd722004-09-23 06:32:00 +0000794
Igor Sysoev899b44e2005-05-12 14:58:06 +0000795 rev->handler = ngx_http_process_request_headers;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000796 ngx_http_process_request_headers(rev);
797
798 return;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000799 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000800
Igor Sysoevc04deca2005-03-28 14:43:02 +0000801 if (rc != NGX_AGAIN) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000802
803 /* there was error while a request line parsing */
804
Igor Sysoevc04deca2005-03-28 14:43:02 +0000805 ngx_log_error(NGX_LOG_INFO, c->log, 0,
806 ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
807 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000808 return;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000809 }
810
Igor Sysoevf7abd722004-09-23 06:32:00 +0000811 /* NGX_AGAIN: a request line parsing is still incomplete */
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000812
Igor Sysoev236e0452004-09-23 16:39:34 +0000813 if (r->header_in->pos == r->header_in->end) {
Igor Sysoeva1c8a922004-01-19 18:09:14 +0000814
Igor Sysoevf7abd722004-09-23 06:32:00 +0000815 rv = ngx_http_alloc_large_header_buffer(r, 1);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000816
Igor Sysoevf7abd722004-09-23 06:32:00 +0000817 if (rv == NGX_ERROR) {
818 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000819 return;
820 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000821
Igor Sysoevf7abd722004-09-23 06:32:00 +0000822 if (rv == NGX_DECLINED) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000823 r->request_line.len = r->header_in->end - r->request_start;
824 r->request_line.data = r->request_start;
825
826 ngx_log_error(NGX_LOG_INFO, c->log, 0,
827 "client sent too long URI");
828 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000829 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000830 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000831 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000832 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000833}
834
Igor Sysoev1af7c822002-09-13 14:47:42 +0000835
Igor Sysoevc1571722005-03-19 12:38:37 +0000836static void
837ngx_http_process_request_headers(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000838{
Igor Sysoev02f742b2005-04-08 15:18:55 +0000839 ssize_t n;
840 ngx_int_t rc, rv;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000841 ngx_str_t header;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000842 ngx_table_elt_t *h;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000843 ngx_connection_t *c;
844 ngx_http_header_t *hh;
845 ngx_http_request_t *r;
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000846 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000847 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000848
Igor Sysoeva9830112003-05-19 16:39:14 +0000849 c = rev->data;
850 r = c->data;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000851
Igor Sysoev865c1502003-11-30 20:03:18 +0000852 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
853 "http process request header line");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000854
Igor Sysoev6b863e32003-05-12 15:52:24 +0000855 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000856 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
857 c->timedout = 1;
858 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000859 return;
860 }
861
Igor Sysoev02f742b2005-04-08 15:18:55 +0000862 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000863 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000864
Igor Sysoevd581fd52003-05-13 16:02:32 +0000865 rc = NGX_AGAIN;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000866
Igor Sysoev016b8522002-08-29 16:59:54 +0000867 for ( ;; ) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000868
Igor Sysoevd581fd52003-05-13 16:02:32 +0000869 if (rc == NGX_AGAIN) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000870
Igor Sysoev236e0452004-09-23 16:39:34 +0000871 if (r->header_in->pos == r->header_in->end) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000872
873 rv = ngx_http_alloc_large_header_buffer(r, 0);
874
875 if (rv == NGX_ERROR) {
876 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000877 return;
878 }
879
880 if (rv == NGX_DECLINED) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000881 header.len = r->header_in->end - r->header_name_start;
882 header.data = r->header_name_start;
Igor Sysoev90c08142005-07-25 09:41:38 +0000883
884 if (header.len > NGX_MAX_ERROR_STR - 300) {
885 header.len = NGX_MAX_ERROR_STR - 300;
886 header.data[header.len++] = '.';
887 header.data[header.len++] = '.';
888 header.data[header.len++] = '.';
889 }
890
Igor Sysoevc04deca2005-03-28 14:43:02 +0000891 ngx_log_error(NGX_LOG_INFO, c->log, 0,
892 "client sent too long header line: \"%V\"",
893 &header);
Igor Sysoev543a6ae2007-08-27 20:52:40 +0000894 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000895 return;
896 }
897 }
898
Igor Sysoevd581fd52003-05-13 16:02:32 +0000899 n = ngx_http_read_request_header(r);
900
901 if (n == NGX_AGAIN || n == NGX_ERROR) {
902 return;
903 }
904 }
905
Igor Sysoeve6779222003-10-03 15:50:53 +0000906 rc = ngx_http_parse_header_line(r, r->header_in);
Igor Sysoev016b8522002-08-29 16:59:54 +0000907
Igor Sysoev0dad6292003-03-05 17:30:51 +0000908 if (rc == NGX_OK) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000909
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000910 if (r->invalid_header && cscf->ignore_invalid_headers) {
Igor Sysoev4d656dc2005-03-22 16:02:46 +0000911
912 /* there was error while a header line parsing */
913
914 header.len = r->header_end - r->header_name_start;
915 header.data = r->header_name_start;
916
Igor Sysoevc04deca2005-03-28 14:43:02 +0000917 ngx_log_error(NGX_LOG_INFO, c->log, 0,
918 "client sent invalid header line: \"%V\"",
Igor Sysoev4d656dc2005-03-22 16:02:46 +0000919 &header);
920 continue;
921 }
922
Igor Sysoevd581fd52003-05-13 16:02:32 +0000923 /* a header line has been parsed successfully */
924
Igor Sysoevc1571722005-03-19 12:38:37 +0000925 h = ngx_list_push(&r->headers_in.headers);
926 if (h == NULL) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000927 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000928 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000929 }
930
Igor Sysoev02f742b2005-04-08 15:18:55 +0000931 h->hash = r->header_hash;
932
Igor Sysoevd581fd52003-05-13 16:02:32 +0000933 h->key.len = r->header_name_end - r->header_name_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000934 h->key.data = r->header_name_start;
935 h->key.data[h->key.len] = '\0';
936
Igor Sysoevd581fd52003-05-13 16:02:32 +0000937 h->value.len = r->header_end - r->header_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000938 h->value.data = r->header_start;
939 h->value.data[h->value.len] = '\0';
Igor Sysoevd581fd52003-05-13 16:02:32 +0000940
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +0000941 h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000942 if (h->lowcase_key == NULL) {
943 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
944 return;
945 }
Igor Sysoev899b44e2005-05-12 14:58:06 +0000946
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000947 if (h->key.len == r->lowcase_index) {
948 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
949
950 } else {
Igor Sysoev777b0192008-08-04 10:07:00 +0000951 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000952 }
953
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000954 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
955 h->lowcase_key, h->key.len);
956
957 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
958 return;
959 }
960
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000961 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000962 "http header: \"%V: %V\"",
963 &h->key, &h->value);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000964
Igor Sysoev6253ca12003-05-27 12:18:54 +0000965 continue;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000966 }
Igor Sysoev6253ca12003-05-27 12:18:54 +0000967
Igor Sysoevc04deca2005-03-28 14:43:02 +0000968 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000969
970 /* a whole header has been parsed successfully */
971
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000972 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
973 "http header done");
Igor Sysoev42feecb2002-12-15 06:25:09 +0000974
Igor Sysoev6a12fc92004-12-06 14:45:08 +0000975 r->request_length += r->header_in->pos - r->header_in->start;
976
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000977 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
978
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000979 rc = ngx_http_process_request_header(r);
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000980
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000981 if (rc != NGX_OK) {
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000982 return;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000983 }
984
Igor Sysoev62864d12007-06-04 20:40:03 +0000985 ngx_http_process_request(r);
Igor Sysoeve5035392005-08-30 10:55:07 +0000986
Igor Sysoevd581fd52003-05-13 16:02:32 +0000987 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000988 }
989
Igor Sysoevc04deca2005-03-28 14:43:02 +0000990 if (rc == NGX_AGAIN) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000991
Igor Sysoevc04deca2005-03-28 14:43:02 +0000992 /* a header line parsing is still not complete */
993
994 continue;
995 }
996
997 /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
998
999 header.len = r->header_end - r->header_name_start;
1000 header.data = r->header_name_start;
1001 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1002 "client sent invalid header line: \"%V\\r...\"",
1003 &header);
Igor Sysoev543a6ae2007-08-27 20:52:40 +00001004 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevc04deca2005-03-28 14:43:02 +00001005 return;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +00001006 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001007}
1008
Igor Sysoevb0869052002-12-10 18:05:12 +00001009
Igor Sysoevc1571722005-03-19 12:38:37 +00001010static ssize_t
1011ngx_http_read_request_header(ngx_http_request_t *r)
Igor Sysoev6b863e32003-05-12 15:52:24 +00001012{
Igor Sysoev187fcd82003-05-23 11:53:01 +00001013 ssize_t n;
1014 ngx_event_t *rev;
Igor Sysoevda173ab2006-08-30 10:39:17 +00001015 ngx_connection_t *c;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001016 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev6b863e32003-05-12 15:52:24 +00001017
Igor Sysoevda173ab2006-08-30 10:39:17 +00001018 c = r->connection;
1019 rev = c->read;
Igor Sysoev239baac2003-06-11 15:28:34 +00001020
Igor Sysoev6b863e32003-05-12 15:52:24 +00001021 n = r->header_in->last - r->header_in->pos;
1022
1023 if (n > 0) {
1024 return n;
1025 }
1026
Igor Sysoevb145b062005-06-15 18:33:41 +00001027 if (rev->ready) {
Igor Sysoevda173ab2006-08-30 10:39:17 +00001028 n = c->recv(c, r->header_in->last,
1029 r->header_in->end - r->header_in->last);
Igor Sysoevb145b062005-06-15 18:33:41 +00001030 } else {
1031 n = NGX_AGAIN;
Igor Sysoev222a2ad2003-11-18 16:49:00 +00001032 }
1033
Igor Sysoev6b863e32003-05-12 15:52:24 +00001034 if (n == NGX_AGAIN) {
Igor Sysoev1bc3a932008-01-08 20:55:27 +00001035 if (!rev->timer_set) {
Igor Sysoevf38e0462004-07-16 17:11:43 +00001036 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev187fcd82003-05-23 11:53:01 +00001037 ngx_add_timer(rev, cscf->client_header_timeout);
Igor Sysoev6b863e32003-05-12 15:52:24 +00001038 }
1039
Igor Sysoevb5faed22003-10-29 08:30:44 +00001040 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001041 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001042 return NGX_ERROR;
1043 }
1044
Igor Sysoev6b863e32003-05-12 15:52:24 +00001045 return NGX_AGAIN;
1046 }
1047
1048 if (n == 0) {
Igor Sysoevda173ab2006-08-30 10:39:17 +00001049 ngx_log_error(NGX_LOG_INFO, c->log, 0,
Igor Sysoev6b863e32003-05-12 15:52:24 +00001050 "client closed prematurely connection");
Igor Sysoevd581fd52003-05-13 16:02:32 +00001051 }
Igor Sysoev6b863e32003-05-12 15:52:24 +00001052
1053 if (n == 0 || n == NGX_ERROR) {
Igor Sysoev23169362007-01-08 18:22:06 +00001054 c->error = 1;
Igor Sysoev1691aaf2007-01-08 18:23:38 +00001055 c->log->action = "reading client request headers";
Igor Sysoevda173ab2006-08-30 10:39:17 +00001056
Igor Sysoev23169362007-01-08 18:22:06 +00001057 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev6b863e32003-05-12 15:52:24 +00001058 return NGX_ERROR;
1059 }
1060
1061 r->header_in->last += n;
1062
1063 return n;
1064}
1065
1066
Igor Sysoevc1571722005-03-19 12:38:37 +00001067static ngx_int_t
1068ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
1069 ngx_uint_t request_line)
Igor Sysoev85080d02004-09-22 16:18:21 +00001070{
1071 u_char *old, *new;
Igor Sysoev85080d02004-09-22 16:18:21 +00001072 ngx_buf_t *b;
1073 ngx_http_connection_t *hc;
1074 ngx_http_core_srv_conf_t *cscf;
1075
1076 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1077 "http alloc large header buffer");
1078
Igor Sysoevf7abd722004-09-23 06:32:00 +00001079 if (request_line && r->state == 0) {
1080
1081 /* the client fills up the buffer with "\r\n" */
1082
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001083 r->request_length += r->header_in->end - r->header_in->start;
1084
Igor Sysoevf7abd722004-09-23 06:32:00 +00001085 r->header_in->pos = r->header_in->start;
1086 r->header_in->last = r->header_in->start;
1087
1088 return NGX_OK;
1089 }
1090
Igor Sysoev85080d02004-09-22 16:18:21 +00001091 old = request_line ? r->request_start : r->header_name_start;
1092
1093 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1094
Igor Sysoevf7abd722004-09-23 06:32:00 +00001095 if (r->state != 0
1096 && (size_t) (r->header_in->pos - old)
1097 >= cscf->large_client_header_buffers.size)
1098 {
Igor Sysoev85080d02004-09-22 16:18:21 +00001099 return NGX_DECLINED;
1100 }
1101
1102 hc = r->http_connection;
1103
1104 if (hc->nfree) {
1105 b = hc->free[--hc->nfree];
1106
Igor Sysoev236e0452004-09-23 16:39:34 +00001107 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +00001108 "http large header free: %p %uz",
Igor Sysoev236e0452004-09-23 16:39:34 +00001109 b->pos, b->end - b->last);
1110
Igor Sysoevf7abd722004-09-23 06:32:00 +00001111 } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
Igor Sysoev85080d02004-09-22 16:18:21 +00001112
1113 if (hc->busy == NULL) {
1114 hc->busy = ngx_palloc(r->connection->pool,
Igor Sysoevf7abd722004-09-23 06:32:00 +00001115 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev85080d02004-09-22 16:18:21 +00001116 if (hc->busy == NULL) {
1117 return NGX_ERROR;
1118 }
1119 }
1120
1121 b = ngx_create_temp_buf(r->connection->pool,
Igor Sysoevf7abd722004-09-23 06:32:00 +00001122 cscf->large_client_header_buffers.size);
Igor Sysoev85080d02004-09-22 16:18:21 +00001123 if (b == NULL) {
1124 return NGX_ERROR;
1125 }
1126
Igor Sysoev236e0452004-09-23 16:39:34 +00001127 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +00001128 "http large header alloc: %p %uz",
Igor Sysoev236e0452004-09-23 16:39:34 +00001129 b->pos, b->end - b->last);
1130
Igor Sysoev85080d02004-09-22 16:18:21 +00001131 } else {
1132 return NGX_DECLINED;
1133 }
1134
1135 hc->busy[hc->nbusy++] = b;
1136
Igor Sysoevf7abd722004-09-23 06:32:00 +00001137 if (r->state == 0) {
1138 /*
1139 * r->state == 0 means that a header line was parsed successfully
1140 * and we do not need to copy incomplete header line and
1141 * to relocate the parser header pointers
1142 */
1143
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001144 r->request_length += r->header_in->end - r->header_in->start;
1145
Igor Sysoevf7abd722004-09-23 06:32:00 +00001146 r->header_in = b;
1147
1148 return NGX_OK;
1149 }
1150
Igor Sysoev236e0452004-09-23 16:39:34 +00001151 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1152 "http large header copy: %d", r->header_in->pos - old);
1153
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001154 r->request_length += old - r->header_in->start;
1155
Igor Sysoev85080d02004-09-22 16:18:21 +00001156 new = b->start;
1157
Igor Sysoev236e0452004-09-23 16:39:34 +00001158 ngx_memcpy(new, old, r->header_in->pos - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001159
1160 b->pos = new + (r->header_in->pos - old);
Igor Sysoev236e0452004-09-23 16:39:34 +00001161 b->last = new + (r->header_in->pos - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001162
1163 if (request_line) {
1164 r->request_start = new;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001165
1166 if (r->request_end) {
1167 r->request_end = new + (r->request_end - old);
1168 }
1169
1170 r->method_end = new + (r->method_end - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001171
1172 r->uri_start = new + (r->uri_start - old);
1173 r->uri_end = new + (r->uri_end - old);
1174
Igor Sysoevf7abd722004-09-23 06:32:00 +00001175 if (r->schema_start) {
1176 r->schema_start = new + (r->schema_start - old);
1177 r->schema_end = new + (r->schema_end - old);
1178 }
1179
1180 if (r->host_start) {
1181 r->host_start = new + (r->host_start - old);
Igor Sysoev03011fa2006-12-15 10:24:57 +00001182 if (r->host_end) {
1183 r->host_end = new + (r->host_end - old);
1184 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00001185 }
1186
1187 if (r->port_start) {
1188 r->port_start = new + (r->port_start - old);
1189 r->port_end = new + (r->port_end - old);
1190 }
1191
Igor Sysoev85080d02004-09-22 16:18:21 +00001192 if (r->uri_ext) {
1193 r->uri_ext = new + (r->uri_ext - old);
1194 }
1195
1196 if (r->args_start) {
1197 r->args_start = new + (r->args_start - old);
1198 }
1199
Igor Sysoev58ea0c12007-12-01 12:22:48 +00001200 if (r->http_protocol.data) {
1201 r->http_protocol.data = new + (r->http_protocol.data - old);
1202 }
1203
Igor Sysoev85080d02004-09-22 16:18:21 +00001204 } else {
1205 r->header_name_start = new;
1206 r->header_name_end = new + (r->header_name_end - old);
1207 r->header_start = new + (r->header_start - old);
1208 r->header_end = new + (r->header_end - old);
1209 }
1210
1211 r->header_in = b;
1212
1213 return NGX_OK;
1214}
1215
Igor Sysoev85080d02004-09-22 16:18:21 +00001216
Igor Sysoevc1571722005-03-19 12:38:37 +00001217static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001218ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1219 ngx_uint_t offset)
1220{
1221 ngx_table_elt_t **ph;
1222
1223 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1224
1225 if (*ph == NULL) {
1226 *ph = h;
1227 }
1228
1229 return NGX_OK;
1230}
1231
1232
1233static ngx_int_t
Igor Sysoevb145b062005-06-15 18:33:41 +00001234ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1235 ngx_uint_t offset)
1236{
1237 ngx_table_elt_t **ph;
1238
1239 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1240
1241 if (*ph == NULL) {
1242 *ph = h;
1243 return NGX_OK;
1244 }
1245
1246 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
Igor Sysoevda173ab2006-08-30 10:39:17 +00001247 "client sent duplicate header line: \"%V: %V\", "
1248 "previous value: \"%V: %V\"",
1249 &h->key, &h->value, &(*ph)->key, &(*ph)->value);
Igor Sysoevb145b062005-06-15 18:33:41 +00001250
1251 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1252
1253 return NGX_ERROR;
1254}
1255
1256
1257static ngx_int_t
Igor Sysoev5fd09312008-05-15 14:44:47 +00001258ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
1259 ngx_uint_t offset)
1260{
1261 ssize_t len;
1262
1263 if (r->headers_in.host == NULL) {
1264 r->headers_in.host = h;
1265 }
1266
1267 len = ngx_http_validate_host(h->value.data, h->value.len);
1268
1269 if (len <= 0) {
1270 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1271 "client sent invalid host header");
1272 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1273 return NGX_ERROR;
1274 }
1275
1276 if (r->headers_in.server.len) {
1277 return NGX_OK;
1278 }
1279
1280 r->headers_in.server.len = len;
1281 r->headers_in.server.data = h->value.data;
1282
1283 return NGX_OK;
1284}
1285
1286
1287static ngx_int_t
Igor Sysoevec67b192007-09-09 18:28:49 +00001288ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
1289 ngx_uint_t offset)
1290{
Igor Sysoevf5329412007-10-01 12:57:47 +00001291 if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
Igor Sysoevec67b192007-09-09 18:28:49 +00001292 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1293
Igor Sysoevf5329412007-10-01 12:57:47 +00001294 } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {
Igor Sysoevec67b192007-09-09 18:28:49 +00001295 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1296 }
1297
1298 return NGX_OK;
1299}
1300
1301
1302static ngx_int_t
Igor Sysoevbc5fb292008-05-13 09:18:58 +00001303ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
1304 ngx_uint_t offset)
1305{
Igor Sysoev54477e42008-08-26 15:09:28 +00001306 u_char *user_agent, *msie;
Igor Sysoevbc5fb292008-05-13 09:18:58 +00001307
1308 if (r->headers_in.user_agent) {
1309 return NGX_OK;
1310 }
1311
1312 r->headers_in.user_agent = h;
1313
1314 /* check some widespread browsers while the header is in CPU cache */
1315
1316 user_agent = h->value.data;
1317
Igor Sysoev54477e42008-08-26 15:09:28 +00001318 msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
Igor Sysoevbc5fb292008-05-13 09:18:58 +00001319
Igor Sysoev54477e42008-08-26 15:09:28 +00001320 if (msie && msie + 7 < user_agent + h->value.len) {
Igor Sysoevbc5fb292008-05-13 09:18:58 +00001321
1322 r->headers_in.msie = 1;
1323
Igor Sysoev54477e42008-08-26 15:09:28 +00001324 if (msie[6] == '.') {
1325
1326 switch (msie[5]) {
1327 case '4':
1328 r->headers_in.msie4 = 1;
1329 /* fall through */
1330 case '5':
1331 case '6':
1332 r->headers_in.msie6 = 1;
1333 }
Igor Sysoevbc5fb292008-05-13 09:18:58 +00001334 }
1335
1336#if 0
1337 /* MSIE ignores the SSL "close notify" alert */
1338 if (c->ssl) {
1339 c->ssl->no_send_shutdown = 1;
1340 }
1341#endif
1342 }
1343
1344 if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
1345 r->headers_in.opera = 1;
1346 r->headers_in.msie = 0;
1347 r->headers_in.msie4 = 0;
Igor Sysoev54477e42008-08-26 15:09:28 +00001348 r->headers_in.msie6 = 0;
Igor Sysoevbc5fb292008-05-13 09:18:58 +00001349 }
1350
1351 if (!r->headers_in.msie && !r->headers_in.opera) {
1352
1353 if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
1354 r->headers_in.gecko = 1;
1355
1356 } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
1357 r->headers_in.konqueror = 1;
1358 }
1359 }
1360
1361 return NGX_OK;
1362}
1363
1364
1365static ngx_int_t
Igor Sysoev5fd09312008-05-15 14:44:47 +00001366ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
1367 ngx_uint_t offset)
1368{
1369 ngx_table_elt_t **cookie;
1370
1371 cookie = ngx_array_push(&r->headers_in.cookies);
1372 if (cookie) {
1373 *cookie = h;
1374 return NGX_OK;
1375 }
1376
1377 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1378
1379 return NGX_ERROR;
1380}
1381
1382
1383static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001384ngx_http_process_request_header(ngx_http_request_t *r)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001385{
Igor Sysoev5fd09312008-05-15 14:44:47 +00001386 if (ngx_http_find_virtual_server(r, r->headers_in.server.data,
1387 r->headers_in.server.len)
1388 == NGX_ERROR)
1389 {
1390 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1391 return NGX_ERROR;
1392 }
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001393
Igor Sysoev5fd09312008-05-15 14:44:47 +00001394 if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) {
1395 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1396 "client sent HTTP/1.1 request without \"Host\" header");
1397 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1398 return NGX_ERROR;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001399 }
1400
1401 if (r->headers_in.content_length) {
1402 r->headers_in.content_length_n =
Igor Sysoev1765f472006-07-07 16:33:19 +00001403 ngx_atoof(r->headers_in.content_length->value.data,
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001404 r->headers_in.content_length->value.len);
1405
1406 if (r->headers_in.content_length_n == NGX_ERROR) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001407 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1408 "client sent invalid \"Content-Length\" header");
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001409 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
Igor Sysoevc04deca2005-03-28 14:43:02 +00001410 return NGX_ERROR;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001411 }
1412 }
1413
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00001414 if (r->method & (NGX_HTTP_POST|NGX_HTTP_PUT)
1415 && r->headers_in.content_length_n == -1)
1416 {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001417 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
Igor Sysoev0d68f272007-12-30 09:11:19 +00001418 "client sent %V method without \"Content-Length\" header",
1419 &r->method_name);
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001420 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
1421 return NGX_ERROR;
1422 }
1423
Igor Sysoev589fc742007-09-07 09:29:08 +00001424 if (r->method & NGX_HTTP_TRACE) {
Igor Sysoev3e933d22007-03-30 18:59:26 +00001425 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1426 "client sent TRACE method");
1427 ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
1428 return NGX_ERROR;
1429 }
1430
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001431 if (r->headers_in.transfer_encoding
Igor Sysoev06597202007-09-26 19:26:14 +00001432 && ngx_strcasestrn(r->headers_in.transfer_encoding->value.data,
Igor Sysoevf5329412007-10-01 12:57:47 +00001433 "chunked", 7 - 1))
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001434 {
1435 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1436 "client sent \"Transfer-Encoding: chunked\" header");
1437 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
Igor Sysoevc04deca2005-03-28 14:43:02 +00001438 return NGX_ERROR;
Igor Sysoev6881bfb2004-03-30 06:27:36 +00001439 }
1440
Igor Sysoevec67b192007-09-09 18:28:49 +00001441 if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
1442 if (r->headers_in.keep_alive) {
1443 r->headers_in.keep_alive_n =
1444 ngx_atotm(r->headers_in.keep_alive->value.data,
1445 r->headers_in.keep_alive->value.len);
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001446 }
1447 }
1448
Igor Sysoev62864d12007-06-04 20:40:03 +00001449 return NGX_OK;
1450}
1451
1452
1453static void
1454ngx_http_process_request(ngx_http_request_t *r)
1455{
Igor Sysoev86ef6aa2007-12-10 12:09:51 +00001456 ngx_connection_t *c;
Igor Sysoev62864d12007-06-04 20:40:03 +00001457
1458 c = r->connection;
1459
Igor Sysoev1d4e9b32007-12-01 11:46:04 +00001460 if (r->plain_http) {
1461 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1462 "client sent plain HTTP request to HTTPS port");
1463 ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1464 return;
1465 }
1466
Igor Sysoevb71c6902006-08-04 16:04:04 +00001467#if (NGX_HTTP_SSL)
1468
Igor Sysoev62864d12007-06-04 20:40:03 +00001469 if (c->ssl) {
Igor Sysoev86ef6aa2007-12-10 12:09:51 +00001470 long rc;
Igor Sysoev439e2882008-04-23 18:57:25 +00001471 X509 *cert;
Igor Sysoev86ef6aa2007-12-10 12:09:51 +00001472 ngx_http_ssl_srv_conf_t *sscf;
1473
Igor Sysoevb71c6902006-08-04 16:04:04 +00001474 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
1475
Igor Sysoev49ed6f32008-07-29 14:29:02 +00001476 if (sscf->verify == 1) {
Igor Sysoev62864d12007-06-04 20:40:03 +00001477 rc = SSL_get_verify_result(c->ssl->connection);
Igor Sysoevb71c6902006-08-04 16:04:04 +00001478
1479 if (rc != X509_V_OK) {
Igor Sysoev62864d12007-06-04 20:40:03 +00001480 ngx_log_error(NGX_LOG_INFO, c->log, 0,
Igor Sysoevc55a1042006-08-09 19:59:45 +00001481 "client SSL certificate verify error: (%l:%s)",
Igor Sysoevb71c6902006-08-04 16:04:04 +00001482 rc, X509_verify_cert_error_string(rc));
Igor Sysoev472233d2008-03-10 14:47:07 +00001483
1484 ngx_ssl_remove_cached_session(sscf->ssl.ctx,
1485 (SSL_get0_session(c->ssl->connection)));
1486
Igor Sysoevb71c6902006-08-04 16:04:04 +00001487 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
Igor Sysoev62864d12007-06-04 20:40:03 +00001488 return;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001489 }
1490
Igor Sysoev439e2882008-04-23 18:57:25 +00001491 cert = SSL_get_peer_certificate(c->ssl->connection);
1492
1493 if (cert == NULL) {
Igor Sysoev62864d12007-06-04 20:40:03 +00001494 ngx_log_error(NGX_LOG_INFO, c->log, 0,
Igor Sysoevb71c6902006-08-04 16:04:04 +00001495 "client sent no required SSL certificate");
Igor Sysoev472233d2008-03-10 14:47:07 +00001496
1497 ngx_ssl_remove_cached_session(sscf->ssl.ctx,
1498 (SSL_get0_session(c->ssl->connection)));
1499
Igor Sysoevb71c6902006-08-04 16:04:04 +00001500 ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
Igor Sysoev62864d12007-06-04 20:40:03 +00001501 return;
Igor Sysoevb71c6902006-08-04 16:04:04 +00001502 }
Igor Sysoev439e2882008-04-23 18:57:25 +00001503
1504 X509_free(cert);
Igor Sysoevb71c6902006-08-04 16:04:04 +00001505 }
1506 }
1507
1508#endif
1509
Igor Sysoev62864d12007-06-04 20:40:03 +00001510 if (c->read->timer_set) {
1511 ngx_del_timer(c->read);
1512 }
1513
1514#if (NGX_STAT_STUB)
1515 ngx_atomic_fetch_add(ngx_stat_reading, -1);
1516 r->stat_reading = 0;
1517 ngx_atomic_fetch_add(ngx_stat_writing, 1);
1518 r->stat_writing = 1;
1519#endif
1520
1521 c->read->handler = ngx_http_request_handler;
1522 c->write->handler = ngx_http_request_handler;
Igor Sysoev7ab4d9c2007-08-06 15:22:40 +00001523 r->read_event_handler = ngx_http_block_reading;
Igor Sysoev62864d12007-06-04 20:40:03 +00001524
1525 ngx_http_handler(r);
1526
1527 return;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001528}
1529
1530
Igor Sysoev5fd09312008-05-15 14:44:47 +00001531static ssize_t
1532ngx_http_validate_host(u_char *host, size_t len)
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001533{
Igor Sysoev5fd09312008-05-15 14:44:47 +00001534 u_char ch;
1535 size_t i, last;
1536 ngx_uint_t dot;
1537
1538 last = len;
1539 dot = 0;
1540
1541 for (i = 0; i < len; i++) {
1542 ch = host[i];
1543
1544 if (ch == '.') {
1545 if (dot) {
1546 return -1;
1547 }
1548
1549 dot = 1;
1550 continue;
1551 }
1552
1553 dot = 0;
1554
1555 if (ch == ':') {
1556 last = i;
1557 continue;
1558 }
1559
1560 if (ch == '/' || ch == '\0') {
1561 return -1;
1562 }
1563
1564#if (NGX_WIN32)
1565 if (ch == '\\') {
1566 return -1;
1567 }
1568#endif
1569 }
1570
1571 if (dot) {
1572 last--;
1573 }
1574
1575 return last;
1576}
1577
1578
1579static ngx_int_t
1580ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len)
1581{
Igor Sysoev6a078332008-08-04 10:18:36 +00001582 u_char *server;
1583 ngx_uint_t hash;
Igor Sysoev305a9d82005-12-26 17:07:48 +00001584 ngx_http_core_loc_conf_t *clcf;
1585 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev5fd09312008-05-15 14:44:47 +00001586 u_char buf[32];
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001587
Igor Sysoevb29426d2008-08-21 12:56:10 +00001588 if (r->virtual_names == NULL) {
Igor Sysoev5fd09312008-05-15 14:44:47 +00001589 return NGX_DECLINED;
1590 }
1591
1592 if (len <= 32) {
1593 server = buf;
1594
1595 } else {
Igor Sysoev7f6b2ff2008-06-17 15:00:30 +00001596 server = ngx_pnalloc(r->pool, len);
Igor Sysoev5fd09312008-05-15 14:44:47 +00001597 if (server == NULL) {
1598 return NGX_ERROR;
1599 }
1600 }
1601
Igor Sysoev6a078332008-08-04 10:18:36 +00001602 hash = ngx_hash_strlow(server, host, len);
Igor Sysoev5fd09312008-05-15 14:44:47 +00001603
1604 cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, server, len);
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001605
Igor Sysoev9d8a75c2007-06-11 19:49:22 +00001606 if (cscf) {
1607 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001608 }
1609
Igor Sysoev43c3bf42007-08-12 19:48:12 +00001610#if (NGX_PCRE)
1611
1612 if (r->virtual_names->nregex) {
Igor Sysoev86ef6aa2007-12-10 12:09:51 +00001613 ngx_int_t n;
1614 ngx_uint_t i;
1615 ngx_str_t name;
1616 ngx_http_server_name_t *sn;
Igor Sysoev43c3bf42007-08-12 19:48:12 +00001617
1618 name.len = len;
Igor Sysoev5fd09312008-05-15 14:44:47 +00001619 name.data = server;
Igor Sysoev43c3bf42007-08-12 19:48:12 +00001620
1621 sn = r->virtual_names->regex;
1622
1623 for (i = 0; i < r->virtual_names->nregex; i++) {
1624
1625 n = ngx_regex_exec(sn[i].regex, &name, NULL, 0);
1626
1627 if (n == NGX_REGEX_NO_MATCHED) {
1628 continue;
1629 }
1630
1631 if (n < 0) {
1632 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1633 ngx_regex_exec_n
1634 " failed: %d on \"%V\" using \"%V\"",
1635 n, &name, &sn[i].name);
Igor Sysoev5fd09312008-05-15 14:44:47 +00001636 return NGX_ERROR;
Igor Sysoev43c3bf42007-08-12 19:48:12 +00001637 }
1638
1639 /* match */
1640
1641 cscf = sn[i].core_srv_conf;
1642
1643 goto found;
1644 }
1645 }
1646
1647#endif
1648
Igor Sysoev5fd09312008-05-15 14:44:47 +00001649 return NGX_OK;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001650
Igor Sysoev899b44e2005-05-12 14:58:06 +00001651found:
1652
Igor Sysoev305a9d82005-12-26 17:07:48 +00001653 r->srv_conf = cscf->ctx->srv_conf;
1654 r->loc_conf = cscf->ctx->loc_conf;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001655
1656 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1657 r->connection->log->file = clcf->err_log->file;
1658
1659 if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1660 r->connection->log->log_level = clcf->err_log->log_level;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001661 }
1662
Igor Sysoev5fd09312008-05-15 14:44:47 +00001663 return NGX_OK;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001664}
1665
1666
Igor Sysoev899b44e2005-05-12 14:58:06 +00001667static void
1668ngx_http_request_handler(ngx_event_t *ev)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001669{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001670 ngx_connection_t *c;
1671 ngx_http_request_t *r;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001672 ngx_http_log_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001673
1674 c = ev->data;
1675 r = c->data;
1676
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001677 ctx = c->log->data;
1678 ctx->current_request = r;
1679
Igor Sysoev899b44e2005-05-12 14:58:06 +00001680 if (ev->write) {
1681 r->write_event_handler(r);
1682
1683 } else {
1684 r->read_event_handler(r);
1685 }
1686}
1687
1688
1689void
1690ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1691{
Igor Sysoevae0347a2007-08-27 15:53:00 +00001692 ngx_connection_t *c;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001693 ngx_http_request_t *pr;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001694 ngx_http_log_ctx_t *ctx;
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001695 ngx_http_core_loc_conf_t *clcf;
1696
Igor Sysoev899b44e2005-05-12 14:58:06 +00001697 if (rc == NGX_DONE) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001698 /* the request pool may be already destroyed */
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001699 return;
1700 }
1701
Igor Sysoevae0347a2007-08-27 15:53:00 +00001702 c = r->connection;
1703
1704 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001705 "http finalize request: %d, \"%V?%V\"",
1706 rc, &r->uri, &r->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001707
Igor Sysoevda173ab2006-08-30 10:39:17 +00001708 if (rc == NGX_DECLINED) {
1709 r->content_handler = NULL;
1710 r->write_event_handler = ngx_http_core_run_phases;
1711 ngx_http_core_run_phases(r);
1712 return;
1713 }
1714
Igor Sysoev960100e2006-10-13 15:20:10 +00001715 if (r != r->main && r->post_subrequest) {
1716 rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
Igor Sysoev8f125582006-07-28 15:16:17 +00001717 }
1718
Igor Sysoeve87afba2007-12-27 13:13:34 +00001719 if (rc == NGX_ERROR
1720 || rc == NGX_HTTP_REQUEST_TIME_OUT
1721 || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
1722 || c->error)
1723 {
Igor Sysoev8b57df92007-01-29 11:53:23 +00001724 if (rc > 0 && r->headers_out.status == 0) {
1725 r->headers_out.status = rc;
Igor Sysoev7f7846d2006-04-26 09:52:47 +00001726 }
1727
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001728 if (ngx_http_post_action(r) == NGX_OK) {
1729 return;
1730 }
1731
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001732 ngx_http_close_request(r, 0);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001733 return;
1734 }
1735
Igor Sysoev7bdb7202006-04-19 15:30:56 +00001736 if (rc >= NGX_HTTP_SPECIAL_RESPONSE
1737 || rc == NGX_HTTP_CREATED
1738 || rc == NGX_HTTP_NO_CONTENT)
1739 {
Igor Sysoevcdc46302005-12-07 14:51:31 +00001740 if (rc == NGX_HTTP_CLOSE) {
1741 ngx_http_close_request(r, rc);
1742 return;
1743 }
1744
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001745 if (r == r->main) {
Igor Sysoevae0347a2007-08-27 15:53:00 +00001746 if (c->read->timer_set) {
1747 ngx_del_timer(c->read);
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001748 }
1749
Igor Sysoevae0347a2007-08-27 15:53:00 +00001750 if (c->write->timer_set) {
1751 ngx_del_timer(c->write);
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001752 }
1753 }
1754
1755 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001756 return;
1757 }
1758
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001759 if (r != r->main || rc == NGX_AGAIN) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001760 if (ngx_http_set_write_handler(r) != NGX_OK) {
1761 return;
1762 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001763 }
1764
Igor Sysoeva936b272007-12-27 14:39:05 +00001765 r->done = 1;
1766
Igor Sysoevae0347a2007-08-27 15:53:00 +00001767 if (r != c->data) {
1768 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001769 "http finalize non-active request: \"%V?%V\"",
1770 &r->uri, &r->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001771 return;
1772 }
1773
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001774 if (r != r->main) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001775
1776 pr = r->parent;
1777
Igor Sysoevae0347a2007-08-27 15:53:00 +00001778 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001779 "http parent request: \"%V?%V\"", &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001780
Igor Sysoev899b44e2005-05-12 14:58:06 +00001781 if (rc != NGX_AGAIN) {
Igor Sysoevae0347a2007-08-27 15:53:00 +00001782 c->data = pr;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001783 }
1784
Igor Sysoevae0347a2007-08-27 15:53:00 +00001785 ctx = c->log->data;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001786 ctx->current_request = pr;
1787
Igor Sysoev899b44e2005-05-12 14:58:06 +00001788 if (pr->postponed) {
1789
Igor Sysoevae0347a2007-08-27 15:53:00 +00001790 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001791 "http request: \"%V?%V\" has postponed",
1792 &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001793
Igor Sysoev899b44e2005-05-12 14:58:06 +00001794 if (rc != NGX_AGAIN && pr->postponed->request == r) {
1795 pr->postponed = pr->postponed->next;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001796 }
1797
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001798 if (r->fast_subrequest) {
Igor Sysoevac72bd12006-05-04 15:32:46 +00001799
1800 if (rc == NGX_AGAIN) {
1801 r->fast_subrequest = 0;
1802 }
1803
Igor Sysoevae0347a2007-08-27 15:53:00 +00001804 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev12dcb352007-12-25 15:31:18 +00001805 "http fast subrequest: \"%V?%V\" done",
1806 &r->uri, &r->args);
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001807 return;
1808 }
1809
Igor Sysoevac72bd12006-05-04 15:32:46 +00001810 if (rc != NGX_AGAIN) {
Igor Sysoevae0347a2007-08-27 15:53:00 +00001811 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoevac72bd12006-05-04 15:32:46 +00001812 "http wake parent request: \"%V?%V\"",
1813 &pr->uri, &pr->args);
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001814
Igor Sysoevac72bd12006-05-04 15:32:46 +00001815 pr->write_event_handler(pr);
1816 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001817 }
1818
1819 return;
1820 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001821
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001822 if (rc == NGX_AGAIN) {
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001823 return;
Igor Sysoev5192b362005-07-08 14:34:20 +00001824 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001825
Igor Sysoevae0347a2007-08-27 15:53:00 +00001826 if (c->buffered) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001827 (void) ngx_http_set_write_handler(r);
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001828 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001829 }
1830
Igor Sysoev6d16e1e2006-04-05 13:40:54 +00001831 if (!r->post_action) {
1832 r->request_complete = 1;
1833 }
1834
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001835 if (ngx_http_post_action(r) == NGX_OK) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001836 return;
1837 }
1838
Igor Sysoevae0347a2007-08-27 15:53:00 +00001839 if (c->read->timer_set) {
1840 ngx_del_timer(c->read);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001841 }
1842
Igor Sysoevae0347a2007-08-27 15:53:00 +00001843 if (c->write->timer_set) {
1844 c->write->delayed = 0;
1845 ngx_del_timer(c->write);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001846 }
1847
Igor Sysoevae0347a2007-08-27 15:53:00 +00001848 if (c->destroyed) {
Igor Sysoev24025022005-12-16 15:07:08 +00001849 return;
1850 }
1851
Igor Sysoevae0347a2007-08-27 15:53:00 +00001852 if (c->read->eof) {
Igor Sysoevdb7b1262007-08-27 15:40:19 +00001853 ngx_http_close_request(r, 0);
1854 return;
1855 }
1856
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001857 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001858
Igor Sysoevc5991982004-01-16 06:15:48 +00001859 if (!ngx_terminate
Igor Sysoev3f4685f2004-04-25 20:13:21 +00001860 && !ngx_exiting
Igor Sysoevcdd43542008-05-21 17:39:51 +00001861 && r->keepalive
Igor Sysoevc5991982004-01-16 06:15:48 +00001862 && clcf->keepalive_timeout > 0)
1863 {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001864 ngx_http_set_keepalive(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001865 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001866
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001867 } else if (r->lingering_close && clcf->lingering_timeout > 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001868 ngx_http_set_lingering_close(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001869 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001870 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001871
Igor Sysoevc5991982004-01-16 06:15:48 +00001872 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001873}
1874
1875
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001876static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001877ngx_http_set_write_handler(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001878{
Igor Sysoevd581fd52003-05-13 16:02:32 +00001879 ngx_event_t *wev;
Igor Sysoeva9830112003-05-19 16:39:14 +00001880 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001881
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001882 r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
1883
Igor Sysoev7ab4d9c2007-08-06 15:22:40 +00001884 r->read_event_handler = ngx_http_test_reading;
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001885 r->write_event_handler = ngx_http_writer;
1886
Igor Sysoev899b44e2005-05-12 14:58:06 +00001887 wev = r->connection->write;
1888
Igor Sysoevef066482004-06-21 15:59:32 +00001889 if (wev->ready && wev->delayed) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001890 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001891 }
1892
Igor Sysoev899b44e2005-05-12 14:58:06 +00001893 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001894 if (!wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001895 ngx_add_timer(wev, clcf->send_timeout);
1896 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001897
Igor Sysoev924bd792004-10-11 15:07:03 +00001898 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001899 ngx_http_close_request(r, 0);
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001900 return NGX_ERROR;
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001901 }
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001902
1903 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001904}
1905
1906
Igor Sysoev899b44e2005-05-12 14:58:06 +00001907static void
1908ngx_http_writer(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001909{
1910 int rc;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001911 ngx_event_t *wev;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001912 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001913 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001914
Igor Sysoev899b44e2005-05-12 14:58:06 +00001915 c = r->connection;
1916 wev = c->write;
Igor Sysoev160d7742003-11-19 16:26:41 +00001917
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001918 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1919 "http writer handler: \"%V?%V\"", &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001920
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001921 if (wev->timedout) {
Igor Sysoevef066482004-06-21 15:59:32 +00001922 if (!wev->delayed) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001923 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
1924 "client timed out");
1925 c->timedout = 1;
Igor Sysoev055951d2005-10-21 19:12:18 +00001926
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001927 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001928 return;
1929 }
1930
1931 wev->timedout = 0;
Igor Sysoevef066482004-06-21 15:59:32 +00001932 wev->delayed = 0;
Igor Sysoev73a73b52004-06-20 19:54:15 +00001933
1934 if (!wev->ready) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001935 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001936 ngx_add_timer(wev, clcf->send_timeout);
1937
Igor Sysoev924bd792004-10-11 15:07:03 +00001938 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001939 ngx_http_close_request(r, 0);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001940 }
1941
1942 return;
1943 }
1944
1945 } else {
Igor Sysoevef066482004-06-21 15:59:32 +00001946 if (wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001947 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1948 "http writer delayed");
Igor Sysoevef066482004-06-21 15:59:32 +00001949
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001950 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001951
Igor Sysoev924bd792004-10-11 15:07:03 +00001952 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001953 ngx_http_close_request(r, 0);
Igor Sysoevef066482004-06-21 15:59:32 +00001954 }
1955
Igor Sysoev73a73b52004-06-20 19:54:15 +00001956 return;
1957 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001958 }
1959
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001960 rc = ngx_http_output_filter(r, NULL);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001961
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001962 if (c->destroyed) {
1963 return;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001964 }
1965
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001966 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
1967 "http writer output filter: %d, \"%V?%V\"",
1968 rc, &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001969
1970 if (rc == NGX_AGAIN) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001971 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001972 if (!wev->ready && !wev->delayed) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001973 ngx_add_timer(wev, clcf->send_timeout);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001974 }
1975
Igor Sysoev924bd792004-10-11 15:07:03 +00001976 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001977 ngx_http_close_request(r, 0);
Igor Sysoev0a280a32003-10-12 16:49:16 +00001978 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001979
Igor Sysoev020ffea2006-10-30 20:25:22 +00001980 if (r == r->main || r->buffered) {
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001981 return;
1982 }
1983
1984 rc = NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001985 }
1986
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001987 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1988 "http writer done: \"%V?%V\"", &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001989
Igor Sysoev0a280a32003-10-12 16:49:16 +00001990 ngx_http_finalize_request(r, rc);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001991}
1992
1993
Igor Sysoev7ab4d9c2007-08-06 15:22:40 +00001994void
1995ngx_http_block_reading(ngx_http_request_t *r)
Igor Sysoev899b44e2005-05-12 14:58:06 +00001996{
Igor Sysoevf53d0f32007-07-10 20:53:45 +00001997 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev7ab4d9c2007-08-06 15:22:40 +00001998 "http reading blocked");
Igor Sysoevf53d0f32007-07-10 20:53:45 +00001999
2000 /* aio does not call this handler */
2001
2002 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
2003 && r->connection->read->active)
2004 {
2005 if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0)
2006 == NGX_ERROR)
2007 {
2008 ngx_http_close_request(r, 0);
2009 }
2010 }
2011}
2012
2013
2014static void
Igor Sysoev7ab4d9c2007-08-06 15:22:40 +00002015ngx_http_test_reading(ngx_http_request_t *r)
Igor Sysoevf53d0f32007-07-10 20:53:45 +00002016{
Igor Sysoev8d6de942007-01-19 08:10:06 +00002017 int n;
2018 char buf[1];
2019 ngx_err_t err;
2020 ngx_event_t *rev;
2021 ngx_connection_t *c;
2022
2023 c = r->connection;
2024 rev = c->read;
2025
Igor Sysoev7ab4d9c2007-08-06 15:22:40 +00002026 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading");
Igor Sysoev8d6de942007-01-19 08:10:06 +00002027
2028#if (NGX_HAVE_KQUEUE)
2029
2030 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2031
2032 if (!rev->pending_eof) {
2033 return;
2034 }
2035
2036 rev->eof = 1;
2037 c->error = 1;
2038 err = rev->kq_errno;
2039
2040 goto closed;
2041 }
2042
2043#endif
2044
2045 n = recv(c->fd, buf, 1, MSG_PEEK);
2046
2047 if (n == 0) {
2048 rev->eof = 1;
2049 c->error = 1;
2050 err = 0;
2051
2052 goto closed;
2053
2054 } else if (n == -1) {
2055 err = ngx_socket_errno;
2056
2057 if (err != NGX_EAGAIN) {
2058 rev->eof = 1;
2059 c->error = 1;
2060
2061 goto closed;
2062 }
2063 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002064
Igor Sysoev73009772003-02-06 17:21:13 +00002065 /* aio does not call this handler */
2066
Igor Sysoev8d6de942007-01-19 08:10:06 +00002067 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
2068
2069 if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00002070 ngx_http_close_request(r, 0);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00002071 }
Igor Sysoev73009772003-02-06 17:21:13 +00002072 }
Igor Sysoev8d6de942007-01-19 08:10:06 +00002073
2074 return;
2075
2076closed:
2077
2078 if (err) {
2079 rev->error = 1;
2080 }
2081
2082 ngx_log_error(NGX_LOG_INFO, c->log, err,
2083 "client closed prematurely connection");
2084
Igor Sysoevd74b66c2007-02-15 18:53:48 +00002085 ngx_http_finalize_request(r, 0);
Igor Sysoev42feecb2002-12-15 06:25:09 +00002086}
2087
2088
Igor Sysoevc1571722005-03-19 12:38:37 +00002089static void
2090ngx_http_set_keepalive(ngx_http_request_t *r)
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002091{
Igor Sysoev924bd792004-10-11 15:07:03 +00002092 int tcp_nodelay;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002093 ngx_int_t i;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002094 ngx_buf_t *b, *f;
Igor Sysoev187fcd82003-05-23 11:53:01 +00002095 ngx_event_t *rev, *wev;
2096 ngx_connection_t *c;
Igor Sysoevdd888c42004-09-21 05:38:28 +00002097 ngx_http_connection_t *hc;
Igor Sysoev187fcd82003-05-23 11:53:01 +00002098 ngx_http_core_srv_conf_t *cscf;
2099 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002100
Igor Sysoev6253ca12003-05-27 12:18:54 +00002101 c = r->connection;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00002102 rev = c->read;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002103
Igor Sysoev4fbd8682007-08-07 10:53:27 +00002104 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2105
Igor Sysoeve04084c2004-01-26 08:52:49 +00002106 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002107
Igor Sysoev4fbd8682007-08-07 10:53:27 +00002108 if (r->discard_body) {
2109 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
2110 ngx_add_timer(rev, clcf->lingering_timeout);
2111 return;
2112 }
2113
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002114 c->log->action = "closing request";
Igor Sysoevdd888c42004-09-21 05:38:28 +00002115
2116 hc = r->http_connection;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002117 b = r->header_in;
2118
Igor Sysoev236e0452004-09-23 16:39:34 +00002119 if (b->pos < b->last) {
Igor Sysoevf7abd722004-09-23 06:32:00 +00002120
Igor Sysoev236e0452004-09-23 16:39:34 +00002121 /* the pipelined request */
Igor Sysoevf7abd722004-09-23 06:32:00 +00002122
2123 if (b != c->buffer) {
2124
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002125 /*
2126 * If the large header buffers were allocated while the previous
2127 * request processing then we do not use c->buffer for
2128 * the pipelined request (see ngx_http_init_request()).
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002129 *
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002130 * Now we would move the large header buffers to the free list.
2131 */
Igor Sysoevf7abd722004-09-23 06:32:00 +00002132
2133 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2134
2135 if (hc->free == NULL) {
2136 hc->free = ngx_palloc(c->pool,
2137 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev236e0452004-09-23 16:39:34 +00002138
Igor Sysoevf7abd722004-09-23 06:32:00 +00002139 if (hc->free == NULL) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00002140 ngx_http_close_request(r, 0);
Igor Sysoevf7abd722004-09-23 06:32:00 +00002141 return;
2142 }
2143 }
2144
2145 for (i = 0; i < hc->nbusy - 1; i++) {
2146 f = hc->busy[i];
2147 hc->free[hc->nfree++] = f;
2148 f->pos = f->start;
2149 f->last = f->start;
2150 }
2151
2152 hc->busy[0] = b;
2153 hc->nbusy = 1;
2154 }
2155 }
2156
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002157 ngx_http_request_done(r, 0);
2158
Igor Sysoevdd888c42004-09-21 05:38:28 +00002159 c->data = hc;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002160
Igor Sysoevfa73aac2003-05-21 13:28:21 +00002161 ngx_add_timer(rev, clcf->keepalive_timeout);
2162
Igor Sysoev899b44e2005-05-12 14:58:06 +00002163 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00002164 ngx_http_close_connection(c);
2165 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00002166 }
2167
Igor Sysoev7b6062a2004-02-12 20:57:10 +00002168 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002169 wev->handler = ngx_http_empty_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00002170
Igor Sysoev369145c2004-05-28 15:49:23 +00002171 if (b->pos < b->last) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +00002172
Igor Sysoeve04084c2004-01-26 08:52:49 +00002173 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
Igor Sysoev6253ca12003-05-27 12:18:54 +00002174
Igor Sysoev055951d2005-10-21 19:12:18 +00002175#if (NGX_STAT_STUB)
2176 ngx_atomic_fetch_add(ngx_stat_reading, 1);
2177#endif
2178
Igor Sysoevdd888c42004-09-21 05:38:28 +00002179 hc->pipeline = 1;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002180 c->log->action = "reading client pipelined request line";
Igor Sysoev055951d2005-10-21 19:12:18 +00002181
Igor Sysoev48242f42008-05-19 10:24:22 +00002182 rev->handler = ngx_http_init_request;
2183 ngx_post_event(rev, &ngx_posted_events);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002184 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00002185 }
2186
Igor Sysoevdd888c42004-09-21 05:38:28 +00002187 hc->pipeline = 0;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00002188
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002189 /*
2190 * To keep a memory footprint as small as possible for an idle
2191 * keepalive connection we try to free the ngx_http_request_t and
2192 * c->buffer's memory if they were allocated outside the c->pool.
2193 * The large header buffers are always allocated outside the c->pool and
2194 * are freed too.
2195 */
2196
Igor Sysoev236e0452004-09-23 16:39:34 +00002197 if (ngx_pfree(c->pool, r) == NGX_OK) {
2198 hc->request = NULL;
2199 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00002200
Igor Sysoev236e0452004-09-23 16:39:34 +00002201 b = c->buffer;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002202
Igor Sysoev236e0452004-09-23 16:39:34 +00002203 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002204
2205 /*
2206 * the special note for ngx_http_keepalive_handler() that
2207 * c->buffer's memory was freed
2208 */
2209
Igor Sysoev236e0452004-09-23 16:39:34 +00002210 b->pos = NULL;
2211
2212 } else {
2213 b->pos = b->start;
2214 b->last = b->start;
2215 }
2216
Igor Sysoev1b735832004-11-11 14:07:14 +00002217 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00002218 hc->free, hc->nfree);
2219
2220 if (hc->free) {
2221 for (i = 0; i < hc->nfree; i++) {
Igor Sysoevacb2f5d2007-12-12 15:42:39 +00002222 ngx_pfree(c->pool, hc->free[i]->start);
Igor Sysoev236e0452004-09-23 16:39:34 +00002223 hc->free[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002224 }
2225
Igor Sysoev236e0452004-09-23 16:39:34 +00002226 hc->nfree = 0;
2227 }
2228
Igor Sysoev1b735832004-11-11 14:07:14 +00002229 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00002230 hc->busy, hc->nbusy);
2231
2232 if (hc->busy) {
2233 for (i = 0; i < hc->nbusy; i++) {
Igor Sysoevacb2f5d2007-12-12 15:42:39 +00002234 ngx_pfree(c->pool, hc->busy[i]->start);
Igor Sysoev236e0452004-09-23 16:39:34 +00002235 hc->busy[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002236 }
2237
Igor Sysoev236e0452004-09-23 16:39:34 +00002238 hc->nbusy = 0;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002239 }
2240
Igor Sysoevcd2aa8e2007-12-26 21:07:30 +00002241#if (NGX_HTTP_SSL)
2242 if (c->ssl) {
2243 ngx_ssl_free_buffer(c);
2244 }
2245#endif
2246
Igor Sysoev899b44e2005-05-12 14:58:06 +00002247 rev->handler = ngx_http_keepalive_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00002248
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002249 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2250 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
2251 ngx_http_close_connection(c);
2252 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00002253 }
2254 }
2255
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002256 c->log->action = "keepalive";
Igor Sysoev6a644c62003-03-04 06:33:48 +00002257
Igor Sysoev67f450d2004-06-01 06:04:46 +00002258 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
Igor Sysoevc1571722005-03-19 12:38:37 +00002259 if (ngx_tcp_push(c->fd) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00002260 ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
2261 ngx_http_close_connection(c);
2262 return;
Igor Sysoev9cf78302003-06-04 17:28:33 +00002263 }
Igor Sysoev924bd792004-10-11 15:07:03 +00002264
Igor Sysoev67f450d2004-06-01 06:04:46 +00002265 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
Igor Sysoev42b12b32004-12-02 18:40:46 +00002266 tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
Igor Sysoev924bd792004-10-11 15:07:03 +00002267
2268 } else {
Igor Sysoev42b12b32004-12-02 18:40:46 +00002269 tcp_nodelay = 1;
2270 }
Igor Sysoev924bd792004-10-11 15:07:03 +00002271
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002272 if (tcp_nodelay
2273 && clcf->tcp_nodelay
2274 && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
2275 {
Igor Sysoev42b12b32004-12-02 18:40:46 +00002276 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
Igor Sysoev924bd792004-10-11 15:07:03 +00002277
Igor Sysoev42b12b32004-12-02 18:40:46 +00002278 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
Igor Sysoevcdf609a2006-04-17 19:55:41 +00002279 (const void *) &tcp_nodelay, sizeof(int))
2280 == -1)
Igor Sysoev42b12b32004-12-02 18:40:46 +00002281 {
2282 ngx_connection_error(c, ngx_socket_errno,
2283 "setsockopt(TCP_NODELAY) failed");
2284 ngx_http_close_connection(c);
2285 return;
Igor Sysoev924bd792004-10-11 15:07:03 +00002286 }
Igor Sysoev42b12b32004-12-02 18:40:46 +00002287
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002288 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
Igor Sysoev9cf78302003-06-04 17:28:33 +00002289 }
2290
Igor Sysoevf7abd722004-09-23 06:32:00 +00002291#if 0
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002292 /* if ngx_http_request_t was freed then we need some other place */
Igor Sysoevc83f6832004-06-24 07:53:37 +00002293 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002294#endif
Igor Sysoevc83f6832004-06-24 07:53:37 +00002295
Igor Sysoev4ddeff42007-03-19 13:20:15 +00002296 c->idle = 1;
2297
Igor Sysoevb5faed22003-10-29 08:30:44 +00002298 if (rev->ready) {
Igor Sysoev48242f42008-05-19 10:24:22 +00002299 ngx_post_event(rev, &ngx_posted_events);
Igor Sysoevb7387572003-03-11 20:38:13 +00002300 }
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002301}
2302
2303
Igor Sysoevc1571722005-03-19 12:38:37 +00002304static void
2305ngx_http_keepalive_handler(ngx_event_t *rev)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002306{
Igor Sysoevc1571722005-03-19 12:38:37 +00002307 size_t size;
2308 ssize_t n;
2309 ngx_buf_t *b;
2310 ngx_connection_t *c;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002311
Igor Sysoev0ad25372004-07-16 06:33:35 +00002312 c = rev->data;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002313
Igor Sysoeve04084c2004-01-26 08:52:49 +00002314 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
Igor Sysoev1af7c822002-09-13 14:47:42 +00002315
Igor Sysoev4ddeff42007-03-19 13:20:15 +00002316 if (rev->timedout || c->close) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002317 ngx_http_close_connection(c);
2318 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00002319 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002320
Igor Sysoevf6906042004-11-25 16:17:31 +00002321#if (NGX_HAVE_KQUEUE)
Igor Sysoev236e0452004-09-23 16:39:34 +00002322
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002323 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoevcdc46302005-12-07 14:51:31 +00002324 if (rev->pending_eof) {
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002325 c->log->handler = NULL;
Igor Sysoev236e0452004-09-23 16:39:34 +00002326 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
Igor Sysoev1b735832004-11-11 14:07:14 +00002327 "kevent() reported that client %V closed "
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002328 "keepalive connection", &c->addr_text);
Igor Sysoev42b12b32004-12-02 18:40:46 +00002329#if (NGX_HTTP_SSL)
2330 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00002331 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00002332 }
2333#endif
Igor Sysoev236e0452004-09-23 16:39:34 +00002334 ngx_http_close_connection(c);
2335 return;
2336 }
2337 }
2338
2339#endif
2340
Igor Sysoev236e0452004-09-23 16:39:34 +00002341 b = c->buffer;
2342 size = b->end - b->start;
2343
2344 if (b->pos == NULL) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002345
2346 /*
2347 * The c->buffer's memory was freed by ngx_http_set_keepalive().
2348 * However, the c->buffer->start and c->buffer->end were not changed
2349 * to keep the buffer size.
2350 */
2351
Igor Sysoevc1571722005-03-19 12:38:37 +00002352 b->pos = ngx_palloc(c->pool, size);
2353 if (b->pos == NULL) {
Igor Sysoev236e0452004-09-23 16:39:34 +00002354 ngx_http_close_connection(c);
2355 return;
2356 }
2357
2358 b->start = b->pos;
2359 b->last = b->pos;
2360 b->end = b->pos + size;
2361 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00002362
Igor Sysoev0a280a32003-10-12 16:49:16 +00002363 /*
2364 * MSIE closes a keepalive connection with RST flag
2365 * so we ignore ECONNRESET here.
2366 */
Igor Sysoevb7387572003-03-11 20:38:13 +00002367
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002368 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
Igor Sysoevb7387572003-03-11 20:38:13 +00002369 ngx_set_socket_errno(0);
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00002370
Igor Sysoev236e0452004-09-23 16:39:34 +00002371 n = c->recv(c, b->last, size);
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002372 c->log_error = NGX_ERROR_INFO;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002373
Igor Sysoevd581fd52003-05-13 16:02:32 +00002374 if (n == NGX_AGAIN) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002375 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002376 ngx_http_close_connection(c);
2377 }
2378
Igor Sysoevd581fd52003-05-13 16:02:32 +00002379 return;
2380 }
2381
2382 if (n == NGX_ERROR) {
2383 ngx_http_close_connection(c);
2384 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00002385 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002386
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002387 c->log->handler = NULL;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002388
2389 if (n == 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +00002390 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002391 "client %V closed keepalive connection", &c->addr_text);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002392 ngx_http_close_connection(c);
2393 return;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002394 }
2395
Igor Sysoevf7abd722004-09-23 06:32:00 +00002396 b->last += n;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002397
Igor Sysoev055951d2005-10-21 19:12:18 +00002398#if (NGX_STAT_STUB)
2399 ngx_atomic_fetch_add(ngx_stat_reading, 1);
2400#endif
2401
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002402 c->log->handler = ngx_http_log_error;
2403 c->log->action = "reading client request line";
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002404
Igor Sysoev4ddeff42007-03-19 13:20:15 +00002405 c->idle = 0;
2406
Igor Sysoevd581fd52003-05-13 16:02:32 +00002407 ngx_http_init_request(rev);
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002408}
2409
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002410
Igor Sysoevc1571722005-03-19 12:38:37 +00002411static void
2412ngx_http_set_lingering_close(ngx_http_request_t *r)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002413{
Igor Sysoev0a280a32003-10-12 16:49:16 +00002414 ngx_event_t *rev, *wev;
Igor Sysoevb7387572003-03-11 20:38:13 +00002415 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002416 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002417
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002418 c = r->connection;
Igor Sysoev9b25d692003-01-26 21:08:14 +00002419
Igor Sysoev6253ca12003-05-27 12:18:54 +00002420 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002421
Igor Sysoev0a280a32003-10-12 16:49:16 +00002422 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002423 rev->handler = ngx_http_lingering_close_handler;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002424
Igor Sysoev208eed22005-10-07 13:30:52 +00002425 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
Igor Sysoev6253ca12003-05-27 12:18:54 +00002426 ngx_add_timer(rev, clcf->lingering_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +00002427
Igor Sysoev899b44e2005-05-12 14:58:06 +00002428 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00002429 ngx_http_close_request(r, 0);
Igor Sysoev0a280a32003-10-12 16:49:16 +00002430 return;
2431 }
2432
2433 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002434 wev->handler = ngx_http_empty_handler;
Igor Sysoev0a280a32003-10-12 16:49:16 +00002435
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002436 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2437 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
2438 ngx_http_close_request(r, 0);
2439 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00002440 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002441 }
2442
Igor Sysoevb7387572003-03-11 20:38:13 +00002443 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00002444 ngx_connection_error(c, ngx_socket_errno,
2445 ngx_shutdown_socket_n " failed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002446 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002447 return;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002448 }
2449
Igor Sysoevb5faed22003-10-29 08:30:44 +00002450 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002451 ngx_http_lingering_close_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00002452 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002453}
2454
2455
Igor Sysoevc1571722005-03-19 12:38:37 +00002456static void
2457ngx_http_lingering_close_handler(ngx_event_t *rev)
Igor Sysoev42feecb2002-12-15 06:25:09 +00002458{
Igor Sysoevdc479b42003-03-20 16:09:44 +00002459 ssize_t n;
2460 ngx_msec_t timer;
2461 ngx_connection_t *c;
2462 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002463 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002464 u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
Igor Sysoev1af7c822002-09-13 14:47:42 +00002465
Igor Sysoev6253ca12003-05-27 12:18:54 +00002466 c = rev->data;
2467 r = c->data;
Igor Sysoev86de4cb2003-01-30 07:28:09 +00002468
Igor Sysoeve04084c2004-01-26 08:52:49 +00002469 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2470 "http lingering close handler");
Igor Sysoevdc479b42003-03-20 16:09:44 +00002471
2472 if (rev->timedout) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002473 c->timedout = 1;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002474 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002475 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002476 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002477
Igor Sysoev1d04b142007-11-15 14:26:36 +00002478 timer = (ngx_msec_t) (r->lingering_time - ngx_time());
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002479 if (timer <= 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002480 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002481 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002482 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002483
Igor Sysoevdc479b42003-03-20 16:09:44 +00002484 do {
Igor Sysoevf7abd722004-09-23 06:32:00 +00002485 n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002486
Igor Sysoeve04084c2004-01-26 08:52:49 +00002487 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002488
Igor Sysoevdc479b42003-03-20 16:09:44 +00002489 if (n == NGX_ERROR || n == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002490 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002491 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002492 }
2493
2494 } while (rev->ready);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002495
Igor Sysoev899b44e2005-05-12 14:58:06 +00002496 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00002497 ngx_http_close_request(r, 0);
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002498 return;
2499 }
2500
Igor Sysoevf7abd722004-09-23 06:32:00 +00002501 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2502
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002503 timer *= 1000;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002504
Igor Sysoev6253ca12003-05-27 12:18:54 +00002505 if (timer > clcf->lingering_timeout) {
2506 timer = clcf->lingering_timeout;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002507 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002508
Igor Sysoevdc479b42003-03-20 16:09:44 +00002509 ngx_add_timer(rev, timer);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002510}
2511
Igor Sysoev2b542382002-08-20 14:48:28 +00002512
Igor Sysoevc1571722005-03-19 12:38:37 +00002513void
2514ngx_http_empty_handler(ngx_event_t *wev)
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002515{
Igor Sysoeve04084c2004-01-26 08:52:49 +00002516 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002517
2518 return;
2519}
2520
2521
Igor Sysoev899b44e2005-05-12 14:58:06 +00002522void
2523ngx_http_request_empty_handler(ngx_http_request_t *r)
2524{
2525 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002526 "http request empty handler");
Igor Sysoev899b44e2005-05-12 14:58:06 +00002527
2528 return;
2529}
2530
2531
Igor Sysoevc1571722005-03-19 12:38:37 +00002532ngx_int_t
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002533ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002534{
Igor Sysoev369145c2004-05-28 15:49:23 +00002535 ngx_buf_t *b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002536 ngx_chain_t out;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002537
Igor Sysoevc1571722005-03-19 12:38:37 +00002538 b = ngx_calloc_buf(r->pool);
2539 if (b == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +00002540 return NGX_ERROR;
2541 }
2542
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002543 if (flags & NGX_HTTP_LAST) {
2544 b->last_buf = 1;
2545 }
2546
2547 if (flags & NGX_HTTP_FLUSH) {
2548 b->flush = 1;
2549 }
2550
Igor Sysoev369145c2004-05-28 15:49:23 +00002551 out.buf = b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002552 out.next = NULL;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002553
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002554 return ngx_http_output_filter(r, &out);
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002555}
2556
2557
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002558static ngx_int_t
2559ngx_http_post_action(ngx_http_request_t *r)
2560{
2561 ngx_http_core_loc_conf_t *clcf;
2562
2563 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2564
2565 if (clcf->post_action.data == NULL) {
2566 return NGX_DECLINED;
2567 }
2568
Igor Sysoev8fea8852006-03-15 09:53:04 +00002569 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2570 "post action: \"%V\"", &clcf->post_action);
2571
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002572 r->http_version = NGX_HTTP_VERSION_9;
2573 r->header_only = 1;
Igor Sysoev6d16e1e2006-04-05 13:40:54 +00002574 r->post_action = 1;
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002575
Igor Sysoev7ab4d9c2007-08-06 15:22:40 +00002576 r->read_event_handler = ngx_http_block_reading;
Igor Sysoevcf100a72006-12-11 08:31:54 +00002577
Igor Sysoevce307652008-02-15 12:46:40 +00002578 if (clcf->post_action.data[0] == '/') {
2579 ngx_http_internal_redirect(r, &clcf->post_action, NULL);
2580
2581 } else {
2582 ngx_http_named_location(r, &clcf->post_action);
2583 }
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002584
2585 return NGX_OK;
2586}
2587
2588
2589static void
Igor Sysoev899b44e2005-05-12 14:58:06 +00002590ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error)
Igor Sysoevd581fd52003-05-13 16:02:32 +00002591{
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002592 ngx_connection_t *c;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002593
2594 c = r->connection;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002595
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002596 ngx_http_request_done(r->main, error);
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002597 ngx_http_close_connection(c);
2598}
2599
2600
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002601static void
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002602ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error)
2603{
2604 ngx_log_t *log;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002605 ngx_uint_t i, n;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002606 struct linger linger;
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002607 ngx_http_cleanup_t *cln;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002608 ngx_http_log_ctx_t *ctx;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002609 ngx_http_handler_pt *log_handler;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002610 ngx_http_core_loc_conf_t *clcf;
2611 ngx_http_core_main_conf_t *cmcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002612
Igor Sysoev865c1502003-11-30 20:03:18 +00002613 log = r->connection->log;
2614
2615 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002616
2617 if (r->pool == NULL) {
Igor Sysoev90c08142005-07-25 09:41:38 +00002618 ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002619 return;
2620 }
2621
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002622 for (cln = r->cleanup; cln; cln = cln->next) {
2623 if (cln->handler) {
2624 cln->handler(cln->data);
2625 }
2626 }
2627
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002628#if (NGX_STAT_STUB)
Igor Sysoev055951d2005-10-21 19:12:18 +00002629
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002630 if (r->stat_reading) {
Igor Sysoev78452232005-10-12 13:50:36 +00002631 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002632 }
2633
2634 if (r->stat_writing) {
Igor Sysoev78452232005-10-12 13:50:36 +00002635 ngx_atomic_fetch_add(ngx_stat_writing, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002636 }
Igor Sysoev055951d2005-10-21 19:12:18 +00002637
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002638#endif
2639
Igor Sysoev669e3312003-12-22 09:40:48 +00002640 if (error && r->headers_out.status == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002641 r->headers_out.status = error;
2642 }
2643
Igor Sysoev504efff2008-06-30 15:32:57 +00002644 log->action = "logging request";
2645
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002646 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2647
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002648 log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
2649 n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
2650 for (i = 0; i < n; i++) {
2651 log_handler[i](r);
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002652 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00002653
Igor Sysoev504efff2008-06-30 15:32:57 +00002654 log->action = "closing request";
2655
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002656 if (r->connection->timedout) {
2657 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2658
2659 if (clcf->reset_timedout_connection) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002660 linger.l_onoff = 1;
2661 linger.l_linger = 0;
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002662
2663 if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
Igor Sysoev899b44e2005-05-12 14:58:06 +00002664 (const void *) &linger, sizeof(struct linger)) == -1)
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002665 {
2666 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
2667 "setsockopt(SO_LINGER) failed");
2668 }
2669 }
2670 }
2671
Igor Sysoev899b44e2005-05-12 14:58:06 +00002672 /* the various request strings were allocated from r->pool */
Igor Sysoev865c1502003-11-30 20:03:18 +00002673 ctx = log->data;
Igor Sysoev1b735832004-11-11 14:07:14 +00002674 ctx->request = NULL;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002675
Igor Sysoevc83f6832004-06-24 07:53:37 +00002676 r->request_line.len = 0;
2677
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002678 r->connection->destroyed = 1;
2679
Igor Sysoevd581fd52003-05-13 16:02:32 +00002680 ngx_destroy_pool(r->pool);
2681}
2682
2683
Igor Sysoev90c08142005-07-25 09:41:38 +00002684static void
Igor Sysoevc1571722005-03-19 12:38:37 +00002685ngx_http_close_connection(ngx_connection_t *c)
Igor Sysoev6b863e32003-05-12 15:52:24 +00002686{
Igor Sysoev02025fd2005-01-18 13:03:58 +00002687 ngx_pool_t *pool;
2688
Igor Sysoeve04084c2004-01-26 08:52:49 +00002689 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev54498db2004-02-11 17:08:49 +00002690 "close http connection: %d", c->fd);
Igor Sysoev6b863e32003-05-12 15:52:24 +00002691
Igor Sysoevceb99292005-09-06 16:09:32 +00002692#if (NGX_HTTP_SSL)
Igor Sysoev924bd792004-10-11 15:07:03 +00002693
2694 if (c->ssl) {
2695 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002696 c->ssl->handler = ngx_http_close_connection;
Igor Sysoev924bd792004-10-11 15:07:03 +00002697 return;
2698 }
2699 }
2700
2701#endif
2702
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002703#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +00002704 ngx_atomic_fetch_add(ngx_stat_active, -1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002705#endif
2706
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002707 c->destroyed = 1;
2708
Igor Sysoev02025fd2005-01-18 13:03:58 +00002709 pool = c->pool;
2710
Igor Sysoev59cf56c2004-09-07 15:29:22 +00002711 ngx_close_connection(c);
Igor Sysoev02025fd2005-01-18 13:03:58 +00002712
Igor Sysoevc1571722005-03-19 12:38:37 +00002713 ngx_destroy_pool(pool);
Igor Sysoev2ba1ee02002-10-04 17:58:04 +00002714}
2715
2716
Igor Sysoevc1571722005-03-19 12:38:37 +00002717static u_char *
2718ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002719{
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002720 u_char *p;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002721 ngx_http_request_t *r;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002722 ngx_http_log_ctx_t *ctx;
Igor Sysoev7578ec92003-06-02 15:24:30 +00002723
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002724 if (log->action) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002725 p = ngx_snprintf(buf, len, " while %s", log->action);
Igor Sysoev1b735832004-11-11 14:07:14 +00002726 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002727 buf = p;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002728 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002729
Igor Sysoev899b44e2005-05-12 14:58:06 +00002730 ctx = log->data;
2731
Igor Sysoevcc595672007-12-30 08:01:50 +00002732 p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text);
Igor Sysoev899b44e2005-05-12 14:58:06 +00002733 len -= p - buf;
Igor Sysoev1b735832004-11-11 14:07:14 +00002734
Igor Sysoevc04deca2005-03-28 14:43:02 +00002735 r = ctx->request;
2736
Igor Sysoev899b44e2005-05-12 14:58:06 +00002737 if (r) {
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002738 return r->log_handler(r, ctx->current_request, p, len);
Igor Sysoevcc595672007-12-30 08:01:50 +00002739
2740 } else {
2741 p = ngx_snprintf(p, len, ", server: %V",
2742 &ctx->connection->listening->addr_text);
Igor Sysoev1b735832004-11-11 14:07:14 +00002743 }
2744
Igor Sysoev899b44e2005-05-12 14:58:06 +00002745 return p;
2746}
2747
2748
2749static u_char *
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002750ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
2751 u_char *buf, size_t len)
Igor Sysoev899b44e2005-05-12 14:58:06 +00002752{
Igor Sysoevfeee7262007-12-30 08:15:27 +00002753 char *uri_separator;
2754 u_char *p;
2755 ngx_http_upstream_t *u;
2756 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev1b735832004-11-11 14:07:14 +00002757
Igor Sysoevfeee7262007-12-30 08:15:27 +00002758 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2759
2760 p = ngx_snprintf(buf, len, ", server: %V", &cscf->server_name);
2761 len -= p - buf;
2762 buf = p;
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002763
Igor Sysoeva6b59572007-11-27 12:22:01 +00002764 if (r->request_line.data == NULL && r->request_start) {
2765 for (p = r->request_start; p < r->header_in->last; p++) {
2766 if (*p == CR || *p == LF) {
2767 break;
2768 }
2769 }
2770
2771 r->request_line.len = p - r->request_start;
2772 r->request_line.data = r->request_start;
2773 }
2774
2775 if (r->request_line.len) {
2776 p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
Igor Sysoevc04deca2005-03-28 14:43:02 +00002777 len -= p - buf;
2778 buf = p;
Igor Sysoev1b735832004-11-11 14:07:14 +00002779 }
2780
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002781 if (r != sr) {
2782 p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
2783 len -= p - buf;
2784 buf = p;
2785 }
2786
2787 u = sr->upstream;
2788
Igor Sysoev3d2fd182006-12-04 16:46:13 +00002789 if (u && u->peer.name) {
2790
2791 uri_separator = "";
2792
2793#if (NGX_HAVE_UNIX_DOMAIN)
2794 if (u->peer.sockaddr && u->peer.sockaddr->sa_family == AF_UNIX) {
2795 uri_separator = ":";
2796 }
2797#endif
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002798
2799 p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
Igor Sysoev96dd8af2007-11-27 13:34:13 +00002800 &u->schema, u->peer.name,
Igor Sysoev3d2fd182006-12-04 16:46:13 +00002801 uri_separator, &u->uri);
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002802 len -= p - buf;
2803 buf = p;
2804 }
2805
Igor Sysoevc04deca2005-03-28 14:43:02 +00002806 if (r->headers_in.host) {
2807 p = ngx_snprintf(buf, len, ", host: \"%V\"",
2808 &r->headers_in.host->value);
2809 len -= p - buf;
2810 buf = p;
2811 }
2812
2813 if (r->headers_in.referer) {
2814 p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
2815 &r->headers_in.referer->value);
2816 buf = p;
2817 }
2818
2819 return buf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00002820}