blob: f6dcd6a5693181579e45c6b24b762fca214f00ac [file] [log] [blame]
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Igor Sysoevd90282d2004-09-28 08:34:51 +00004 */
5
6
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00007#include <ngx_config.h>
Igor Sysoev0ad17c02002-08-26 15:18:19 +00008#include <ngx_core.h>
Igor Sysoevfcce8d52003-01-23 18:47:54 +00009#include <ngx_event.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000010#include <ngx_http.h>
11
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000012
Igor Sysoev6b863e32003-05-12 15:52:24 +000013static void ngx_http_init_request(ngx_event_t *ev);
14static void ngx_http_process_request_line(ngx_event_t *rev);
15static void ngx_http_process_request_headers(ngx_event_t *rev);
Igor Sysoev6b863e32003-05-12 15:52:24 +000016static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
Igor Sysoevf7abd722004-09-23 06:32:00 +000017static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
Igor Sysoevc1571722005-03-19 12:38:37 +000018 ngx_uint_t request_line);
Igor Sysoev899b44e2005-05-12 14:58:06 +000019
20static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
21 ngx_table_elt_t *h, ngx_uint_t offset);
Igor Sysoevb145b062005-06-15 18:33:41 +000022static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
23 ngx_table_elt_t *h, ngx_uint_t offset);
Igor Sysoev899b44e2005-05-12 14:58:06 +000024static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r,
25 ngx_table_elt_t *h, ngx_uint_t offset);
26
Igor Sysoev2f657222004-06-16 15:32:11 +000027static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
Igor Sysoev3338cfd2006-05-11 14:43:47 +000028static void ngx_http_find_virtual_server(ngx_http_request_t *r,
29 ngx_http_virtual_names_t *vn, ngx_uint_t hash);
Igor Sysoev6b863e32003-05-12 15:52:24 +000030
Igor Sysoev899b44e2005-05-12 14:58:06 +000031static void ngx_http_request_handler(ngx_event_t *ev);
Igor Sysoev85ef94b2005-06-23 13:41:06 +000032static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
Igor Sysoev899b44e2005-05-12 14:58:06 +000033static void ngx_http_writer(ngx_http_request_t *r);
Igor Sysoev6b863e32003-05-12 15:52:24 +000034
Igor Sysoev899b44e2005-05-12 14:58:06 +000035static void ngx_http_block_read(ngx_http_request_t *r);
Igor Sysoevd581fd52003-05-13 16:02:32 +000036static void ngx_http_set_keepalive(ngx_http_request_t *r);
37static void ngx_http_keepalive_handler(ngx_event_t *ev);
38static void ngx_http_set_lingering_close(ngx_http_request_t *r);
39static void ngx_http_lingering_close_handler(ngx_event_t *ev);
Igor Sysoevc2807ec2006-02-16 15:26:46 +000040static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
Igor Sysoev90c08142005-07-25 09:41:38 +000041static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
Igor Sysoev9ac946b2005-10-24 15:09:41 +000042static void ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error);
Igor Sysoev90c08142005-07-25 09:41:38 +000043static void ngx_http_close_connection(ngx_connection_t *c);
Igor Sysoevd581fd52003-05-13 16:02:32 +000044
Igor Sysoeve5a222c2005-01-25 12:27:35 +000045static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
Igor Sysoevbb28b6d2006-07-11 13:20:19 +000046static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
47 ngx_http_request_t *sr, u_char *buf, size_t len);
Igor Sysoev0ad17c02002-08-26 15:18:19 +000048
Igor Sysoevceb99292005-09-06 16:09:32 +000049#if (NGX_HTTP_SSL)
50static void ngx_http_ssl_handshake(ngx_event_t *rev);
Igor Sysoev9fa5a822005-09-30 14:41:25 +000051static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
Igor Sysoevceb99292005-09-06 16:09:32 +000052#endif
53
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000054
Igor Sysoevc04deca2005-03-28 14:43:02 +000055static char *ngx_http_client_errors[] = {
Igor Sysoev0ad17c02002-08-26 15:18:19 +000056
Igor Sysoevc04deca2005-03-28 14:43:02 +000057 /* NGX_HTTP_PARSE_INVALID_METHOD */
58 "client sent invalid method",
Igor Sysoev6a644c62003-03-04 06:33:48 +000059
Igor Sysoevc04deca2005-03-28 14:43:02 +000060 /* NGX_HTTP_PARSE_INVALID_REQUEST */
61 "client sent invalid request",
62
63 /* NGX_HTTP_PARSE_INVALID_09_METHOD */
64 "client sent invalid method in HTTP/0.9 request"
Igor Sysoev016b8522002-08-29 16:59:54 +000065};
66
67
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000068ngx_http_header_t ngx_http_headers_in[] = {
Igor Sysoev899b44e2005-05-12 14:58:06 +000069 { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
Igor Sysoevb145b062005-06-15 18:33:41 +000070 ngx_http_process_unique_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000071
Igor Sysoev899b44e2005-05-12 14:58:06 +000072 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
Igor Sysoevb145b062005-06-15 18:33:41 +000073 ngx_http_process_unique_header_line },
Igor Sysoev899b44e2005-05-12 14:58:06 +000074
75 { ngx_string("If-Modified-Since"),
76 offsetof(ngx_http_headers_in_t, if_modified_since),
77 ngx_http_process_header_line },
78
79 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
80 ngx_http_process_header_line },
81
82 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
83 ngx_http_process_header_line },
84
85 { ngx_string("Content-Length"),
86 offsetof(ngx_http_headers_in_t, content_length),
Igor Sysoevb145b062005-06-15 18:33:41 +000087 ngx_http_process_unique_header_line },
Igor Sysoev899b44e2005-05-12 14:58:06 +000088
89 { ngx_string("Content-Type"),
90 offsetof(ngx_http_headers_in_t, content_type),
91 ngx_http_process_header_line },
92
93 { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
94 ngx_http_process_header_line },
95
Igor Sysoevc31a9bb2005-11-26 10:11:11 +000096 { ngx_string("Transfer-Encoding"),
97 offsetof(ngx_http_headers_in_t, transfer_encoding),
98 ngx_http_process_header_line },
99
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000100#if (NGX_HTTP_GZIP)
101 { ngx_string("Accept-Encoding"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000102 offsetof(ngx_http_headers_in_t, accept_encoding),
103 ngx_http_process_header_line },
104
105 { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
106 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000107#endif
108
109 { ngx_string("Authorization"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000110 offsetof(ngx_http_headers_in_t, authorization),
Igor Sysoevb145b062005-06-15 18:33:41 +0000111 ngx_http_process_unique_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000112
Igor Sysoev899b44e2005-05-12 14:58:06 +0000113 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
114 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000115
Igor Sysoev09c684b2005-11-09 17:25:55 +0000116#if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000117 { ngx_string("X-Forwarded-For"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000118 offsetof(ngx_http_headers_in_t, x_forwarded_for),
119 ngx_http_process_header_line },
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000120#endif
Igor Sysoev02025fd2005-01-18 13:03:58 +0000121
Igor Sysoev09c684b2005-11-09 17:25:55 +0000122#if (NGX_HTTP_REALIP)
123 { ngx_string("X-Real-IP"),
124 offsetof(ngx_http_headers_in_t, x_real_ip),
125 ngx_http_process_header_line },
126#endif
127
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000128#if (NGX_HTTP_HEADERS)
Igor Sysoev899b44e2005-05-12 14:58:06 +0000129 { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
130 ngx_http_process_header_line },
131
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000132 { ngx_string("Accept-Language"),
Igor Sysoev899b44e2005-05-12 14:58:06 +0000133 offsetof(ngx_http_headers_in_t, accept_language),
134 ngx_http_process_header_line },
Igor Sysoev1ebfead2005-02-16 13:40:36 +0000135#endif
136
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000137#if (NGX_HTTP_DAV)
138 { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
139 ngx_http_process_header_line },
140
141 { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
142 ngx_http_process_header_line },
Igor Sysoevda173ab2006-08-30 10:39:17 +0000143
144 { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
145 ngx_http_process_header_line },
Igor Sysoev7bdb7202006-04-19 15:30:56 +0000146#endif
147
Igor Sysoev899b44e2005-05-12 14:58:06 +0000148 { ngx_string("Cookie"), 0, ngx_http_process_cookie },
149
150 { ngx_null_string, 0, NULL }
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000151};
152
153
Igor Sysoevc1571722005-03-19 12:38:37 +0000154void
155ngx_http_init_connection(ngx_connection_t *c)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000156{
Igor Sysoev6253ca12003-05-27 12:18:54 +0000157 ngx_event_t *rev;
Igor Sysoev160d7742003-11-19 16:26:41 +0000158 ngx_http_log_ctx_t *ctx;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000159
Igor Sysoevc1571722005-03-19 12:38:37 +0000160 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
161 if (ctx == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000162 ngx_http_close_connection(c);
163 return;
164 }
165
Igor Sysoev1b735832004-11-11 14:07:14 +0000166 ctx->client = &c->addr_text;
Igor Sysoev1b735832004-11-11 14:07:14 +0000167 ctx->request = NULL;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +0000168 ctx->current_request = NULL;
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000169
170 c->log->connection = c->number;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000171 c->log->handler = ngx_http_log_error;
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000172 c->log->data = ctx;
173 c->log->action = "reading client request line";
174
Igor Sysoevc7a2f682004-02-10 16:23:38 +0000175 c->log_error = NGX_ERROR_INFO;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000176
Igor Sysoevdc479b42003-03-20 16:09:44 +0000177 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000178 rev->handler = ngx_http_init_request;
Igor Sysoev9ac946b2005-10-24 15:09:41 +0000179 c->write->handler = ngx_http_empty_handler;
Igor Sysoev7af6b162004-02-09 07:46:43 +0000180
Igor Sysoev055951d2005-10-21 19:12:18 +0000181#if (NGX_STAT_STUB)
182 ngx_atomic_fetch_add(ngx_stat_reading, 1);
183#endif
184
Igor Sysoevdc479b42003-03-20 16:09:44 +0000185 if (rev->ready) {
Igor Sysoev0ab91b92004-06-06 19:49:18 +0000186 /* the deferred accept(), rtsig, aio, iocp */
Igor Sysoev709405b2004-03-31 15:26:46 +0000187
Igor Sysoevffe71442006-02-08 15:33:12 +0000188 if (ngx_use_accept_mutex) {
Igor Sysoevc2068d02005-10-19 12:33:58 +0000189 ngx_post_event(rev, &ngx_posted_events);
Igor Sysoev709405b2004-03-31 15:26:46 +0000190 return;
191 }
192
Igor Sysoev6b863e32003-05-12 15:52:24 +0000193 ngx_http_init_request(rev);
194 return;
Igor Sysoev016b8522002-08-29 16:59:54 +0000195 }
Igor Sysoev73009772003-02-06 17:21:13 +0000196
Igor Sysoev239baac2003-06-11 15:28:34 +0000197 ngx_add_timer(rev, c->listening->post_accept_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000198
Igor Sysoevb5faed22003-10-29 08:30:44 +0000199 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev055951d2005-10-21 19:12:18 +0000200#if (NGX_STAT_STUB)
201 ngx_atomic_fetch_add(ngx_stat_reading, -1);
202#endif
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000203 ngx_http_close_connection(c);
204 return;
205 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000206}
207
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000208
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000209static void
210ngx_http_init_request(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000211{
Igor Sysoev09c684b2005-11-09 17:25:55 +0000212 socklen_t len;
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000213 ngx_uint_t i;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000214 struct sockaddr_in sin;
215 ngx_connection_t *c;
216 ngx_http_request_t *r;
Igor Sysoev305a9d82005-12-26 17:07:48 +0000217 ngx_http_in_port_t *hip;
218 ngx_http_in_addr_t *hia;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000219 ngx_http_log_ctx_t *ctx;
220 ngx_http_connection_t *hc;
Igor Sysoev09c684b2005-11-09 17:25:55 +0000221 ngx_http_core_srv_conf_t *cscf;
222 ngx_http_core_loc_conf_t *clcf;
223 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000224#if (NGX_HTTP_SSL)
Igor Sysoev09c684b2005-11-09 17:25:55 +0000225 ngx_http_ssl_srv_conf_t *sscf;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000226#endif
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000227
Igor Sysoev055951d2005-10-21 19:12:18 +0000228#if (NGX_STAT_STUB)
229 ngx_atomic_fetch_add(ngx_stat_reading, -1);
230#endif
231
Igor Sysoeva9830112003-05-19 16:39:14 +0000232 c = rev->data;
Igor Sysoeva9830112003-05-19 16:39:14 +0000233
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000234 if (rev->timedout) {
235 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000236
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000237 ngx_http_close_connection(c);
238 return;
239 }
240
Igor Sysoevf7abd722004-09-23 06:32:00 +0000241 hc = c->data;
Igor Sysoevdd888c42004-09-21 05:38:28 +0000242
Igor Sysoev055951d2005-10-21 19:12:18 +0000243 if (hc == NULL) {
Igor Sysoevc1571722005-03-19 12:38:37 +0000244 hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
245 if (hc == NULL) {
Igor Sysoevdd888c42004-09-21 05:38:28 +0000246 ngx_http_close_connection(c);
247 return;
248 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000249 }
Igor Sysoevdd888c42004-09-21 05:38:28 +0000250
Igor Sysoevf7abd722004-09-23 06:32:00 +0000251 r = hc->request;
252
253 if (r) {
254 ngx_memzero(r, sizeof(ngx_http_request_t));
255
256 r->pipeline = hc->pipeline;
257
258 if (hc->nbusy) {
259 r->header_in = hc->busy[0];
260 }
261
Igor Sysoevf7abd722004-09-23 06:32:00 +0000262 } else {
Igor Sysoevc1571722005-03-19 12:38:37 +0000263 r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
264 if (r == NULL) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000265 ngx_http_close_connection(c);
266 return;
267 }
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000268
Igor Sysoevdd888c42004-09-21 05:38:28 +0000269 hc->request = r;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000270 }
271
Igor Sysoevdd888c42004-09-21 05:38:28 +0000272 c->data = r;
273 r->http_connection = hc;
274
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000275 c->sent = 0;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000276 r->signature = NGX_HTTP_MODULE;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000277
Igor Sysoev6253ca12003-05-27 12:18:54 +0000278 /* find the server configuration for the address:port */
279
280 /* AF_INET only */
281
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000282 hip = c->listening->servers;
Igor Sysoev305a9d82005-12-26 17:07:48 +0000283 hia = hip->addrs;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000284
Igor Sysoev305a9d82005-12-26 17:07:48 +0000285 r->port = hip->port;
286 r->port_text = &hip->port_text;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000287
288 i = 0;
289
Igor Sysoev305a9d82005-12-26 17:07:48 +0000290 if (hip->naddrs > 1) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000291
Igor Sysoev239baac2003-06-11 15:28:34 +0000292 /*
Igor Sysoevd00b3652004-08-23 19:09:29 +0000293 * There are several addresses on this port and one of them
294 * is the "*:port" wildcard so getsockname() is needed to determine
Igor Sysoev239baac2003-06-11 15:28:34 +0000295 * the server address.
Igor Sysoevd00b3652004-08-23 19:09:29 +0000296 *
Igor Sysoev239baac2003-06-11 15:28:34 +0000297 * AcceptEx() already gave this address.
298 */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000299
Igor Sysoev1b735832004-11-11 14:07:14 +0000300#if (NGX_WIN32)
Igor Sysoev239baac2003-06-11 15:28:34 +0000301 if (c->local_sockaddr) {
302 r->in_addr =
303 ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000304
Igor Sysoev02025fd2005-01-18 13:03:58 +0000305 } else
Igor Sysoev239baac2003-06-11 15:28:34 +0000306#endif
Igor Sysoev02025fd2005-01-18 13:03:58 +0000307 {
Igor Sysoev239baac2003-06-11 15:28:34 +0000308 len = sizeof(struct sockaddr_in);
Igor Sysoev02025fd2005-01-18 13:03:58 +0000309 if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000310 ngx_connection_error(c, ngx_socket_errno,
311 "getsockname() failed");
Igor Sysoev239baac2003-06-11 15:28:34 +0000312 ngx_http_close_connection(c);
313 return;
314 }
Igor Sysoev10a543a2004-03-16 07:10:12 +0000315
Igor Sysoev02025fd2005-01-18 13:03:58 +0000316 r->in_addr = sin.sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000317 }
318
Igor Sysoev7f7846d2006-04-26 09:52:47 +0000319 /* the last address is "*" */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000320
Igor Sysoev305a9d82005-12-26 17:07:48 +0000321 for ( /* void */ ; i < hip->naddrs - 1; i++) {
322 if (hia[i].addr == r->in_addr) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000323 break;
324 }
325 }
326
327 } else {
Igor Sysoev305a9d82005-12-26 17:07:48 +0000328 r->in_addr = hia[0].addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000329 }
330
Igor Sysoev305a9d82005-12-26 17:07:48 +0000331 r->virtual_names = hia[i].virtual_names;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000332
333 /* the default server configuration for the address:port */
Igor Sysoev305a9d82005-12-26 17:07:48 +0000334 cscf = hia[i].core_srv_conf;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000335
336 r->main_conf = cscf->ctx->main_conf;
337 r->srv_conf = cscf->ctx->srv_conf;
338 r->loc_conf = cscf->ctx->loc_conf;
339
Igor Sysoev305a9d82005-12-26 17:07:48 +0000340 r->server_name = cscf->server_name;
341
Igor Sysoev899b44e2005-05-12 14:58:06 +0000342 rev->handler = ngx_http_process_request_line;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000343
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000344#if (NGX_HTTP_SSL)
345
Igor Sysoevf38e0462004-07-16 17:11:43 +0000346 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000347 if (sscf->enable) {
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000348
349 if (c->ssl == NULL) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000350 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
Igor Sysoev02f742b2005-04-08 15:18:55 +0000351 == NGX_ERROR)
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000352 {
353 ngx_http_close_connection(c);
354 return;
355 }
356
Igor Sysoev899b44e2005-05-12 14:58:06 +0000357 rev->handler = ngx_http_ssl_handshake;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000358 }
359
Igor Sysoevd52477f2005-05-16 13:53:20 +0000360 r->main_filter_need_in_memory = 1;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000361 }
362
Igor Sysoev4aa88882004-07-14 20:07:58 +0000363#endif
364
Igor Sysoev890fc962003-07-20 21:15:59 +0000365 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
366 c->log->file = clcf->err_log->file;
Igor Sysoevfff32322004-04-08 15:58:25 +0000367 if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
368 c->log->log_level = clcf->err_log->log_level;
369 }
Igor Sysoev890fc962003-07-20 21:15:59 +0000370
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000371 if (c->buffer == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +0000372 c->buffer = ngx_create_temp_buf(c->pool,
373 cscf->client_header_buffer_size);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000374 if (c->buffer == NULL) {
375 ngx_http_close_connection(c);
376 return;
377 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000378 }
379
Igor Sysoevf7abd722004-09-23 06:32:00 +0000380 if (r->header_in == NULL) {
381 r->header_in = c->buffer;
382 }
383
Igor Sysoevc1571722005-03-19 12:38:37 +0000384 r->pool = ngx_create_pool(cscf->request_pool_size, c->log);
385 if (r->pool == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000386 ngx_http_close_connection(c);
387 return;
388 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000389
Igor Sysoev89690bf2004-03-23 06:01:52 +0000390
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000391 if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000392 sizeof(ngx_table_elt_t))
393 == NGX_ERROR)
Igor Sysoev980a9242004-09-05 19:54:02 +0000394 {
395 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev980a9242004-09-05 19:54:02 +0000396 return;
397 }
398
Igor Sysoev6b863e32003-05-12 15:52:24 +0000399 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
400 if (r->ctx == NULL) {
401 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000402 return;
403 }
Igor Sysoeve0268b92002-09-11 15:18:33 +0000404
Igor Sysoev09c684b2005-11-09 17:25:55 +0000405 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
406
407 r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
408 * sizeof(ngx_http_variable_value_t));
409 if (r->variables == NULL) {
410 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
411 return;
412 }
413
Igor Sysoevc78c41c2004-07-07 06:15:04 +0000414 c->single_connection = 1;
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000415 c->destroyed = 0;
416
Igor Sysoev6b863e32003-05-12 15:52:24 +0000417 r->connection = c;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000418
Igor Sysoevf6e1fe32005-10-04 10:38:53 +0000419 r->main = r;
420
Igor Sysoev11d75322005-03-01 15:20:36 +0000421 r->start_time = ngx_time();
422
Igor Sysoev94e32ce2006-04-07 14:08:04 +0000423 r->method = NGX_HTTP_UNKNOWN;
424
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000425 r->headers_in.content_length_n = -1;
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000426 r->headers_in.keep_alive_n = -1;
427 r->headers_out.content_length_n = -1;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000428 r->headers_out.last_modified_time = -1;
429
Igor Sysoevef316432006-08-16 13:09:33 +0000430 r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
431 r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;
432
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000433 r->http_state = NGX_HTTP_READING_REQUEST_STATE;
434
Igor Sysoevc04deca2005-03-28 14:43:02 +0000435 ctx = c->log->data;
436 ctx->request = r;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +0000437 ctx->current_request = r;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000438 r->log_handler = ngx_http_log_error_handler;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000439
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000440#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000441 ngx_atomic_fetch_add(ngx_stat_reading, 1);
Igor Sysoevb1dfe472004-12-21 12:30:30 +0000442 r->stat_reading = 1;
Igor Sysoev78452232005-10-12 13:50:36 +0000443 ngx_atomic_fetch_add(ngx_stat_requests, 1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000444#endif
445
Igor Sysoev899b44e2005-05-12 14:58:06 +0000446 rev->handler(rev);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000447}
448
449
450#if (NGX_HTTP_SSL)
451
Igor Sysoevc1571722005-03-19 12:38:37 +0000452static void
453ngx_http_ssl_handshake(ngx_event_t *rev)
Igor Sysoevf38e0462004-07-16 17:11:43 +0000454{
Igor Sysoevf38e0462004-07-16 17:11:43 +0000455 u_char buf[1];
Igor Sysoev1b735832004-11-11 14:07:14 +0000456 ssize_t n;
457 ngx_int_t rc;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000458 ngx_connection_t *c;
459 ngx_http_request_t *r;
460
461 c = rev->data;
462 r = c->data;
463
464 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
465 "http check ssl handshake");
466
467 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000468 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
469 c->timedout = 1;
470 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000471 return;
472 }
473
Igor Sysoevd3283ff2005-12-05 13:18:09 +0000474 n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000475
476 if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
477 return;
478 }
479
480 if (n == 1) {
481 if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
482 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000483 "https ssl handshake: 0x%02Xd", buf[0]);
Igor Sysoevf38e0462004-07-16 17:11:43 +0000484
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000485 rc = ngx_ssl_handshake(c);
486
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000487 if (rc == NGX_AGAIN) {
488 c->ssl->handler = ngx_http_ssl_handshake_handler;
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000489 return;
490 }
491
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000492 ngx_http_ssl_handshake_handler(c);
493
494 return;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000495
496 } else {
497 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
498 "plain http");
499
500 r->plain_http = 1;
501 }
502 }
503
Igor Sysoev899b44e2005-05-12 14:58:06 +0000504 rev->handler = ngx_http_process_request_line;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000505 ngx_http_process_request_line(rev);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000506}
507
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000508
509static void
510ngx_http_ssl_handshake_handler(ngx_connection_t *c)
511{
512 ngx_http_request_t *r;
513
514 if (c->ssl->handshaked) {
515
516 /*
517 * The majority of browsers do not send the "close notify" alert.
518 * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
519 * and Links. And what is more, MSIE ignores the server's alert.
520 *
521 * Opera and recent Mozilla send the alert.
522 */
523
524 c->ssl->no_wait_shutdown = 1;
525
526 c->read->handler = ngx_http_process_request_line;
527 /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
528
529 ngx_http_process_request_line(c->read);
530
531 return;
532 }
533
534 r = c->data;
535
536 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev9fa5a822005-09-30 14:41:25 +0000537
538 return;
539}
540
541
Igor Sysoevf38e0462004-07-16 17:11:43 +0000542#endif
543
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000544
Igor Sysoevc1571722005-03-19 12:38:37 +0000545static void
546ngx_http_process_request_line(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000547{
Igor Sysoevf7abd722004-09-23 06:32:00 +0000548 ssize_t n;
Igor Sysoevc3e47462004-09-24 16:12:19 +0000549 ngx_int_t rc, rv;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000550 ngx_connection_t *c;
551 ngx_http_request_t *r;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000552
Igor Sysoeva9830112003-05-19 16:39:14 +0000553 c = rev->data;
554 r = c->data;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000555
Igor Sysoev2b58fbf2003-12-09 15:08:11 +0000556 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
557 "http process request line");
Igor Sysoevdc479b42003-03-20 16:09:44 +0000558
559 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000560 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
561 c->timedout = 1;
562 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000563 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000564 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000565
Igor Sysoevf7abd722004-09-23 06:32:00 +0000566 rc = NGX_AGAIN;
Igor Sysoev016b8522002-08-29 16:59:54 +0000567
Igor Sysoevf7abd722004-09-23 06:32:00 +0000568 for ( ;; ) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000569
Igor Sysoevf7abd722004-09-23 06:32:00 +0000570 if (rc == NGX_AGAIN) {
571 n = ngx_http_read_request_header(r);
Igor Sysoevdc479b42003-03-20 16:09:44 +0000572
Igor Sysoevf7abd722004-09-23 06:32:00 +0000573 if (n == NGX_AGAIN || n == NGX_ERROR) {
Igor Sysoev865c1502003-11-30 20:03:18 +0000574 return;
575 }
Igor Sysoeva9830112003-05-19 16:39:14 +0000576 }
577
Igor Sysoevf7abd722004-09-23 06:32:00 +0000578 rc = ngx_http_parse_request_line(r, r->header_in);
Igor Sysoeva9830112003-05-19 16:39:14 +0000579
Igor Sysoevf7abd722004-09-23 06:32:00 +0000580 if (rc == NGX_OK) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000581
Igor Sysoevf7abd722004-09-23 06:32:00 +0000582 /* the request line has been parsed successfully */
Igor Sysoev6b863e32003-05-12 15:52:24 +0000583
Igor Sysoev1b735832004-11-11 14:07:14 +0000584 r->request_line.len = r->request_end - r->request_start;
585 r->request_line.data = r->request_start;
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000586
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000587
Igor Sysoevdc479b42003-03-20 16:09:44 +0000588 if (r->args_start) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000589 r->uri.len = r->args_start - 1 - r->uri_start;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000590 } else {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000591 r->uri.len = r->uri_end - r->uri_start;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000592 }
593
Igor Sysoevf6906042004-11-25 16:17:31 +0000594
Igor Sysoev924bd792004-10-11 15:07:03 +0000595 if (r->complex_uri || r->quoted_uri) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000596
Igor Sysoevc1571722005-03-19 12:38:37 +0000597 r->uri.data = ngx_palloc(r->pool, r->uri.len + 1);
598 if (r->uri.data == NULL) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000599 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev1b735832004-11-11 14:07:14 +0000600 return;
601 }
602
Igor Sysoevf7abd722004-09-23 06:32:00 +0000603 rc = ngx_http_parse_complex_uri(r);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000604
Igor Sysoevc04deca2005-03-28 14:43:02 +0000605 if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) {
606 ngx_log_error(NGX_LOG_INFO, c->log, 0,
607 "client sent invalid request");
608 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000609 return;
610 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000611
Igor Sysoevf7abd722004-09-23 06:32:00 +0000612 } else {
Igor Sysoev1b735832004-11-11 14:07:14 +0000613 r->uri.data = r->uri_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000614 }
615
Igor Sysoevf6906042004-11-25 16:17:31 +0000616
Igor Sysoev1b735832004-11-11 14:07:14 +0000617 r->unparsed_uri.len = r->uri_end - r->uri_start;
618 r->unparsed_uri.data = r->uri_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000619
Igor Sysoevf7abd722004-09-23 06:32:00 +0000620
Igor Sysoev899b44e2005-05-12 14:58:06 +0000621 r->method_name.len = r->method_end - r->request_start + 1;
622 r->method_name.data = r->request_line.data;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000623
Igor Sysoev1b735832004-11-11 14:07:14 +0000624
Igor Sysoev02025fd2005-01-18 13:03:58 +0000625 if (r->http_protocol.data) {
626 r->http_protocol.len = r->request_end - r->http_protocol.data;
627 }
628
629
Igor Sysoevf7abd722004-09-23 06:32:00 +0000630 if (r->uri_ext) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000631 if (r->args_start) {
632 r->exten.len = r->args_start - 1 - r->uri_ext;
633 } else {
634 r->exten.len = r->uri_end - r->uri_ext;
635 }
636
Igor Sysoev1b735832004-11-11 14:07:14 +0000637 r->exten.data = r->uri_ext;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000638 }
639
Igor Sysoev1b735832004-11-11 14:07:14 +0000640
Igor Sysoevf7abd722004-09-23 06:32:00 +0000641 if (r->args_start && r->uri_end > r->args_start) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000642 r->args.len = r->uri_end - r->args_start;
Igor Sysoev1b735832004-11-11 14:07:14 +0000643 r->args.data = r->args_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000644 }
645
Igor Sysoevf7abd722004-09-23 06:32:00 +0000646
647 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000648 "http request line: \"%V\"", &r->request_line);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000649
650 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000651 "http uri: \"%V\"", &r->uri);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000652
653 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000654 "http args: \"%V\"", &r->args);
655
656 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
657 "http exten: \"%V\"", &r->exten);
658
Igor Sysoevf7abd722004-09-23 06:32:00 +0000659 if (r->http_version < NGX_HTTP_VERSION_10) {
Igor Sysoeve5035392005-08-30 10:55:07 +0000660
661 if (rev->timer_set) {
662 ngx_del_timer(rev);
663 }
664
665#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000666 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoeve5035392005-08-30 10:55:07 +0000667 r->stat_reading = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000668 ngx_atomic_fetch_add(ngx_stat_writing, 1);
Igor Sysoeve5035392005-08-30 10:55:07 +0000669 r->stat_writing = 1;
670#endif
671
672 rev->handler = ngx_http_request_handler;
673 c->write->handler = ngx_http_request_handler;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000674 r->read_event_handler = ngx_http_block_read;
Igor Sysoeve5035392005-08-30 10:55:07 +0000675
Igor Sysoevf7abd722004-09-23 06:32:00 +0000676 ngx_http_handler(r);
Igor Sysoeve5035392005-08-30 10:55:07 +0000677
Igor Sysoev6b863e32003-05-12 15:52:24 +0000678 return;
679 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000680
Igor Sysoevdc479b42003-03-20 16:09:44 +0000681
Igor Sysoevf7abd722004-09-23 06:32:00 +0000682 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000683 sizeof(ngx_table_elt_t))
684 == NGX_ERROR)
Igor Sysoevf7abd722004-09-23 06:32:00 +0000685 {
686 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000687 return;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000688 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000689
690
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000691 if (ngx_array_init(&r->headers_in.cookies, r->pool, 2,
Igor Sysoevc31a9bb2005-11-26 10:11:11 +0000692 sizeof(ngx_table_elt_t *))
693 == NGX_ERROR)
Igor Sysoevf7abd722004-09-23 06:32:00 +0000694 {
695 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000696 return;
697 }
698
Igor Sysoeve5a222c2005-01-25 12:27:35 +0000699 c->log->action = "reading client request headers";
Igor Sysoevf7abd722004-09-23 06:32:00 +0000700
Igor Sysoev899b44e2005-05-12 14:58:06 +0000701 rev->handler = ngx_http_process_request_headers;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000702 ngx_http_process_request_headers(rev);
703
704 return;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000705 }
Igor Sysoevf7abd722004-09-23 06:32:00 +0000706
Igor Sysoevc04deca2005-03-28 14:43:02 +0000707 if (rc != NGX_AGAIN) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000708
709 /* there was error while a request line parsing */
710
Igor Sysoevc04deca2005-03-28 14:43:02 +0000711 ngx_log_error(NGX_LOG_INFO, c->log, 0,
712 ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
713 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000714 return;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000715 }
716
Igor Sysoevf7abd722004-09-23 06:32:00 +0000717 /* NGX_AGAIN: a request line parsing is still incomplete */
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000718
Igor Sysoev236e0452004-09-23 16:39:34 +0000719 if (r->header_in->pos == r->header_in->end) {
Igor Sysoeva1c8a922004-01-19 18:09:14 +0000720
Igor Sysoevf7abd722004-09-23 06:32:00 +0000721 rv = ngx_http_alloc_large_header_buffer(r, 1);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000722
Igor Sysoevf7abd722004-09-23 06:32:00 +0000723 if (rv == NGX_ERROR) {
724 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000725 return;
726 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000727
Igor Sysoevf7abd722004-09-23 06:32:00 +0000728 if (rv == NGX_DECLINED) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000729 r->request_line.len = r->header_in->end - r->request_start;
730 r->request_line.data = r->request_start;
731
732 ngx_log_error(NGX_LOG_INFO, c->log, 0,
733 "client sent too long URI");
734 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000735 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000736 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000737 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000738 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000739}
740
Igor Sysoev1af7c822002-09-13 14:47:42 +0000741
Igor Sysoevc1571722005-03-19 12:38:37 +0000742static void
743ngx_http_process_request_headers(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000744{
Igor Sysoev02f742b2005-04-08 15:18:55 +0000745 ssize_t n;
746 ngx_int_t rc, rv;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000747 ngx_str_t header;
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000748 ngx_uint_t i;
Igor Sysoev899b44e2005-05-12 14:58:06 +0000749 ngx_table_elt_t *h;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000750 ngx_connection_t *c;
751 ngx_http_header_t *hh;
752 ngx_http_request_t *r;
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000753 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev02f742b2005-04-08 15:18:55 +0000754 ngx_http_core_main_conf_t *cmcf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000755
Igor Sysoeva9830112003-05-19 16:39:14 +0000756 c = rev->data;
757 r = c->data;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000758
Igor Sysoev865c1502003-11-30 20:03:18 +0000759 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
760 "http process request header line");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000761
Igor Sysoev6b863e32003-05-12 15:52:24 +0000762 if (rev->timedout) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000763 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
764 c->timedout = 1;
765 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000766 return;
767 }
768
Igor Sysoev02f742b2005-04-08 15:18:55 +0000769 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000770 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev02f742b2005-04-08 15:18:55 +0000771
Igor Sysoevd581fd52003-05-13 16:02:32 +0000772 rc = NGX_AGAIN;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000773
Igor Sysoev016b8522002-08-29 16:59:54 +0000774 for ( ;; ) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000775
Igor Sysoevd581fd52003-05-13 16:02:32 +0000776 if (rc == NGX_AGAIN) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000777
Igor Sysoev236e0452004-09-23 16:39:34 +0000778 if (r->header_in->pos == r->header_in->end) {
Igor Sysoevf7abd722004-09-23 06:32:00 +0000779
780 rv = ngx_http_alloc_large_header_buffer(r, 0);
781
782 if (rv == NGX_ERROR) {
783 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000784 return;
785 }
786
787 if (rv == NGX_DECLINED) {
Igor Sysoevc04deca2005-03-28 14:43:02 +0000788 header.len = r->header_in->end - r->header_name_start;
789 header.data = r->header_name_start;
Igor Sysoev90c08142005-07-25 09:41:38 +0000790
791 if (header.len > NGX_MAX_ERROR_STR - 300) {
792 header.len = NGX_MAX_ERROR_STR - 300;
793 header.data[header.len++] = '.';
794 header.data[header.len++] = '.';
795 header.data[header.len++] = '.';
796 }
797
Igor Sysoevc04deca2005-03-28 14:43:02 +0000798 ngx_log_error(NGX_LOG_INFO, c->log, 0,
799 "client sent too long header line: \"%V\"",
800 &header);
801 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevf7abd722004-09-23 06:32:00 +0000802 return;
803 }
804 }
805
Igor Sysoevd581fd52003-05-13 16:02:32 +0000806 n = ngx_http_read_request_header(r);
807
808 if (n == NGX_AGAIN || n == NGX_ERROR) {
809 return;
810 }
811 }
812
Igor Sysoeve6779222003-10-03 15:50:53 +0000813 rc = ngx_http_parse_header_line(r, r->header_in);
Igor Sysoev016b8522002-08-29 16:59:54 +0000814
Igor Sysoev0dad6292003-03-05 17:30:51 +0000815 if (rc == NGX_OK) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000816
Igor Sysoev3362b8d2005-05-14 18:42:03 +0000817 if (r->invalid_header && cscf->ignore_invalid_headers) {
Igor Sysoev4d656dc2005-03-22 16:02:46 +0000818
819 /* there was error while a header line parsing */
820
821 header.len = r->header_end - r->header_name_start;
822 header.data = r->header_name_start;
823
Igor Sysoevc04deca2005-03-28 14:43:02 +0000824 ngx_log_error(NGX_LOG_INFO, c->log, 0,
825 "client sent invalid header line: \"%V\"",
Igor Sysoev4d656dc2005-03-22 16:02:46 +0000826 &header);
827 continue;
828 }
829
Igor Sysoevd581fd52003-05-13 16:02:32 +0000830 /* a header line has been parsed successfully */
831
Igor Sysoevc1571722005-03-19 12:38:37 +0000832 h = ngx_list_push(&r->headers_in.headers);
833 if (h == NULL) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000834 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000835 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000836 }
837
Igor Sysoev02f742b2005-04-08 15:18:55 +0000838 h->hash = r->header_hash;
839
Igor Sysoevd581fd52003-05-13 16:02:32 +0000840 h->key.len = r->header_name_end - r->header_name_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000841 h->key.data = r->header_name_start;
842 h->key.data[h->key.len] = '\0';
843
Igor Sysoevd581fd52003-05-13 16:02:32 +0000844 h->value.len = r->header_end - r->header_start;
Igor Sysoevf7abd722004-09-23 06:32:00 +0000845 h->value.data = r->header_start;
846 h->value.data[h->value.len] = '\0';
Igor Sysoevd581fd52003-05-13 16:02:32 +0000847
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000848 h->lowcase_key = ngx_palloc(r->pool, h->key.len);
849 if (h->lowcase_key == NULL) {
850 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
851 return;
852 }
Igor Sysoev899b44e2005-05-12 14:58:06 +0000853
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000854 if (h->key.len == r->lowcase_index) {
855 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
856
857 } else {
858 for (i = 0; i < h->key.len; i++) {
Igor Sysoev8f125582006-07-28 15:16:17 +0000859 h->lowcase_key[i] = ngx_tolower(h->key.data[i]);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000860 }
Igor Sysoevd581fd52003-05-13 16:02:32 +0000861 }
862
Igor Sysoev3338cfd2006-05-11 14:43:47 +0000863 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
864 h->lowcase_key, h->key.len);
865
866 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
867 return;
868 }
869
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000870 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000871 "http header: \"%V: %V\"",
872 &h->key, &h->value);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000873
Igor Sysoev6253ca12003-05-27 12:18:54 +0000874 continue;
Igor Sysoevc04deca2005-03-28 14:43:02 +0000875 }
Igor Sysoev6253ca12003-05-27 12:18:54 +0000876
Igor Sysoevc04deca2005-03-28 14:43:02 +0000877 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000878
879 /* a whole header has been parsed successfully */
880
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000881 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
882 "http header done");
Igor Sysoev42feecb2002-12-15 06:25:09 +0000883
Igor Sysoev6a12fc92004-12-06 14:45:08 +0000884 r->request_length += r->header_in->pos - r->header_in->start;
885
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000886 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
887
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000888 rc = ngx_http_process_request_header(r);
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000889
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000890 if (rc != NGX_OK) {
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000891 return;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000892 }
893
Igor Sysoev425a42c2003-10-27 16:16:17 +0000894 if (rev->timer_set) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000895 ngx_del_timer(rev);
896 }
897
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000898#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +0000899 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000900 r->stat_reading = 0;
Igor Sysoev78452232005-10-12 13:50:36 +0000901 ngx_atomic_fetch_add(ngx_stat_writing, 1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +0000902 r->stat_writing = 1;
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000903#endif
904
Igor Sysoev899b44e2005-05-12 14:58:06 +0000905 rev->handler = ngx_http_request_handler;
906 c->write->handler = ngx_http_request_handler;
907 r->read_event_handler = ngx_http_block_read;
908
Igor Sysoevd581fd52003-05-13 16:02:32 +0000909 ngx_http_handler(r);
Igor Sysoeve5035392005-08-30 10:55:07 +0000910
Igor Sysoevd581fd52003-05-13 16:02:32 +0000911 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000912 }
913
Igor Sysoevc04deca2005-03-28 14:43:02 +0000914 if (rc == NGX_AGAIN) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000915
Igor Sysoevc04deca2005-03-28 14:43:02 +0000916 /* a header line parsing is still not complete */
917
918 continue;
919 }
920
921 /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
922
923 header.len = r->header_end - r->header_name_start;
924 header.data = r->header_name_start;
925 ngx_log_error(NGX_LOG_INFO, c->log, 0,
926 "client sent invalid header line: \"%V\\r...\"",
927 &header);
928 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevc04deca2005-03-28 14:43:02 +0000929 return;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000930 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000931}
932
Igor Sysoevb0869052002-12-10 18:05:12 +0000933
Igor Sysoevc1571722005-03-19 12:38:37 +0000934static ssize_t
935ngx_http_read_request_header(ngx_http_request_t *r)
Igor Sysoev6b863e32003-05-12 15:52:24 +0000936{
Igor Sysoev187fcd82003-05-23 11:53:01 +0000937 ssize_t n;
938 ngx_event_t *rev;
Igor Sysoevda173ab2006-08-30 10:39:17 +0000939 ngx_connection_t *c;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000940 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000941
Igor Sysoevda173ab2006-08-30 10:39:17 +0000942 c = r->connection;
943 rev = c->read;
Igor Sysoev239baac2003-06-11 15:28:34 +0000944
Igor Sysoev6b863e32003-05-12 15:52:24 +0000945 n = r->header_in->last - r->header_in->pos;
946
947 if (n > 0) {
948 return n;
949 }
950
Igor Sysoevb145b062005-06-15 18:33:41 +0000951 if (rev->ready) {
Igor Sysoevda173ab2006-08-30 10:39:17 +0000952 n = c->recv(c, r->header_in->last,
953 r->header_in->end - r->header_in->last);
Igor Sysoevb145b062005-06-15 18:33:41 +0000954 } else {
955 n = NGX_AGAIN;
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000956 }
957
Igor Sysoev6b863e32003-05-12 15:52:24 +0000958 if (n == NGX_AGAIN) {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000959 if (!r->header_timeout_set) {
Igor Sysoevf38e0462004-07-16 17:11:43 +0000960 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev187fcd82003-05-23 11:53:01 +0000961 ngx_add_timer(rev, cscf->client_header_timeout);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000962 r->header_timeout_set = 1;
963 }
964
Igor Sysoevb5faed22003-10-29 08:30:44 +0000965 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000966 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000967 return NGX_ERROR;
968 }
969
Igor Sysoev6b863e32003-05-12 15:52:24 +0000970 return NGX_AGAIN;
971 }
972
973 if (n == 0) {
Igor Sysoevda173ab2006-08-30 10:39:17 +0000974 ngx_log_error(NGX_LOG_INFO, c->log, 0,
Igor Sysoev6b863e32003-05-12 15:52:24 +0000975 "client closed prematurely connection");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000976 }
Igor Sysoev6b863e32003-05-12 15:52:24 +0000977
978 if (n == 0 || n == NGX_ERROR) {
Igor Sysoevda173ab2006-08-30 10:39:17 +0000979 c->error = rev->error;
980 c->log->action = "sending response to client";
981
Igor Sysoev8a3cdc02006-09-25 17:49:49 +0000982 ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000983 return NGX_ERROR;
984 }
985
986 r->header_in->last += n;
987
988 return n;
989}
990
991
Igor Sysoevc1571722005-03-19 12:38:37 +0000992static ngx_int_t
993ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
994 ngx_uint_t request_line)
Igor Sysoev85080d02004-09-22 16:18:21 +0000995{
996 u_char *old, *new;
Igor Sysoev85080d02004-09-22 16:18:21 +0000997 ngx_buf_t *b;
998 ngx_http_connection_t *hc;
999 ngx_http_core_srv_conf_t *cscf;
1000
1001 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1002 "http alloc large header buffer");
1003
Igor Sysoevf7abd722004-09-23 06:32:00 +00001004 if (request_line && r->state == 0) {
1005
1006 /* the client fills up the buffer with "\r\n" */
1007
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001008 r->request_length += r->header_in->end - r->header_in->start;
1009
Igor Sysoevf7abd722004-09-23 06:32:00 +00001010 r->header_in->pos = r->header_in->start;
1011 r->header_in->last = r->header_in->start;
1012
1013 return NGX_OK;
1014 }
1015
Igor Sysoev85080d02004-09-22 16:18:21 +00001016 old = request_line ? r->request_start : r->header_name_start;
1017
1018 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1019
Igor Sysoevf7abd722004-09-23 06:32:00 +00001020 if (r->state != 0
1021 && (size_t) (r->header_in->pos - old)
1022 >= cscf->large_client_header_buffers.size)
1023 {
Igor Sysoev85080d02004-09-22 16:18:21 +00001024 return NGX_DECLINED;
1025 }
1026
1027 hc = r->http_connection;
1028
1029 if (hc->nfree) {
1030 b = hc->free[--hc->nfree];
1031
Igor Sysoev236e0452004-09-23 16:39:34 +00001032 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +00001033 "http large header free: %p %uz",
Igor Sysoev236e0452004-09-23 16:39:34 +00001034 b->pos, b->end - b->last);
1035
Igor Sysoevf7abd722004-09-23 06:32:00 +00001036 } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
Igor Sysoev85080d02004-09-22 16:18:21 +00001037
1038 if (hc->busy == NULL) {
1039 hc->busy = ngx_palloc(r->connection->pool,
Igor Sysoevf7abd722004-09-23 06:32:00 +00001040 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev85080d02004-09-22 16:18:21 +00001041 if (hc->busy == NULL) {
1042 return NGX_ERROR;
1043 }
1044 }
1045
1046 b = ngx_create_temp_buf(r->connection->pool,
Igor Sysoevf7abd722004-09-23 06:32:00 +00001047 cscf->large_client_header_buffers.size);
Igor Sysoev85080d02004-09-22 16:18:21 +00001048 if (b == NULL) {
1049 return NGX_ERROR;
1050 }
1051
Igor Sysoev236e0452004-09-23 16:39:34 +00001052 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +00001053 "http large header alloc: %p %uz",
Igor Sysoev236e0452004-09-23 16:39:34 +00001054 b->pos, b->end - b->last);
1055
Igor Sysoev85080d02004-09-22 16:18:21 +00001056 } else {
1057 return NGX_DECLINED;
1058 }
1059
1060 hc->busy[hc->nbusy++] = b;
1061
Igor Sysoevf7abd722004-09-23 06:32:00 +00001062 if (r->state == 0) {
1063 /*
1064 * r->state == 0 means that a header line was parsed successfully
1065 * and we do not need to copy incomplete header line and
1066 * to relocate the parser header pointers
1067 */
1068
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001069 r->request_length += r->header_in->end - r->header_in->start;
1070
Igor Sysoevf7abd722004-09-23 06:32:00 +00001071 r->header_in = b;
1072
1073 return NGX_OK;
1074 }
1075
Igor Sysoev236e0452004-09-23 16:39:34 +00001076 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1077 "http large header copy: %d", r->header_in->pos - old);
1078
Igor Sysoev6a12fc92004-12-06 14:45:08 +00001079 r->request_length += old - r->header_in->start;
1080
Igor Sysoev85080d02004-09-22 16:18:21 +00001081 new = b->start;
1082
Igor Sysoev236e0452004-09-23 16:39:34 +00001083 ngx_memcpy(new, old, r->header_in->pos - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001084
1085 b->pos = new + (r->header_in->pos - old);
Igor Sysoev236e0452004-09-23 16:39:34 +00001086 b->last = new + (r->header_in->pos - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001087
1088 if (request_line) {
1089 r->request_start = new;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001090
1091 if (r->request_end) {
1092 r->request_end = new + (r->request_end - old);
1093 }
1094
1095 r->method_end = new + (r->method_end - old);
Igor Sysoev85080d02004-09-22 16:18:21 +00001096
1097 r->uri_start = new + (r->uri_start - old);
1098 r->uri_end = new + (r->uri_end - old);
1099
Igor Sysoevf7abd722004-09-23 06:32:00 +00001100 if (r->schema_start) {
1101 r->schema_start = new + (r->schema_start - old);
1102 r->schema_end = new + (r->schema_end - old);
1103 }
1104
1105 if (r->host_start) {
1106 r->host_start = new + (r->host_start - old);
Igor Sysoev03011fa2006-12-15 10:24:57 +00001107 if (r->host_end) {
1108 r->host_end = new + (r->host_end - old);
1109 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00001110 }
1111
1112 if (r->port_start) {
1113 r->port_start = new + (r->port_start - old);
1114 r->port_end = new + (r->port_end - old);
1115 }
1116
Igor Sysoev85080d02004-09-22 16:18:21 +00001117 if (r->uri_ext) {
1118 r->uri_ext = new + (r->uri_ext - old);
1119 }
1120
1121 if (r->args_start) {
1122 r->args_start = new + (r->args_start - old);
1123 }
1124
1125 } else {
1126 r->header_name_start = new;
1127 r->header_name_end = new + (r->header_name_end - old);
1128 r->header_start = new + (r->header_start - old);
1129 r->header_end = new + (r->header_end - old);
1130 }
1131
1132 r->header_in = b;
1133
1134 return NGX_OK;
1135}
1136
Igor Sysoev85080d02004-09-22 16:18:21 +00001137
Igor Sysoevc1571722005-03-19 12:38:37 +00001138static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001139ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1140 ngx_uint_t offset)
1141{
1142 ngx_table_elt_t **ph;
1143
1144 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1145
1146 if (*ph == NULL) {
1147 *ph = h;
1148 }
1149
1150 return NGX_OK;
1151}
1152
1153
1154static ngx_int_t
Igor Sysoevb145b062005-06-15 18:33:41 +00001155ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1156 ngx_uint_t offset)
1157{
1158 ngx_table_elt_t **ph;
1159
1160 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1161
1162 if (*ph == NULL) {
1163 *ph = h;
1164 return NGX_OK;
1165 }
1166
1167 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
Igor Sysoevda173ab2006-08-30 10:39:17 +00001168 "client sent duplicate header line: \"%V: %V\", "
1169 "previous value: \"%V: %V\"",
1170 &h->key, &h->value, &(*ph)->key, &(*ph)->value);
Igor Sysoevb145b062005-06-15 18:33:41 +00001171
1172 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1173
1174 return NGX_ERROR;
1175}
1176
1177
1178static ngx_int_t
Igor Sysoev899b44e2005-05-12 14:58:06 +00001179ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
1180 ngx_uint_t offset)
1181{
1182 ngx_table_elt_t **cookie;
1183
1184 cookie = ngx_array_push(&r->headers_in.cookies);
Igor Sysoevb145b062005-06-15 18:33:41 +00001185 if (cookie) {
1186 *cookie = h;
1187 return NGX_OK;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001188 }
1189
Igor Sysoevb145b062005-06-15 18:33:41 +00001190 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001191
Igor Sysoevb145b062005-06-15 18:33:41 +00001192 return NGX_ERROR;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001193}
1194
1195
1196static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001197ngx_http_process_request_header(ngx_http_request_t *r)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001198{
Igor Sysoev44d87222006-05-06 16:28:56 +00001199 size_t len;
1200 u_char *ua, *user_agent, ch;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001201 ngx_uint_t hash;
Igor Sysoev44d87222006-05-06 16:28:56 +00001202#if (NGX_HTTP_SSL)
1203 long rc;
1204 ngx_http_ssl_srv_conf_t *sscf;
1205#endif
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001206
1207 if (r->headers_in.host) {
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001208
1209 hash = 0;
1210
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001211 for (len = 0; len < r->headers_in.host->value.len; len++) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001212 ch = r->headers_in.host->value.data[len];
1213
1214 if (ch == ':') {
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001215 break;
1216 }
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001217
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001218 ch = ngx_tolower(ch);
1219 r->headers_in.host->value.data[len] = ch;
1220 hash = ngx_hash(hash, ch);
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001221 }
Igor Sysoevc04deca2005-03-28 14:43:02 +00001222
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001223 if (len && r->headers_in.host->value.data[len - 1] == '.') {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001224 len--;
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001225 hash = ngx_hash_key(r->headers_in.host->value.data, len);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001226 }
1227
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001228 r->headers_in.host_name_len = len;
1229
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001230 if (r->virtual_names) {
1231 ngx_http_find_virtual_server(r, r->virtual_names, hash);
1232 }
Igor Sysoev3043bfc2004-05-14 16:51:47 +00001233
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001234 } else {
1235 if (r->http_version > NGX_HTTP_VERSION_10) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001236 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1237 "client sent HTTP/1.1 request without \"Host\" header");
1238 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1239 return NGX_ERROR;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001240 }
Igor Sysoevc04deca2005-03-28 14:43:02 +00001241
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001242 r->headers_in.host_name_len = 0;
1243 }
1244
1245 if (r->headers_in.content_length) {
1246 r->headers_in.content_length_n =
Igor Sysoev1765f472006-07-07 16:33:19 +00001247 ngx_atoof(r->headers_in.content_length->value.data,
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001248 r->headers_in.content_length->value.len);
1249
1250 if (r->headers_in.content_length_n == NGX_ERROR) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001251 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1252 "client sent invalid \"Content-Length\" header");
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001253 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
Igor Sysoevc04deca2005-03-28 14:43:02 +00001254 return NGX_ERROR;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001255 }
1256 }
1257
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00001258 if (r->method & (NGX_HTTP_POST|NGX_HTTP_PUT)
1259 && r->headers_in.content_length_n == -1)
1260 {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001261 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1262 "client sent POST method without \"Content-Length\" header");
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00001263 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
1264 return NGX_ERROR;
1265 }
1266
1267 if (r->headers_in.transfer_encoding
1268 && ngx_strstr(r->headers_in.transfer_encoding->value.data, "chunked"))
1269 {
1270 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1271 "client sent \"Transfer-Encoding: chunked\" header");
1272 ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED);
Igor Sysoevc04deca2005-03-28 14:43:02 +00001273 return NGX_ERROR;
Igor Sysoev6881bfb2004-03-30 06:27:36 +00001274 }
1275
Igor Sysoevf38e0462004-07-16 17:11:43 +00001276 if (r->plain_http) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001277 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1278 "client sent plain HTTP request to HTTPS port");
1279 ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1280 return NGX_ERROR;
Igor Sysoevf38e0462004-07-16 17:11:43 +00001281 }
1282
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001283 if (r->headers_in.connection) {
1284 if (r->headers_in.connection->value.len == 5
1285 && ngx_strcasecmp(r->headers_in.connection->value.data, "close")
Igor Sysoev899b44e2005-05-12 14:58:06 +00001286 == 0)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001287 {
1288 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1289
1290 } else if (r->headers_in.connection->value.len == 10
1291 && ngx_strcasecmp(r->headers_in.connection->value.data,
Igor Sysoev899b44e2005-05-12 14:58:06 +00001292 "keep-alive") == 0)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001293 {
1294 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1295
1296 if (r->headers_in.keep_alive) {
1297 r->headers_in.keep_alive_n =
Igor Sysoevc1571722005-03-19 12:38:37 +00001298 ngx_atotm(r->headers_in.keep_alive->value.data,
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001299 r->headers_in.keep_alive->value.len);
1300 }
1301 }
1302 }
1303
Igor Sysoev2f657222004-06-16 15:32:11 +00001304 if (r->headers_in.user_agent) {
1305
1306 /*
1307 * check some widespread browsers while the headers are still
1308 * in CPU cache
1309 */
1310
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001311 user_agent = r->headers_in.user_agent->value.data;
1312
1313 ua = (u_char *) ngx_strstr(user_agent, "MSIE");
1314
1315 if (ua && ua + 8 < user_agent + r->headers_in.user_agent->value.len) {
1316
Igor Sysoev2f657222004-06-16 15:32:11 +00001317 r->headers_in.msie = 1;
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001318
Igor Sysoev2f657222004-06-16 15:32:11 +00001319 if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') {
1320 r->headers_in.msie4 = 1;
1321 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001322
1323#if 0
1324 /* MSIE ignores the SSL "close notify" alert */
Igor Sysoev42b12b32004-12-02 18:40:46 +00001325 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00001326 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00001327 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001328#endif
Igor Sysoev2f657222004-06-16 15:32:11 +00001329 }
Igor Sysoev85cccfb2004-09-15 16:00:43 +00001330
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001331 if (ngx_strstr(user_agent, "Opera")) {
Igor Sysoev85cccfb2004-09-15 16:00:43 +00001332 r->headers_in.opera = 1;
1333 r->headers_in.msie = 0;
1334 r->headers_in.msie4 = 0;
1335 }
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001336
1337 if (!r->headers_in.msie && !r->headers_in.opera) {
1338
Igor Sysoeva2c81192004-09-19 18:27:00 +00001339 if (ngx_strstr(user_agent, "Gecko/")) {
Igor Sysoev307c3ad2004-09-17 16:07:35 +00001340 r->headers_in.gecko = 1;
1341
1342 } else if (ngx_strstr(user_agent, "Konqueror")) {
1343 r->headers_in.konqueror = 1;
1344 }
1345 }
Igor Sysoev2f657222004-06-16 15:32:11 +00001346 }
1347
Igor Sysoevb71c6902006-08-04 16:04:04 +00001348#if (NGX_HTTP_SSL)
1349
1350 if (r->connection->ssl) {
1351 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
1352
1353 if (sscf->verify) {
1354 rc = SSL_get_verify_result(r->connection->ssl->connection);
1355
1356 if (rc != X509_V_OK) {
1357 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
Igor Sysoevc55a1042006-08-09 19:59:45 +00001358 "client SSL certificate verify error: (%l:%s)",
Igor Sysoevb71c6902006-08-04 16:04:04 +00001359 rc, X509_verify_cert_error_string(rc));
1360 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
1361 return NGX_ERROR;
1362 }
1363
1364 if (SSL_get_peer_certificate(r->connection->ssl->connection)
1365 == NULL)
1366 {
1367 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1368 "client sent no required SSL certificate");
1369 ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
1370 return NGX_ERROR;
1371 }
1372 }
1373 }
1374
1375#endif
1376
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001377 return NGX_OK;
1378}
1379
1380
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001381static void
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001382ngx_http_find_virtual_server(ngx_http_request_t *r,
1383 ngx_http_virtual_names_t *vn, ngx_uint_t hash)
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001384{
Igor Sysoev305a9d82005-12-26 17:07:48 +00001385 size_t len;
1386 u_char *host;
Igor Sysoev305a9d82005-12-26 17:07:48 +00001387 ngx_http_core_loc_conf_t *clcf;
1388 ngx_http_core_srv_conf_t *cscf;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001389
Igor Sysoev95ead462006-11-23 20:20:23 +00001390 host = r->host_start;
1391
1392 if (host == NULL) {
1393 host = r->headers_in.host->value.data;
1394 len = r->headers_in.host_name_len;
1395
1396 } else {
1397 len = r->host_end - host;
1398 }
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001399
Igor Sysoev305a9d82005-12-26 17:07:48 +00001400 if (vn->hash.buckets) {
Igor Sysoev3338cfd2006-05-11 14:43:47 +00001401 cscf = ngx_hash_find(&vn->hash, hash, host, len);
Igor Sysoev305a9d82005-12-26 17:07:48 +00001402 if (cscf) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001403 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001404 }
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001405 }
1406
Igor Sysoev305a9d82005-12-26 17:07:48 +00001407 if (vn->dns_wildcards && vn->dns_wildcards->hash.buckets) {
1408 cscf = ngx_hash_find_wildcard(vn->dns_wildcards, host, len);
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001409
Igor Sysoev305a9d82005-12-26 17:07:48 +00001410 if (cscf) {
1411 goto found;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001412 }
1413 }
1414
Igor Sysoev1765f472006-07-07 16:33:19 +00001415 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1416
1417 if (cscf->wildcard) {
1418 r->server_name.len = len;
1419 r->server_name.data = host;
1420 }
1421
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001422 return;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001423
Igor Sysoev899b44e2005-05-12 14:58:06 +00001424found:
1425
Igor Sysoev305a9d82005-12-26 17:07:48 +00001426 r->server_name.len = len;
1427 r->server_name.data = host;
1428
1429 r->srv_conf = cscf->ctx->srv_conf;
1430 r->loc_conf = cscf->ctx->loc_conf;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001431
1432 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1433 r->connection->log->file = clcf->err_log->file;
1434
1435 if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1436 r->connection->log->log_level = clcf->err_log->log_level;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001437 }
1438
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001439 return;
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001440}
1441
1442
Igor Sysoev899b44e2005-05-12 14:58:06 +00001443static void
1444ngx_http_request_handler(ngx_event_t *ev)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001445{
Igor Sysoev899b44e2005-05-12 14:58:06 +00001446 ngx_connection_t *c;
1447 ngx_http_request_t *r;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001448 ngx_http_log_ctx_t *ctx;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001449
1450 c = ev->data;
1451 r = c->data;
1452
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001453 ctx = c->log->data;
1454 ctx->current_request = r;
1455
Igor Sysoev899b44e2005-05-12 14:58:06 +00001456 if (ev->write) {
1457 r->write_event_handler(r);
1458
1459 } else {
1460 r->read_event_handler(r);
1461 }
1462}
1463
1464
1465void
1466ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1467{
1468 ngx_http_request_t *pr;
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001469 ngx_http_log_ctx_t *ctx;
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001470 ngx_http_core_loc_conf_t *clcf;
1471
Igor Sysoev899b44e2005-05-12 14:58:06 +00001472 if (rc == NGX_DONE) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001473 /* the request pool may be already destroyed */
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001474 return;
1475 }
1476
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001477 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1478 "http finalize request: %d, \"%V?%V\"",
1479 rc, &r->uri, &r->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001480
Igor Sysoevda173ab2006-08-30 10:39:17 +00001481 if (rc == NGX_DECLINED) {
1482 r->content_handler = NULL;
1483 r->write_event_handler = ngx_http_core_run_phases;
1484 ngx_http_core_run_phases(r);
1485 return;
1486 }
1487
Igor Sysoev960100e2006-10-13 15:20:10 +00001488 if (r != r->main && r->post_subrequest) {
1489 rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
Igor Sysoev8f125582006-07-28 15:16:17 +00001490 }
1491
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001492 if (rc == NGX_ERROR
1493 || rc == NGX_HTTP_REQUEST_TIME_OUT
1494 || r->connection->error)
1495 {
Igor Sysoev7f7846d2006-04-26 09:52:47 +00001496 if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
1497 && r->headers_out.status == 0)
1498 {
1499 r->headers_out.status = NGX_HTTP_CLIENT_CLOSED_REQUEST;
1500 }
1501
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001502 if (ngx_http_post_action(r) == NGX_OK) {
1503 return;
1504 }
1505
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001506 ngx_http_close_request(r, 0);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001507 return;
1508 }
1509
Igor Sysoev7bdb7202006-04-19 15:30:56 +00001510 if (rc >= NGX_HTTP_SPECIAL_RESPONSE
1511 || rc == NGX_HTTP_CREATED
1512 || rc == NGX_HTTP_NO_CONTENT)
1513 {
Igor Sysoevcdc46302005-12-07 14:51:31 +00001514 if (rc == NGX_HTTP_CLOSE) {
1515 ngx_http_close_request(r, rc);
1516 return;
1517 }
1518
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001519 if (r == r->main) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001520 if (r->connection->read->timer_set) {
1521 ngx_del_timer(r->connection->read);
1522 }
1523
1524 if (r->connection->write->timer_set) {
1525 ngx_del_timer(r->connection->write);
1526 }
1527 }
1528
1529 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001530 return;
1531 }
1532
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001533 if (r != r->main || rc == NGX_AGAIN) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001534 if (ngx_http_set_write_handler(r) != NGX_OK) {
1535 return;
1536 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001537 }
1538
1539 r->done = 1;
1540
1541 if (r != r->connection->data) {
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001542 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1543 "http finalize non-active request: \"%V?%V\"",
1544 &r->uri, &r->args);
Igor Sysoev899b44e2005-05-12 14:58:06 +00001545 return;
1546 }
1547
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001548 if (r != r->main) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00001549
1550 pr = r->parent;
1551
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001552 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1553 "http parent request: \"%V?%V\"", &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001554
Igor Sysoev899b44e2005-05-12 14:58:06 +00001555 if (rc != NGX_AGAIN) {
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001556 r->connection->data = pr;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001557 }
1558
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00001559 ctx = r->connection->log->data;
1560 ctx->current_request = pr;
1561
Igor Sysoev899b44e2005-05-12 14:58:06 +00001562 if (pr->postponed) {
1563
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001564 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1565 "http request: \"%V?%V\" has postponed",
1566 &pr->uri, &pr->args);
Igor Sysoev5192b362005-07-08 14:34:20 +00001567
Igor Sysoev899b44e2005-05-12 14:58:06 +00001568 if (rc != NGX_AGAIN && pr->postponed->request == r) {
1569 pr->postponed = pr->postponed->next;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001570 }
1571
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001572 if (r->fast_subrequest) {
Igor Sysoevac72bd12006-05-04 15:32:46 +00001573
1574 if (rc == NGX_AGAIN) {
1575 r->fast_subrequest = 0;
1576 }
1577
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001578 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1579 "http fast subrequest: \"%V?%V\" done",
1580 &r->uri, &r->args);
1581 return;
1582 }
1583
Igor Sysoevac72bd12006-05-04 15:32:46 +00001584 if (rc != NGX_AGAIN) {
1585 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1586 "http wake parent request: \"%V?%V\"",
1587 &pr->uri, &pr->args);
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001588
Igor Sysoevac72bd12006-05-04 15:32:46 +00001589 pr->write_event_handler(pr);
1590 }
Igor Sysoev899b44e2005-05-12 14:58:06 +00001591 }
1592
1593 return;
1594 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001595
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001596 if (rc == NGX_AGAIN) {
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001597 return;
Igor Sysoev5192b362005-07-08 14:34:20 +00001598 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001599
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001600 if (r->connection->buffered) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001601 (void) ngx_http_set_write_handler(r);
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001602 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001603 }
1604
Igor Sysoev6d16e1e2006-04-05 13:40:54 +00001605 if (!r->post_action) {
1606 r->request_complete = 1;
1607 }
1608
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001609 if (ngx_http_post_action(r) == NGX_OK) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001610 return;
1611 }
1612
Igor Sysoev0a280a32003-10-12 16:49:16 +00001613 if (r->connection->read->timer_set) {
1614 ngx_del_timer(r->connection->read);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001615 }
1616
Igor Sysoev0a280a32003-10-12 16:49:16 +00001617 if (r->connection->write->timer_set) {
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001618 r->connection->write->delayed = 0;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001619 ngx_del_timer(r->connection->write);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001620 }
1621
Igor Sysoev24025022005-12-16 15:07:08 +00001622 if (r->connection->destroyed) {
1623 return;
1624 }
1625
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001626 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001627
Igor Sysoevc5991982004-01-16 06:15:48 +00001628 if (!ngx_terminate
Igor Sysoev3f4685f2004-04-25 20:13:21 +00001629 && !ngx_exiting
Igor Sysoevc5991982004-01-16 06:15:48 +00001630 && r->keepalive != 0
1631 && clcf->keepalive_timeout > 0)
1632 {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001633 ngx_http_set_keepalive(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001634 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001635
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001636 } else if (r->lingering_close && clcf->lingering_timeout > 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001637 ngx_http_set_lingering_close(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001638 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001639 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001640
Igor Sysoevc5991982004-01-16 06:15:48 +00001641 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001642}
1643
1644
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001645static ngx_int_t
Igor Sysoevc1571722005-03-19 12:38:37 +00001646ngx_http_set_write_handler(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001647{
Igor Sysoevd581fd52003-05-13 16:02:32 +00001648 ngx_event_t *wev;
Igor Sysoeva9830112003-05-19 16:39:14 +00001649 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001650
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001651 r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
1652
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001653 r->write_event_handler = ngx_http_writer;
1654
Igor Sysoev899b44e2005-05-12 14:58:06 +00001655 wev = r->connection->write;
1656
Igor Sysoevef066482004-06-21 15:59:32 +00001657 if (wev->ready && wev->delayed) {
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001658 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001659 }
1660
Igor Sysoev899b44e2005-05-12 14:58:06 +00001661 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001662 if (!wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001663 ngx_add_timer(wev, clcf->send_timeout);
1664 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001665
Igor Sysoev924bd792004-10-11 15:07:03 +00001666 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001667 ngx_http_close_request(r, 0);
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001668 return NGX_ERROR;
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001669 }
Igor Sysoev85ef94b2005-06-23 13:41:06 +00001670
1671 return NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001672}
1673
1674
Igor Sysoev899b44e2005-05-12 14:58:06 +00001675static void
1676ngx_http_writer(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001677{
1678 int rc;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001679 ngx_event_t *wev;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001680 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001681 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001682
Igor Sysoev899b44e2005-05-12 14:58:06 +00001683 c = r->connection;
1684 wev = c->write;
Igor Sysoev160d7742003-11-19 16:26:41 +00001685
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001686 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1687 "http writer handler: \"%V?%V\"", &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001688
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001689 if (wev->timedout) {
Igor Sysoevef066482004-06-21 15:59:32 +00001690 if (!wev->delayed) {
Igor Sysoevc04deca2005-03-28 14:43:02 +00001691 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
1692 "client timed out");
1693 c->timedout = 1;
Igor Sysoev055951d2005-10-21 19:12:18 +00001694
Igor Sysoevc2807ec2006-02-16 15:26:46 +00001695 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001696 return;
1697 }
1698
1699 wev->timedout = 0;
Igor Sysoevef066482004-06-21 15:59:32 +00001700 wev->delayed = 0;
Igor Sysoev73a73b52004-06-20 19:54:15 +00001701
1702 if (!wev->ready) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001703 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001704 ngx_add_timer(wev, clcf->send_timeout);
1705
Igor Sysoev924bd792004-10-11 15:07:03 +00001706 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001707 ngx_http_close_request(r, 0);
Igor Sysoev73a73b52004-06-20 19:54:15 +00001708 }
1709
1710 return;
1711 }
1712
1713 } else {
Igor Sysoevef066482004-06-21 15:59:32 +00001714 if (wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001715 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1716 "http writer delayed");
Igor Sysoevef066482004-06-21 15:59:32 +00001717
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001718 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001719
Igor Sysoev924bd792004-10-11 15:07:03 +00001720 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001721 ngx_http_close_request(r, 0);
Igor Sysoevef066482004-06-21 15:59:32 +00001722 }
1723
Igor Sysoev73a73b52004-06-20 19:54:15 +00001724 return;
1725 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001726 }
1727
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001728 rc = ngx_http_output_filter(r, NULL);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001729
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001730 if (c->destroyed) {
1731 return;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001732 }
1733
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001734 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
1735 "http writer output filter: %d, \"%V?%V\"",
1736 rc, &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001737
1738 if (rc == NGX_AGAIN) {
Igor Sysoevf6e1fe32005-10-04 10:38:53 +00001739 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001740 if (!wev->ready && !wev->delayed) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001741 ngx_add_timer(wev, clcf->send_timeout);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001742 }
1743
Igor Sysoev924bd792004-10-11 15:07:03 +00001744 if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001745 ngx_http_close_request(r, 0);
Igor Sysoev0a280a32003-10-12 16:49:16 +00001746 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001747
Igor Sysoev020ffea2006-10-30 20:25:22 +00001748 if (r == r->main || r->buffered) {
Igor Sysoevdf3254a2006-01-11 15:26:57 +00001749 return;
1750 }
1751
1752 rc = NGX_OK;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001753 }
1754
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001755 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1756 "http writer done: \"%V?%V\"", &r->uri, &r->args);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001757
Igor Sysoev0a280a32003-10-12 16:49:16 +00001758 ngx_http_finalize_request(r, rc);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001759}
1760
1761
Igor Sysoev899b44e2005-05-12 14:58:06 +00001762static void
1763ngx_http_block_read(ngx_http_request_t *r)
1764{
1765 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1766 "http read blocked");
Igor Sysoev42feecb2002-12-15 06:25:09 +00001767
Igor Sysoev73009772003-02-06 17:21:13 +00001768 /* aio does not call this handler */
1769
Igor Sysoev899b44e2005-05-12 14:58:06 +00001770 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
1771 && r->connection->read->active)
1772 {
1773 if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0)
1774 == NGX_ERROR)
1775 {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001776 ngx_http_close_request(r, 0);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001777 }
Igor Sysoev73009772003-02-06 17:21:13 +00001778 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001779}
1780
1781
Igor Sysoevc1571722005-03-19 12:38:37 +00001782static void
1783ngx_http_set_keepalive(ngx_http_request_t *r)
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001784{
Igor Sysoev924bd792004-10-11 15:07:03 +00001785 int tcp_nodelay;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001786 ngx_int_t i;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001787 ngx_buf_t *b, *f;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001788 ngx_event_t *rev, *wev;
1789 ngx_connection_t *c;
Igor Sysoevdd888c42004-09-21 05:38:28 +00001790 ngx_http_connection_t *hc;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001791 ngx_http_core_srv_conf_t *cscf;
1792 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001793
Igor Sysoev6253ca12003-05-27 12:18:54 +00001794 c = r->connection;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001795 rev = c->read;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001796
Igor Sysoeve04084c2004-01-26 08:52:49 +00001797 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001798
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001799 c->log->action = "closing request";
Igor Sysoevdd888c42004-09-21 05:38:28 +00001800
1801 hc = r->http_connection;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001802 b = r->header_in;
1803
Igor Sysoev236e0452004-09-23 16:39:34 +00001804 if (b->pos < b->last) {
Igor Sysoevf7abd722004-09-23 06:32:00 +00001805
Igor Sysoev236e0452004-09-23 16:39:34 +00001806 /* the pipelined request */
Igor Sysoevf7abd722004-09-23 06:32:00 +00001807
1808 if (b != c->buffer) {
1809
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001810 /*
1811 * If the large header buffers were allocated while the previous
1812 * request processing then we do not use c->buffer for
1813 * the pipelined request (see ngx_http_init_request()).
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00001814 *
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001815 * Now we would move the large header buffers to the free list.
1816 */
Igor Sysoevf7abd722004-09-23 06:32:00 +00001817
1818 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1819
1820 if (hc->free == NULL) {
1821 hc->free = ngx_palloc(c->pool,
1822 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
Igor Sysoev236e0452004-09-23 16:39:34 +00001823
Igor Sysoevf7abd722004-09-23 06:32:00 +00001824 if (hc->free == NULL) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001825 ngx_http_close_request(r, 0);
Igor Sysoevf7abd722004-09-23 06:32:00 +00001826 return;
1827 }
1828 }
1829
1830 for (i = 0; i < hc->nbusy - 1; i++) {
1831 f = hc->busy[i];
1832 hc->free[hc->nfree++] = f;
1833 f->pos = f->start;
1834 f->last = f->start;
1835 }
1836
1837 hc->busy[0] = b;
1838 hc->nbusy = 1;
1839 }
1840 }
1841
Igor Sysoevb1dfe472004-12-21 12:30:30 +00001842 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1843
Igor Sysoev9ac946b2005-10-24 15:09:41 +00001844 ngx_http_request_done(r, 0);
1845
Igor Sysoevdd888c42004-09-21 05:38:28 +00001846 c->data = hc;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001847
Igor Sysoevfa73aac2003-05-21 13:28:21 +00001848 ngx_add_timer(rev, clcf->keepalive_timeout);
1849
Igor Sysoev899b44e2005-05-12 14:58:06 +00001850 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001851 ngx_http_close_connection(c);
1852 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00001853 }
1854
Igor Sysoev7b6062a2004-02-12 20:57:10 +00001855 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00001856 wev->handler = ngx_http_empty_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001857
Igor Sysoev369145c2004-05-28 15:49:23 +00001858 if (b->pos < b->last) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001859
Igor Sysoeve04084c2004-01-26 08:52:49 +00001860 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
Igor Sysoev6253ca12003-05-27 12:18:54 +00001861
Igor Sysoev055951d2005-10-21 19:12:18 +00001862#if (NGX_STAT_STUB)
1863 ngx_atomic_fetch_add(ngx_stat_reading, 1);
1864#endif
1865
Igor Sysoevdd888c42004-09-21 05:38:28 +00001866 hc->pipeline = 1;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001867 c->log->action = "reading client pipelined request line";
Igor Sysoev055951d2005-10-21 19:12:18 +00001868
Igor Sysoevd581fd52003-05-13 16:02:32 +00001869 ngx_http_init_request(rev);
1870 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001871 }
1872
Igor Sysoevdd888c42004-09-21 05:38:28 +00001873 hc->pipeline = 0;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001874
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001875 /*
1876 * To keep a memory footprint as small as possible for an idle
1877 * keepalive connection we try to free the ngx_http_request_t and
1878 * c->buffer's memory if they were allocated outside the c->pool.
1879 * The large header buffers are always allocated outside the c->pool and
1880 * are freed too.
1881 */
1882
Igor Sysoev236e0452004-09-23 16:39:34 +00001883 if (ngx_pfree(c->pool, r) == NGX_OK) {
1884 hc->request = NULL;
1885 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00001886
Igor Sysoev236e0452004-09-23 16:39:34 +00001887 b = c->buffer;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001888
Igor Sysoev236e0452004-09-23 16:39:34 +00001889 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001890
1891 /*
1892 * the special note for ngx_http_keepalive_handler() that
1893 * c->buffer's memory was freed
1894 */
1895
Igor Sysoev236e0452004-09-23 16:39:34 +00001896 b->pos = NULL;
1897
1898 } else {
1899 b->pos = b->start;
1900 b->last = b->start;
1901 }
1902
Igor Sysoev1b735832004-11-11 14:07:14 +00001903 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00001904 hc->free, hc->nfree);
1905
1906 if (hc->free) {
1907 for (i = 0; i < hc->nfree; i++) {
1908 ngx_pfree(c->pool, hc->free[i]);
1909 hc->free[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001910 }
1911
Igor Sysoev236e0452004-09-23 16:39:34 +00001912 hc->nfree = 0;
1913 }
1914
Igor Sysoev1b735832004-11-11 14:07:14 +00001915 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",
Igor Sysoev236e0452004-09-23 16:39:34 +00001916 hc->busy, hc->nbusy);
1917
1918 if (hc->busy) {
1919 for (i = 0; i < hc->nbusy; i++) {
1920 ngx_pfree(c->pool, hc->busy[i]);
1921 hc->busy[i] = NULL;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001922 }
1923
Igor Sysoev236e0452004-09-23 16:39:34 +00001924 hc->nbusy = 0;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001925 }
1926
Igor Sysoev899b44e2005-05-12 14:58:06 +00001927 rev->handler = ngx_http_keepalive_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001928
Igor Sysoevd3283ff2005-12-05 13:18:09 +00001929 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
1930 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
1931 ngx_http_close_connection(c);
1932 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001933 }
1934 }
1935
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001936 c->log->action = "keepalive";
Igor Sysoev6a644c62003-03-04 06:33:48 +00001937
Igor Sysoev67f450d2004-06-01 06:04:46 +00001938 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
Igor Sysoevc1571722005-03-19 12:38:37 +00001939 if (ngx_tcp_push(c->fd) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00001940 ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
1941 ngx_http_close_connection(c);
1942 return;
Igor Sysoev9cf78302003-06-04 17:28:33 +00001943 }
Igor Sysoev924bd792004-10-11 15:07:03 +00001944
Igor Sysoev67f450d2004-06-01 06:04:46 +00001945 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
Igor Sysoev42b12b32004-12-02 18:40:46 +00001946 tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
Igor Sysoev924bd792004-10-11 15:07:03 +00001947
1948 } else {
Igor Sysoev42b12b32004-12-02 18:40:46 +00001949 tcp_nodelay = 1;
1950 }
Igor Sysoev924bd792004-10-11 15:07:03 +00001951
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001952 if (tcp_nodelay
1953 && clcf->tcp_nodelay
1954 && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
1955 {
Igor Sysoev42b12b32004-12-02 18:40:46 +00001956 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
Igor Sysoev924bd792004-10-11 15:07:03 +00001957
Igor Sysoev42b12b32004-12-02 18:40:46 +00001958 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
Igor Sysoevcdf609a2006-04-17 19:55:41 +00001959 (const void *) &tcp_nodelay, sizeof(int))
1960 == -1)
Igor Sysoev42b12b32004-12-02 18:40:46 +00001961 {
1962 ngx_connection_error(c, ngx_socket_errno,
1963 "setsockopt(TCP_NODELAY) failed");
1964 ngx_http_close_connection(c);
1965 return;
Igor Sysoev924bd792004-10-11 15:07:03 +00001966 }
Igor Sysoev42b12b32004-12-02 18:40:46 +00001967
Igor Sysoeve5a222c2005-01-25 12:27:35 +00001968 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
Igor Sysoev9cf78302003-06-04 17:28:33 +00001969 }
1970
Igor Sysoevf7abd722004-09-23 06:32:00 +00001971#if 0
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00001972 /* if ngx_http_request_t was freed then we need some other place */
Igor Sysoevc83f6832004-06-24 07:53:37 +00001973 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
Igor Sysoevf7abd722004-09-23 06:32:00 +00001974#endif
Igor Sysoevc83f6832004-06-24 07:53:37 +00001975
Igor Sysoevb5faed22003-10-29 08:30:44 +00001976 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001977 ngx_http_keepalive_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00001978 }
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001979}
1980
1981
Igor Sysoevc1571722005-03-19 12:38:37 +00001982static void
1983ngx_http_keepalive_handler(ngx_event_t *rev)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001984{
Igor Sysoevc1571722005-03-19 12:38:37 +00001985 size_t size;
1986 ssize_t n;
1987 ngx_buf_t *b;
1988 ngx_connection_t *c;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001989
Igor Sysoev0ad25372004-07-16 06:33:35 +00001990 c = rev->data;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001991
Igor Sysoeve04084c2004-01-26 08:52:49 +00001992 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
Igor Sysoev1af7c822002-09-13 14:47:42 +00001993
Igor Sysoevdc479b42003-03-20 16:09:44 +00001994 if (rev->timedout) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001995 ngx_http_close_connection(c);
1996 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00001997 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001998
Igor Sysoevf6906042004-11-25 16:17:31 +00001999#if (NGX_HAVE_KQUEUE)
Igor Sysoev236e0452004-09-23 16:39:34 +00002000
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002001 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
Igor Sysoevcdc46302005-12-07 14:51:31 +00002002 if (rev->pending_eof) {
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002003 c->log->handler = NULL;
Igor Sysoev236e0452004-09-23 16:39:34 +00002004 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
Igor Sysoev1b735832004-11-11 14:07:14 +00002005 "kevent() reported that client %V closed "
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002006 "keepalive connection", &c->addr_text);
Igor Sysoev42b12b32004-12-02 18:40:46 +00002007#if (NGX_HTTP_SSL)
2008 if (c->ssl) {
Igor Sysoev9fa5a822005-09-30 14:41:25 +00002009 c->ssl->no_send_shutdown = 1;
Igor Sysoev42b12b32004-12-02 18:40:46 +00002010 }
2011#endif
Igor Sysoev236e0452004-09-23 16:39:34 +00002012 ngx_http_close_connection(c);
2013 return;
2014 }
2015 }
2016
2017#endif
2018
Igor Sysoev236e0452004-09-23 16:39:34 +00002019 b = c->buffer;
2020 size = b->end - b->start;
2021
2022 if (b->pos == NULL) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +00002023
2024 /*
2025 * The c->buffer's memory was freed by ngx_http_set_keepalive().
2026 * However, the c->buffer->start and c->buffer->end were not changed
2027 * to keep the buffer size.
2028 */
2029
Igor Sysoevc1571722005-03-19 12:38:37 +00002030 b->pos = ngx_palloc(c->pool, size);
2031 if (b->pos == NULL) {
Igor Sysoev236e0452004-09-23 16:39:34 +00002032 ngx_http_close_connection(c);
2033 return;
2034 }
2035
2036 b->start = b->pos;
2037 b->last = b->pos;
2038 b->end = b->pos + size;
2039 }
Igor Sysoevf7abd722004-09-23 06:32:00 +00002040
Igor Sysoev0a280a32003-10-12 16:49:16 +00002041 /*
2042 * MSIE closes a keepalive connection with RST flag
2043 * so we ignore ECONNRESET here.
2044 */
Igor Sysoevb7387572003-03-11 20:38:13 +00002045
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002046 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
Igor Sysoevb7387572003-03-11 20:38:13 +00002047 ngx_set_socket_errno(0);
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00002048
Igor Sysoev236e0452004-09-23 16:39:34 +00002049 n = c->recv(c, b->last, size);
Igor Sysoevc7a2f682004-02-10 16:23:38 +00002050 c->log_error = NGX_ERROR_INFO;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002051
Igor Sysoevd581fd52003-05-13 16:02:32 +00002052 if (n == NGX_AGAIN) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002053 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002054 ngx_http_close_connection(c);
2055 }
2056
Igor Sysoevd581fd52003-05-13 16:02:32 +00002057 return;
2058 }
2059
2060 if (n == NGX_ERROR) {
2061 ngx_http_close_connection(c);
2062 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00002063 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002064
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002065 c->log->handler = NULL;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002066
2067 if (n == 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +00002068 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002069 "client %V closed keepalive connection", &c->addr_text);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002070 ngx_http_close_connection(c);
2071 return;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002072 }
2073
Igor Sysoevf7abd722004-09-23 06:32:00 +00002074 b->last += n;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002075
Igor Sysoev055951d2005-10-21 19:12:18 +00002076#if (NGX_STAT_STUB)
2077 ngx_atomic_fetch_add(ngx_stat_reading, 1);
2078#endif
2079
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002080 c->log->handler = ngx_http_log_error;
2081 c->log->action = "reading client request line";
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002082
Igor Sysoevd581fd52003-05-13 16:02:32 +00002083 ngx_http_init_request(rev);
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002084}
2085
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002086
Igor Sysoevc1571722005-03-19 12:38:37 +00002087static void
2088ngx_http_set_lingering_close(ngx_http_request_t *r)
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002089{
Igor Sysoev0a280a32003-10-12 16:49:16 +00002090 ngx_event_t *rev, *wev;
Igor Sysoevb7387572003-03-11 20:38:13 +00002091 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002092 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002093
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00002094 c = r->connection;
Igor Sysoev9b25d692003-01-26 21:08:14 +00002095
Igor Sysoev6253ca12003-05-27 12:18:54 +00002096 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00002097
Igor Sysoev0a280a32003-10-12 16:49:16 +00002098 rev = c->read;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002099 rev->handler = ngx_http_lingering_close_handler;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002100
Igor Sysoev208eed22005-10-07 13:30:52 +00002101 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
Igor Sysoev6253ca12003-05-27 12:18:54 +00002102 ngx_add_timer(rev, clcf->lingering_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +00002103
Igor Sysoev899b44e2005-05-12 14:58:06 +00002104 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00002105 ngx_http_close_request(r, 0);
Igor Sysoev0a280a32003-10-12 16:49:16 +00002106 return;
2107 }
2108
2109 wev = c->write;
Igor Sysoev899b44e2005-05-12 14:58:06 +00002110 wev->handler = ngx_http_empty_handler;
Igor Sysoev0a280a32003-10-12 16:49:16 +00002111
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002112 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2113 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
2114 ngx_http_close_request(r, 0);
2115 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00002116 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002117 }
2118
Igor Sysoevb7387572003-03-11 20:38:13 +00002119 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00002120 ngx_connection_error(c, ngx_socket_errno,
2121 ngx_shutdown_socket_n " failed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002122 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002123 return;
Igor Sysoev42feecb2002-12-15 06:25:09 +00002124 }
2125
Igor Sysoevb5faed22003-10-29 08:30:44 +00002126 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002127 ngx_http_lingering_close_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00002128 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00002129}
2130
2131
Igor Sysoevc1571722005-03-19 12:38:37 +00002132static void
2133ngx_http_lingering_close_handler(ngx_event_t *rev)
Igor Sysoev42feecb2002-12-15 06:25:09 +00002134{
Igor Sysoevdc479b42003-03-20 16:09:44 +00002135 ssize_t n;
2136 ngx_msec_t timer;
2137 ngx_connection_t *c;
2138 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +00002139 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002140 u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
Igor Sysoev1af7c822002-09-13 14:47:42 +00002141
Igor Sysoev6253ca12003-05-27 12:18:54 +00002142 c = rev->data;
2143 r = c->data;
Igor Sysoev86de4cb2003-01-30 07:28:09 +00002144
Igor Sysoeve04084c2004-01-26 08:52:49 +00002145 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2146 "http lingering close handler");
Igor Sysoevdc479b42003-03-20 16:09:44 +00002147
2148 if (rev->timedout) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002149 c->timedout = 1;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002150 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002151 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002152 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002153
Igor Sysoevc0247302004-06-27 18:01:57 +00002154 timer = r->lingering_time - ngx_time();
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002155 if (timer <= 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002156 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002157 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002158 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002159
Igor Sysoevdc479b42003-03-20 16:09:44 +00002160 do {
Igor Sysoevf7abd722004-09-23 06:32:00 +00002161 n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002162
Igor Sysoeve04084c2004-01-26 08:52:49 +00002163 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002164
Igor Sysoevdc479b42003-03-20 16:09:44 +00002165 if (n == NGX_ERROR || n == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002166 ngx_http_close_request(r, 0);
Igor Sysoevd581fd52003-05-13 16:02:32 +00002167 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002168 }
2169
2170 } while (rev->ready);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002171
Igor Sysoev899b44e2005-05-12 14:58:06 +00002172 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb1dfe472004-12-21 12:30:30 +00002173 ngx_http_close_request(r, 0);
Igor Sysoev6a12fc92004-12-06 14:45:08 +00002174 return;
2175 }
2176
Igor Sysoevf7abd722004-09-23 06:32:00 +00002177 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2178
Igor Sysoev682bf8e2002-09-16 15:01:44 +00002179 timer *= 1000;
Igor Sysoevf7abd722004-09-23 06:32:00 +00002180
Igor Sysoev6253ca12003-05-27 12:18:54 +00002181 if (timer > clcf->lingering_timeout) {
2182 timer = clcf->lingering_timeout;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00002183 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00002184
Igor Sysoevdc479b42003-03-20 16:09:44 +00002185 ngx_add_timer(rev, timer);
Igor Sysoev1af7c822002-09-13 14:47:42 +00002186}
2187
Igor Sysoev2b542382002-08-20 14:48:28 +00002188
Igor Sysoevc1571722005-03-19 12:38:37 +00002189void
2190ngx_http_empty_handler(ngx_event_t *wev)
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002191{
Igor Sysoeve04084c2004-01-26 08:52:49 +00002192 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00002193
2194 return;
2195}
2196
2197
Igor Sysoev899b44e2005-05-12 14:58:06 +00002198void
2199ngx_http_request_empty_handler(ngx_http_request_t *r)
2200{
2201 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002202 "http request empty handler");
Igor Sysoev899b44e2005-05-12 14:58:06 +00002203
2204 return;
2205}
2206
2207
Igor Sysoevc1571722005-03-19 12:38:37 +00002208ngx_int_t
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002209ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002210{
Igor Sysoev369145c2004-05-28 15:49:23 +00002211 ngx_buf_t *b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002212 ngx_chain_t out;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002213
Igor Sysoevc1571722005-03-19 12:38:37 +00002214 b = ngx_calloc_buf(r->pool);
2215 if (b == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +00002216 return NGX_ERROR;
2217 }
2218
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002219 if (flags & NGX_HTTP_LAST) {
2220 b->last_buf = 1;
2221 }
2222
2223 if (flags & NGX_HTTP_FLUSH) {
2224 b->flush = 1;
2225 }
2226
Igor Sysoev369145c2004-05-28 15:49:23 +00002227 out.buf = b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002228 out.next = NULL;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002229
Igor Sysoev419f9ac2003-10-21 16:49:56 +00002230 return ngx_http_output_filter(r, &out);
Igor Sysoev1342d9c2003-10-09 07:00:45 +00002231}
2232
2233
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002234static ngx_int_t
2235ngx_http_post_action(ngx_http_request_t *r)
2236{
2237 ngx_http_core_loc_conf_t *clcf;
2238
2239 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2240
2241 if (clcf->post_action.data == NULL) {
2242 return NGX_DECLINED;
2243 }
2244
Igor Sysoev8fea8852006-03-15 09:53:04 +00002245 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2246 "post action: \"%V\"", &clcf->post_action);
2247
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002248 r->http_version = NGX_HTTP_VERSION_9;
2249 r->header_only = 1;
Igor Sysoev6d16e1e2006-04-05 13:40:54 +00002250 r->post_action = 1;
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002251
Igor Sysoevcf100a72006-12-11 08:31:54 +00002252 r->read_event_handler = ngx_http_block_read;
2253
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002254 ngx_http_internal_redirect(r, &clcf->post_action, NULL);
2255
2256 return NGX_OK;
2257}
2258
2259
2260static void
Igor Sysoev899b44e2005-05-12 14:58:06 +00002261ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error)
Igor Sysoevd581fd52003-05-13 16:02:32 +00002262{
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002263 ngx_connection_t *c;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002264
2265 c = r->connection;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002266
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002267 ngx_http_request_done(r->main, error);
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002268 ngx_http_close_connection(c);
2269}
2270
2271
Igor Sysoevc2807ec2006-02-16 15:26:46 +00002272static void
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002273ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error)
2274{
2275 ngx_log_t *log;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002276 ngx_uint_t i, n;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002277 struct linger linger;
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002278 ngx_http_cleanup_t *cln;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002279 ngx_http_log_ctx_t *ctx;
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002280 ngx_http_handler_pt *log_handler;
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002281 ngx_http_core_loc_conf_t *clcf;
2282 ngx_http_core_main_conf_t *cmcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002283
Igor Sysoev865c1502003-11-30 20:03:18 +00002284 log = r->connection->log;
2285
2286 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002287
2288 if (r->pool == NULL) {
Igor Sysoev90c08142005-07-25 09:41:38 +00002289 ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00002290 return;
2291 }
2292
Igor Sysoev4ecb4d72006-04-21 12:06:44 +00002293 for (cln = r->cleanup; cln; cln = cln->next) {
2294 if (cln->handler) {
2295 cln->handler(cln->data);
2296 }
2297 }
2298
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002299#if (NGX_STAT_STUB)
Igor Sysoev055951d2005-10-21 19:12:18 +00002300
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002301 if (r->stat_reading) {
Igor Sysoev78452232005-10-12 13:50:36 +00002302 ngx_atomic_fetch_add(ngx_stat_reading, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002303 }
2304
2305 if (r->stat_writing) {
Igor Sysoev78452232005-10-12 13:50:36 +00002306 ngx_atomic_fetch_add(ngx_stat_writing, -1);
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002307 }
Igor Sysoev055951d2005-10-21 19:12:18 +00002308
Igor Sysoev85cccfb2004-09-15 16:00:43 +00002309#endif
2310
Igor Sysoev669e3312003-12-22 09:40:48 +00002311 if (error && r->headers_out.status == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00002312 r->headers_out.status = error;
2313 }
2314
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002315 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2316
Igor Sysoevc31a9bb2005-11-26 10:11:11 +00002317 log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
2318 n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
2319 for (i = 0; i < n; i++) {
2320 log_handler[i](r);
Igor Sysoev9ac946b2005-10-24 15:09:41 +00002321 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00002322
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002323 if (r->connection->timedout) {
2324 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2325
2326 if (clcf->reset_timedout_connection) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002327 linger.l_onoff = 1;
2328 linger.l_linger = 0;
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002329
2330 if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
Igor Sysoev899b44e2005-05-12 14:58:06 +00002331 (const void *) &linger, sizeof(struct linger)) == -1)
Igor Sysoev0ab91b92004-06-06 19:49:18 +00002332 {
2333 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
2334 "setsockopt(SO_LINGER) failed");
2335 }
2336 }
2337 }
2338
Igor Sysoev899b44e2005-05-12 14:58:06 +00002339 /* the various request strings were allocated from r->pool */
Igor Sysoev865c1502003-11-30 20:03:18 +00002340 ctx = log->data;
Igor Sysoev1b735832004-11-11 14:07:14 +00002341 ctx->request = NULL;
Igor Sysoevd581fd52003-05-13 16:02:32 +00002342
Igor Sysoevc83f6832004-06-24 07:53:37 +00002343 r->request_line.len = 0;
2344
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002345 r->connection->destroyed = 1;
2346
Igor Sysoevd581fd52003-05-13 16:02:32 +00002347 ngx_destroy_pool(r->pool);
2348}
2349
2350
Igor Sysoev90c08142005-07-25 09:41:38 +00002351static void
Igor Sysoevc1571722005-03-19 12:38:37 +00002352ngx_http_close_connection(ngx_connection_t *c)
Igor Sysoev6b863e32003-05-12 15:52:24 +00002353{
Igor Sysoev02025fd2005-01-18 13:03:58 +00002354 ngx_pool_t *pool;
2355
Igor Sysoeve04084c2004-01-26 08:52:49 +00002356 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev54498db2004-02-11 17:08:49 +00002357 "close http connection: %d", c->fd);
Igor Sysoev6b863e32003-05-12 15:52:24 +00002358
Igor Sysoevceb99292005-09-06 16:09:32 +00002359#if (NGX_HTTP_SSL)
Igor Sysoev924bd792004-10-11 15:07:03 +00002360
2361 if (c->ssl) {
2362 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +00002363 c->ssl->handler = ngx_http_close_connection;
Igor Sysoev924bd792004-10-11 15:07:03 +00002364 return;
2365 }
2366 }
2367
2368#endif
2369
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002370#if (NGX_STAT_STUB)
Igor Sysoev78452232005-10-12 13:50:36 +00002371 ngx_atomic_fetch_add(ngx_stat_active, -1);
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00002372#endif
2373
Igor Sysoevd3283ff2005-12-05 13:18:09 +00002374 c->destroyed = 1;
2375
Igor Sysoev02025fd2005-01-18 13:03:58 +00002376 pool = c->pool;
2377
Igor Sysoev59cf56c2004-09-07 15:29:22 +00002378 ngx_close_connection(c);
Igor Sysoev02025fd2005-01-18 13:03:58 +00002379
Igor Sysoevc1571722005-03-19 12:38:37 +00002380 ngx_destroy_pool(pool);
Igor Sysoev2ba1ee02002-10-04 17:58:04 +00002381}
2382
2383
Igor Sysoevc1571722005-03-19 12:38:37 +00002384static u_char *
2385ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00002386{
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002387 u_char *p;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002388 ngx_http_request_t *r;
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002389 ngx_http_log_ctx_t *ctx;
Igor Sysoev7578ec92003-06-02 15:24:30 +00002390
Igor Sysoeve5a222c2005-01-25 12:27:35 +00002391 if (log->action) {
Igor Sysoev899b44e2005-05-12 14:58:06 +00002392 p = ngx_snprintf(buf, len, " while %s", log->action);
Igor Sysoev1b735832004-11-11 14:07:14 +00002393 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002394 buf = p;
Igor Sysoevdc479b42003-03-20 16:09:44 +00002395 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002396
Igor Sysoev899b44e2005-05-12 14:58:06 +00002397 ctx = log->data;
2398
Igor Sysoevc04deca2005-03-28 14:43:02 +00002399 p = ngx_snprintf(buf, len, ", client: %V", ctx->client);
Igor Sysoev899b44e2005-05-12 14:58:06 +00002400 len -= p - buf;
Igor Sysoev1b735832004-11-11 14:07:14 +00002401
Igor Sysoevc04deca2005-03-28 14:43:02 +00002402 r = ctx->request;
2403
Igor Sysoev899b44e2005-05-12 14:58:06 +00002404 if (r) {
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002405 return r->log_handler(r, ctx->current_request, p, len);
Igor Sysoev1b735832004-11-11 14:07:14 +00002406 }
2407
Igor Sysoev899b44e2005-05-12 14:58:06 +00002408 return p;
2409}
2410
2411
2412static u_char *
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002413ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
2414 u_char *buf, size_t len)
Igor Sysoev899b44e2005-05-12 14:58:06 +00002415{
Igor Sysoev3d2fd182006-12-04 16:46:13 +00002416 char *uri_separator;
2417 u_char *p;
2418 ngx_http_upstream_t *u;
Igor Sysoev1b735832004-11-11 14:07:14 +00002419
Igor Sysoevc04deca2005-03-28 14:43:02 +00002420 if (r->server_name.data) {
2421 p = ngx_snprintf(buf, len, ", server: %V", &r->server_name);
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002422 len -= p - buf;
Igor Sysoevc04deca2005-03-28 14:43:02 +00002423 buf = p;
Igor Sysoev4d656dc2005-03-22 16:02:46 +00002424 }
2425
Igor Sysoevc04deca2005-03-28 14:43:02 +00002426 if (r->unparsed_uri.data) {
2427 p = ngx_snprintf(buf, len, ", URL: \"%V\"", &r->unparsed_uri);
2428 len -= p - buf;
2429 buf = p;
Igor Sysoev1b735832004-11-11 14:07:14 +00002430
Igor Sysoevc04deca2005-03-28 14:43:02 +00002431 } else {
2432 if (r->request_line.data == NULL && r->request_start) {
2433 for (p = r->request_start; p < r->header_in->last; p++) {
2434 if (*p == CR || *p == LF) {
2435 break;
2436 }
2437 }
2438
2439 r->request_line.len = p - r->request_start;
2440 r->request_line.data = r->request_start;
2441 }
2442
2443 if (r->request_line.len) {
2444 p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
2445 len -= p - buf;
2446 buf = p;
2447 }
Igor Sysoev1b735832004-11-11 14:07:14 +00002448 }
2449
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002450 if (r != sr) {
2451 p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
2452 len -= p - buf;
2453 buf = p;
2454 }
2455
2456 u = sr->upstream;
2457
Igor Sysoev3d2fd182006-12-04 16:46:13 +00002458 if (u && u->peer.name) {
2459
2460 uri_separator = "";
2461
2462#if (NGX_HAVE_UNIX_DOMAIN)
2463 if (u->peer.sockaddr && u->peer.sockaddr->sa_family == AF_UNIX) {
2464 uri_separator = ":";
2465 }
2466#endif
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002467
2468 p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
Igor Sysoev3d2fd182006-12-04 16:46:13 +00002469 &u->conf->schema, u->peer.name,
2470 uri_separator, &u->uri);
Igor Sysoevbb28b6d2006-07-11 13:20:19 +00002471 len -= p - buf;
2472 buf = p;
2473 }
2474
Igor Sysoevc04deca2005-03-28 14:43:02 +00002475 if (r->headers_in.host) {
2476 p = ngx_snprintf(buf, len, ", host: \"%V\"",
2477 &r->headers_in.host->value);
2478 len -= p - buf;
2479 buf = p;
2480 }
2481
2482 if (r->headers_in.referer) {
2483 p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
2484 &r->headers_in.referer->value);
2485 buf = p;
2486 }
2487
2488 return buf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00002489}