blob: 8b44accd81abb29592d0d6c12b1196dd988b27f5 [file] [log] [blame]
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00001
2#include <ngx_config.h>
Igor Sysoev0ad17c02002-08-26 15:18:19 +00003#include <ngx_core.h>
Igor Sysoevfcce8d52003-01-23 18:47:54 +00004#include <ngx_event.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00005#include <ngx_http.h>
6
Igor Sysoeva58e3ca2002-09-02 14:48:24 +00007
Igor Sysoev6b863e32003-05-12 15:52:24 +00008static void ngx_http_init_request(ngx_event_t *ev);
Igor Sysoevf38e0462004-07-16 17:11:43 +00009#if (NGX_HTTP_SSL)
Igor Sysoev74a5ddb2004-07-18 19:11:20 +000010static void ngx_http_ssl_handshake(ngx_event_t *rev);
Igor Sysoevf38e0462004-07-16 17:11:43 +000011#endif
Igor Sysoev6b863e32003-05-12 15:52:24 +000012static void ngx_http_process_request_line(ngx_event_t *rev);
13static void ngx_http_process_request_headers(ngx_event_t *rev);
Igor Sysoev6b863e32003-05-12 15:52:24 +000014static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
Igor Sysoev2f657222004-06-16 15:32:11 +000015static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
Igor Sysoev6b863e32003-05-12 15:52:24 +000016
Igor Sysoevb3e73d82003-10-10 15:10:50 +000017static void ngx_http_set_write_handler(ngx_http_request_t *r);
Igor Sysoev6b863e32003-05-12 15:52:24 +000018
Igor Sysoev6ddfbf02003-05-15 15:42:53 +000019static void ngx_http_block_read(ngx_event_t *ev);
20static void ngx_http_read_discarded_body_event(ngx_event_t *rev);
Igor Sysoev2f657222004-06-16 15:32:11 +000021static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r);
Igor Sysoev3a40d482002-09-12 14:42:29 +000022
Igor Sysoevd581fd52003-05-13 16:02:32 +000023static void ngx_http_set_keepalive(ngx_http_request_t *r);
24static void ngx_http_keepalive_handler(ngx_event_t *ev);
25static void ngx_http_set_lingering_close(ngx_http_request_t *r);
26static void ngx_http_lingering_close_handler(ngx_event_t *ev);
27
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000028static void ngx_http_client_error(ngx_http_request_t *r,
29 int client_error, int error);
Igor Sysoev0ad17c02002-08-26 15:18:19 +000030static size_t ngx_http_log_error(void *data, char *buf, size_t len);
31
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000032
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000033/* NGX_HTTP_PARSE_... errors */
Igor Sysoev0ad17c02002-08-26 15:18:19 +000034
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000035static char *client_header_errors[] = {
Igor Sysoev016b8522002-08-29 16:59:54 +000036 "client %s sent invalid method",
37 "client %s sent invalid request",
Igor Sysoev1af7c822002-09-13 14:47:42 +000038 "client %s sent too long URI",
Igor Sysoev6ddfbf02003-05-15 15:42:53 +000039 "client %s sent invalid method in HTTP/0.9 request",
Igor Sysoev6a644c62003-03-04 06:33:48 +000040
41 "client %s sent invalid header, URL: %s",
42 "client %s sent too long header line, URL: %s",
Igor Sysoev980a9242004-09-05 19:54:02 +000043 "client %s sent too many headers, URL: %s",
Igor Sysoeva09f08d2003-04-25 14:43:13 +000044 "client %s sent HTTP/1.1 request without \"Host\" header, URL: %s",
Igor Sysoev6707ba92004-03-30 15:59:50 +000045 "client %s sent invalid \"Content-Length\" header, URL: %s",
Igor Sysoev3043bfc2004-05-14 16:51:47 +000046 "client %s sent POST method without \"Content-Length\" header, URL: %s",
Igor Sysoevf38e0462004-07-16 17:11:43 +000047 "client %s sent plain HTTP request to HTTPS port, URL: %s",
Igor Sysoev3043bfc2004-05-14 16:51:47 +000048 "client %s sent invalid \"Host\" header \"%s\", URL: %s"
Igor Sysoev016b8522002-08-29 16:59:54 +000049};
50
51
Igor Sysoevaab4d8c2004-09-06 18:45:00 +000052ngx_http_header_t ngx_http_headers_in[] = {
53 { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host) },
54 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection) },
55 { ngx_string("If-Modified-Since"),
56 offsetof(ngx_http_headers_in_t, if_modified_since) },
57 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) },
58 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer) },
59 { ngx_string("Content-Length"),
60 offsetof(ngx_http_headers_in_t, content_length) },
61
62 { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range) },
63#if 0
64 { ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range) },
65#endif
66
67#if (NGX_HTTP_GZIP)
68 { ngx_string("Accept-Encoding"),
69 offsetof(ngx_http_headers_in_t, accept_encoding) },
70 { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via) },
71#endif
72
73 { ngx_string("Authorization"),
74 offsetof(ngx_http_headers_in_t, authorization) },
75
76 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive) },
77
78#if (NGX_HTTP_PROXY)
79 { ngx_string("X-Forwarded-For"),
80 offsetof(ngx_http_headers_in_t, x_forwarded_for) },
81#endif
82
83 { ngx_null_string, 0 }
84};
85
86
Igor Sysoevdc867cd2003-12-14 20:10:27 +000087#if 0
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000088static void ngx_http_dummy(ngx_event_t *wev)
89{
90 return;
91}
Igor Sysoevdc867cd2003-12-14 20:10:27 +000092#endif
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000093
94
Igor Sysoev6b863e32003-05-12 15:52:24 +000095void ngx_http_init_connection(ngx_connection_t *c)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000096{
Igor Sysoev6253ca12003-05-27 12:18:54 +000097 ngx_event_t *rev;
Igor Sysoev160d7742003-11-19 16:26:41 +000098 ngx_http_log_ctx_t *ctx;
Igor Sysoev6b863e32003-05-12 15:52:24 +000099
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000100#if (NGX_STAT_STUB)
101 (*ngx_stat_reading)++;
102#endif
103
Igor Sysoev160d7742003-11-19 16:26:41 +0000104 if (!(ctx = ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t)))) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000105 ngx_http_close_connection(c);
106 return;
107 }
108
Igor Sysoev160d7742003-11-19 16:26:41 +0000109 ctx->connection = c->number;
110 ctx->client = c->addr_text.data;
111 ctx->action = "reading client request line";
112 c->log->data = ctx;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000113 c->log->handler = ngx_http_log_error;
Igor Sysoevc7a2f682004-02-10 16:23:38 +0000114 c->log_error = NGX_ERROR_INFO;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000115
Igor Sysoevdc479b42003-03-20 16:09:44 +0000116 rev = c->read;
117 rev->event_handler = ngx_http_init_request;
Igor Sysoev2ba1ee02002-10-04 17:58:04 +0000118
Igor Sysoev7b6062a2004-02-12 20:57:10 +0000119 /* STUB: epoll edge */ c->write->event_handler = ngx_http_empty_handler;
Igor Sysoev7af6b162004-02-09 07:46:43 +0000120
Igor Sysoevdc479b42003-03-20 16:09:44 +0000121 if (rev->ready) {
Igor Sysoev0ab91b92004-06-06 19:49:18 +0000122 /* the deferred accept(), rtsig, aio, iocp */
Igor Sysoev709405b2004-03-31 15:26:46 +0000123
Igor Sysoev67f450d2004-06-01 06:04:46 +0000124 if (ngx_accept_mutex) {
Igor Sysoev709405b2004-03-31 15:26:46 +0000125 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
126 ngx_http_close_connection(c);
127 return;
128 }
129
Igor Sysoev3d540612004-04-13 15:08:48 +0000130 ngx_post_event(rev);
Igor Sysoev709405b2004-03-31 15:26:46 +0000131
132 ngx_mutex_unlock(ngx_posted_events_mutex);
133 return;
134 }
135
Igor Sysoev6b863e32003-05-12 15:52:24 +0000136 ngx_http_init_request(rev);
137 return;
Igor Sysoev016b8522002-08-29 16:59:54 +0000138 }
Igor Sysoev73009772003-02-06 17:21:13 +0000139
Igor Sysoev239baac2003-06-11 15:28:34 +0000140 ngx_add_timer(rev, c->listening->post_accept_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000141
Igor Sysoevb5faed22003-10-29 08:30:44 +0000142 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000143 ngx_http_close_connection(c);
144 return;
145 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000146
147#if 0
Igor Sysoevfe0f5cc2003-10-31 16:05:33 +0000148 /* TODO: learn SO_SNDBUF (to use in zerocopy) via kqueue's EV_CLEAR event */
149
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000150 c->write->ready = 0;
151 c->write->event_handler = ngx_http_dummy;
152
153 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
154 ngx_http_close_connection(c);
155 return;
156 }
157#endif
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000158}
159
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000160
Igor Sysoev6b863e32003-05-12 15:52:24 +0000161static void ngx_http_init_request(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000162{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000163 ngx_uint_t i;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000164 socklen_t len;
165 struct sockaddr_in addr_in;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000166 ngx_connection_t *c;
167 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000168 ngx_http_in_port_t *in_port;
169 ngx_http_in_addr_t *in_addr;
170 ngx_http_server_name_t *server_name;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000171 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev890fc962003-07-20 21:15:59 +0000172 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000173#if (NGX_HTTP_SSL)
174 ngx_http_ssl_srv_conf_t *sscf;
175#endif
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000176
Igor Sysoeva9830112003-05-19 16:39:14 +0000177 c = rev->data;
Igor Sysoeva9830112003-05-19 16:39:14 +0000178
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000179 if (rev->timedout) {
180 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
181 ngx_http_close_connection(c);
182 return;
183 }
184
Igor Sysoev0a280a32003-10-12 16:49:16 +0000185 if (c->data) {
186 r = c->data;
187 ngx_memzero(r, sizeof(ngx_http_request_t));
188
189 } else {
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000190 if (!(r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)))) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000191 ngx_http_close_connection(c);
192 return;
193 }
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000194
195 c->data = r;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000196 }
197
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000198 c->sent = 0;
Igor Sysoevc83f6832004-06-24 07:53:37 +0000199 r->signature = NGX_HTTP_MODULE;
Igor Sysoev3b30a902003-12-25 20:26:58 +0000200
Igor Sysoev6253ca12003-05-27 12:18:54 +0000201 /* find the server configuration for the address:port */
202
203 /* AF_INET only */
204
205 in_port = c->servers;
206 in_addr = in_port->addrs.elts;
207
208 r->port = in_port->port;
Igor Sysoev0292cbb2004-09-13 16:18:09 +0000209 r->port_text = &in_port->port_text;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000210
211 i = 0;
212
213 if (in_port->addrs.nelts > 1) {
214
Igor Sysoev239baac2003-06-11 15:28:34 +0000215 /*
Igor Sysoevd00b3652004-08-23 19:09:29 +0000216 * There are several addresses on this port and one of them
217 * is the "*:port" wildcard so getsockname() is needed to determine
Igor Sysoev239baac2003-06-11 15:28:34 +0000218 * the server address.
Igor Sysoevd00b3652004-08-23 19:09:29 +0000219 *
Igor Sysoev239baac2003-06-11 15:28:34 +0000220 * AcceptEx() already gave this address.
221 */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000222
Igor Sysoev239baac2003-06-11 15:28:34 +0000223#if (WIN32)
224 if (c->local_sockaddr) {
225 r->in_addr =
226 ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000227
Igor Sysoev239baac2003-06-11 15:28:34 +0000228 } else {
229#endif
230 len = sizeof(struct sockaddr_in);
231 if (getsockname(c->fd, (struct sockaddr *) &addr_in, &len) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +0000232 ngx_connection_error(c, ngx_socket_errno,
233 "getsockname() failed");
Igor Sysoev239baac2003-06-11 15:28:34 +0000234 ngx_http_close_connection(c);
235 return;
236 }
Igor Sysoev10a543a2004-03-16 07:10:12 +0000237
238 r->in_addr = addr_in.sin_addr.s_addr;
239
Igor Sysoev239baac2003-06-11 15:28:34 +0000240#if (WIN32)
Igor Sysoev6253ca12003-05-27 12:18:54 +0000241 }
Igor Sysoev239baac2003-06-11 15:28:34 +0000242#endif
Igor Sysoev6253ca12003-05-27 12:18:54 +0000243
Igor Sysoev6253ca12003-05-27 12:18:54 +0000244 /* the last in_port->addrs address is "*" */
245
246 for ( /* void */ ; i < in_port->addrs.nelts - 1; i++) {
247 if (in_addr[i].addr == r->in_addr) {
248 break;
249 }
250 }
251
252 } else {
253 r->in_addr = in_addr[0].addr;
254 }
255
256 r->virtual_names = &in_addr[i].names;
257
258 /* the default server configuration for the address:port */
259 cscf = in_addr[i].core_srv_conf;
260
261 r->main_conf = cscf->ctx->main_conf;
262 r->srv_conf = cscf->ctx->srv_conf;
263 r->loc_conf = cscf->ctx->loc_conf;
264
Igor Sysoevf38e0462004-07-16 17:11:43 +0000265 rev->event_handler = ngx_http_process_request_line;
266
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000267#if (NGX_HTTP_SSL)
268
Igor Sysoevf38e0462004-07-16 17:11:43 +0000269 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000270 if (sscf->enable) {
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000271
272 if (c->ssl == NULL) {
273 if (ngx_ssl_create_session(sscf->ssl_ctx, c, NGX_SSL_BUFFER)
Igor Sysoevf38e0462004-07-16 17:11:43 +0000274 == NGX_ERROR)
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000275 {
276 ngx_http_close_connection(c);
277 return;
278 }
279
280 /*
281 * The majority of browsers do not send the "close notify" alert.
282 * Among them are MSIE, Mozilla, Netscape 4, Konqueror, and Links.
283 * And what is more MSIE ignores the server's alert.
284 *
285 * Opera always sends the alert.
286 */
287
288 c->ssl->no_rcv_shut = 1;
289 rev->event_handler = ngx_http_ssl_handshake;
Igor Sysoev1c3567e2004-07-15 16:35:51 +0000290 }
291
292 r->filter_need_in_memory = 1;
293 }
294
Igor Sysoev4aa88882004-07-14 20:07:58 +0000295#endif
296
Igor Sysoev6253ca12003-05-27 12:18:54 +0000297 server_name = cscf->server_names.elts;
298 r->server_name = &server_name->name;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000299
Igor Sysoev890fc962003-07-20 21:15:59 +0000300 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
301 c->log->file = clcf->err_log->file;
Igor Sysoevfff32322004-04-08 15:58:25 +0000302 if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
303 c->log->log_level = clcf->err_log->log_level;
304 }
Igor Sysoev890fc962003-07-20 21:15:59 +0000305
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000306 if (c->buffer == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +0000307 c->buffer = ngx_create_temp_buf(c->pool,
308 cscf->client_header_buffer_size);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000309 if (c->buffer == NULL) {
310 ngx_http_close_connection(c);
311 return;
312 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000313 }
314
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000315 if (!(r->pool = ngx_create_pool(cscf->request_pool_size, c->log))) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000316 ngx_http_close_connection(c);
317 return;
318 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000319
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000320 if (ngx_array_init(&r->cleanup, r->pool, 5, sizeof(ngx_http_cleanup_t))
321 == NGX_ERROR)
322 {
Igor Sysoevc2bba092003-11-28 17:41:47 +0000323 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
324 ngx_http_close_connection(c);
325 return;
326 }
Igor Sysoevd00b3652004-08-23 19:09:29 +0000327
Igor Sysoev89690bf2004-03-23 06:01:52 +0000328
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000329 if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
Igor Sysoev980a9242004-09-05 19:54:02 +0000330 sizeof(ngx_table_elt_t)) == NGX_ERROR)
331 {
332 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
333 ngx_http_close_connection(c);
334 return;
335 }
336
337
Igor Sysoev6b863e32003-05-12 15:52:24 +0000338 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
339 if (r->ctx == NULL) {
340 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
341 ngx_http_close_connection(c);
342 return;
343 }
Igor Sysoeve0268b92002-09-11 15:18:33 +0000344
Igor Sysoevc78c41c2004-07-07 06:15:04 +0000345 c->single_connection = 1;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000346 r->connection = c;
347 r->pipeline = c->pipeline;
348 r->header_in = c->buffer;
349
350 r->file.fd = NGX_INVALID_FILE;
351
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000352 r->headers_in.content_length_n = -1;
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000353 r->headers_in.keep_alive_n = -1;
354 r->headers_out.content_length_n = -1;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000355 r->headers_out.last_modified_time = -1;
356
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000357 r->http_state = NGX_HTTP_READING_REQUEST_STATE;
358
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000359#if (NGX_STAT_STUB)
360 (*ngx_stat_requests)++;
361#endif
362
Igor Sysoevf38e0462004-07-16 17:11:43 +0000363 rev->event_handler(rev);
364}
365
366
367#if (NGX_HTTP_SSL)
368
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000369static void ngx_http_ssl_handshake(ngx_event_t *rev)
Igor Sysoevf38e0462004-07-16 17:11:43 +0000370{
371 int n;
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000372 ngx_int_t rc;
Igor Sysoevf38e0462004-07-16 17:11:43 +0000373 u_char buf[1];
374 ngx_connection_t *c;
375 ngx_http_request_t *r;
376
377 c = rev->data;
378 r = c->data;
379
380 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
381 "http check ssl handshake");
382
383 if (rev->timedout) {
384 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
385 return;
386 }
387
388 n = recv(c->fd, buf, 1, MSG_PEEK);
389
390 if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
391 return;
392 }
393
394 if (n == 1) {
395 if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
396 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
397 "https ssl handshake: 0x%X", buf[0]);
398
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000399 c->recv = ngx_ssl_recv;
400 c->send_chain = ngx_ssl_send_chain;
401
402 rc = ngx_ssl_handshake(c);
403
404 if (rc == NGX_ERROR) {
405 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
406 ngx_http_close_connection(r->connection);
407 return;
408 }
409
410 if (rc != NGX_OK) {
411 return;
412 }
Igor Sysoevf38e0462004-07-16 17:11:43 +0000413
414 } else {
415 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
416 "plain http");
417
418 r->plain_http = 1;
419 }
420 }
421
Igor Sysoev6b863e32003-05-12 15:52:24 +0000422 rev->event_handler = ngx_http_process_request_line;
423 ngx_http_process_request_line(rev);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000424}
425
Igor Sysoevf38e0462004-07-16 17:11:43 +0000426#endif
427
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000428
Igor Sysoev6b863e32003-05-12 15:52:24 +0000429static void ngx_http_process_request_line(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000430{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000431 u_char *p;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000432 ssize_t n;
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000433 ngx_int_t rc, offset;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000434 ngx_connection_t *c;
435 ngx_http_request_t *r;
Igor Sysoev160d7742003-11-19 16:26:41 +0000436 ngx_http_log_ctx_t *ctx;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000437 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000438
Igor Sysoeva9830112003-05-19 16:39:14 +0000439 c = rev->data;
440 r = c->data;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000441
Igor Sysoev2b58fbf2003-12-09 15:08:11 +0000442 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
443 "http process request line");
Igor Sysoevdc479b42003-03-20 16:09:44 +0000444
445 if (rev->timedout) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000446 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000447 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000448 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000449
Igor Sysoev6b863e32003-05-12 15:52:24 +0000450 n = ngx_http_read_request_header(r);
Igor Sysoev016b8522002-08-29 16:59:54 +0000451
Igor Sysoev6b863e32003-05-12 15:52:24 +0000452 if (n == NGX_AGAIN || n == NGX_ERROR) {
453 return;
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000454 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000455
Igor Sysoeve6779222003-10-03 15:50:53 +0000456 rc = ngx_http_parse_request_line(r);
Igor Sysoevdc479b42003-03-20 16:09:44 +0000457
Igor Sysoev016b8522002-08-29 16:59:54 +0000458 if (rc == NGX_OK) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000459
Igor Sysoev6b863e32003-05-12 15:52:24 +0000460 /* the request line has been parsed successfully */
461
Igor Sysoeva3677242004-04-14 05:57:36 +0000462#if 0
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000463 /* TODO: we need to handle proxy URIs */
Igor Sysoevc2bba092003-11-28 17:41:47 +0000464 if (r->unusual_uri) {
Igor Sysoev1c104622003-06-03 15:42:58 +0000465 r->request_line.len = r->request_end - r->request_start;
466 r->request_line.data = r->request_start;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000467#if 0
Igor Sysoev1c104622003-06-03 15:42:58 +0000468 r->request_line.data[r->request_line.len] = '\0';
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000469#endif
Igor Sysoev1c104622003-06-03 15:42:58 +0000470
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000471 ngx_http_client_error(r, NGX_HTTP_PARSE_INVALID_REQUEST,
472 NGX_HTTP_BAD_REQUEST);
Igor Sysoev7578ec92003-06-02 15:24:30 +0000473 return;
474 }
Igor Sysoeva3677242004-04-14 05:57:36 +0000475#endif
Igor Sysoev7578ec92003-06-02 15:24:30 +0000476
Igor Sysoev6253ca12003-05-27 12:18:54 +0000477 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoeva9830112003-05-19 16:39:14 +0000478
Igor Sysoeve2a31542003-04-08 15:40:10 +0000479 if (r->http_version >= NGX_HTTP_VERSION_10
Igor Sysoev187fcd82003-05-23 11:53:01 +0000480 && cscf->large_client_header == 0
Igor Sysoeve2a31542003-04-08 15:40:10 +0000481 && r->header_in->pos == r->header_in->end)
482 {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000483 /* no space for "\r\n" at the end of the header */
484
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000485 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
486 NGX_HTTP_REQUEST_URI_TOO_LARGE);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000487 return;
Igor Sysoeve2a31542003-04-08 15:40:10 +0000488 }
489
Igor Sysoev6414b962003-10-24 16:10:38 +0000490
Igor Sysoevc2bba092003-11-28 17:41:47 +0000491 /* copy unparsed URI */
492
493 r->unparsed_uri.len = r->uri_end - r->uri_start;
494 r->unparsed_uri.data = ngx_palloc(r->pool, r->unparsed_uri.len + 1);
495 if (r->unparsed_uri.data == NULL) {
496 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
497 ngx_http_close_connection(c);
498 return;
499 }
500
501 ngx_cpystrn(r->unparsed_uri.data, r->uri_start,
502 r->unparsed_uri.len + 1);
503
504
Igor Sysoev6a644c62003-03-04 06:33:48 +0000505 /* copy URI */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000506
507 if (r->args_start) {
508 r->uri.len = r->args_start - 1 - r->uri_start;
509 } else {
510 r->uri.len = r->uri_end - r->uri_start;
511 }
512
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000513 if (!(r->uri.data = ngx_palloc(r->pool, r->uri.len + 1))) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000514 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
515 ngx_http_close_connection(c);
516 return;
517 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000518
Igor Sysoevc2bba092003-11-28 17:41:47 +0000519 if (r->complex_uri) {
520 rc = ngx_http_parse_complex_uri(r);
Igor Sysoev016b8522002-08-29 16:59:54 +0000521
Igor Sysoev865c1502003-11-30 20:03:18 +0000522 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
523 ngx_http_close_request(r, rc);
524 ngx_http_close_connection(c);
525 return;
526 }
527
528 if (rc != NGX_OK) {
529 r->request_line.len = r->request_end - r->request_start;
530 r->request_line.data = r->request_start;
Igor Sysoev865c1502003-11-30 20:03:18 +0000531
532 ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST);
533 return;
534 }
535
Igor Sysoevc2bba092003-11-28 17:41:47 +0000536 } else {
537 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1);
Igor Sysoeva9830112003-05-19 16:39:14 +0000538 }
539
Igor Sysoeva9830112003-05-19 16:39:14 +0000540
Igor Sysoevdc479b42003-03-20 16:09:44 +0000541 r->request_line.len = r->request_end - r->request_start;
542
Igor Sysoev187fcd82003-05-23 11:53:01 +0000543 if (cscf->large_client_header) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000544
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000545 /*
546 * if the large client headers are enabled then
Igor Sysoeva2aca9a2004-01-18 21:09:21 +0000547 * we need to copy the request line
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000548 */
549
Igor Sysoev6b863e32003-05-12 15:52:24 +0000550 r->request_line.data = ngx_palloc(r->pool, r->request_line.len + 1);
551 if (r->request_line.data == NULL) {
552 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
553 ngx_http_close_connection(c);
554 return;
555 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000556
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000557 ngx_cpystrn(r->request_line.data, r->request_start,
Igor Sysoev6a644c62003-03-04 06:33:48 +0000558 r->request_line.len + 1);
559
560 } else {
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000561 r->request_line.data = r->request_start;
Igor Sysoev6a644c62003-03-04 06:33:48 +0000562 r->request_line.data[r->request_line.len] = '\0';
563 }
564
Igor Sysoeva3677242004-04-14 05:57:36 +0000565 if (r->method == 0) {
566 r->method_name.len = r->method_end - r->request_start + 1;
567 r->method_name.data = r->request_line.data;
568 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000569
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000570 if (r->uri_ext) {
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000571
572 /* copy URI extention */
573
Igor Sysoevdc479b42003-03-20 16:09:44 +0000574 if (r->args_start) {
575 r->exten.len = r->args_start - 1 - r->uri_ext;
576 } else {
577 r->exten.len = r->uri_end - r->uri_ext;
578 }
579
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000580 if (!(r->exten.data = ngx_palloc(r->pool, r->exten.len + 1))) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000581 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
582 ngx_http_close_connection(c);
583 return;
584 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000585
Igor Sysoevb0869052002-12-10 18:05:12 +0000586 ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000587 }
588
Igor Sysoevdc479b42003-03-20 16:09:44 +0000589 if (r->args_start && r->uri_end > r->args_start) {
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000590
591 /* copy URI arguments */
592
Igor Sysoevdc479b42003-03-20 16:09:44 +0000593 r->args.len = r->uri_end - r->args_start;
594
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000595 if (!(r->args.data = ngx_palloc(r->pool, r->args.len + 1))) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000596 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
597 ngx_http_close_connection(c);
598 return;
599 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000600
601 ngx_cpystrn(r->args.data, r->args_start, r->args.len + 1);
602 }
603
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000604 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
605 "http request line: \"%s\"", r->request_line.data);
606
607 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
608 "http uri: \"%s\"", r->uri.data);
609
610 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev10a543a2004-03-16 07:10:12 +0000611 "http args: \"%s\"",
612 r->args.data ? r->args.data : (u_char *) "");
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000613
614 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
615 "http exten: \"%s\"",
Igor Sysoev10a543a2004-03-16 07:10:12 +0000616 r->exten.data ? r->exten.data : (u_char *) "");
Igor Sysoev016b8522002-08-29 16:59:54 +0000617
Igor Sysoev7578ec92003-06-02 15:24:30 +0000618 if (r->http_version < NGX_HTTP_VERSION_10) {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000619 rev->event_handler = ngx_http_block_read;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000620 ngx_http_handler(r);
621 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000622 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000623
Igor Sysoev89690bf2004-03-23 06:01:52 +0000624
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000625 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
Igor Sysoev980a9242004-09-05 19:54:02 +0000626 sizeof(ngx_table_elt_t)) == NGX_ERROR)
627 {
Igor Sysoev89690bf2004-03-23 06:01:52 +0000628 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
629 ngx_http_close_connection(c);
630 return;
631 }
632
Igor Sysoev89690bf2004-03-23 06:01:52 +0000633
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000634 if (ngx_array_init(&r->headers_in.cookies, r->pool, 5,
Igor Sysoev980a9242004-09-05 19:54:02 +0000635 sizeof(ngx_table_elt_t *)) == NGX_ERROR)
636 {
Igor Sysoev967fd632004-08-27 15:40:59 +0000637 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
638 ngx_http_close_connection(c);
639 return;
640 }
641
Igor Sysoev967fd632004-08-27 15:40:59 +0000642
Igor Sysoev160d7742003-11-19 16:26:41 +0000643 ctx = c->log->data;
644 ctx->action = "reading client request headers";
645 ctx->url = r->unparsed_uri.data;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000646
Igor Sysoev187fcd82003-05-23 11:53:01 +0000647 if (cscf->large_client_header
Igor Sysoevdc479b42003-03-20 16:09:44 +0000648 && r->header_in->pos == r->header_in->last)
649 {
650 r->header_in->pos = r->header_in->last = r->header_in->start;
651 }
Igor Sysoev016b8522002-08-29 16:59:54 +0000652
Igor Sysoevd581fd52003-05-13 16:02:32 +0000653 rev->event_handler = ngx_http_process_request_headers;
654 ngx_http_process_request_headers(rev);
655
656 return;
657
Igor Sysoev0dad6292003-03-05 17:30:51 +0000658 } else if (rc != NGX_AGAIN) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000659
660 /* there was error while a request line parsing */
661
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000662 for (p = r->request_start; p < r->header_in->last; p++) {
663 if (*p == CR || *p == LF) {
664 break;
665 }
666 }
667
668 r->request_line.len = p - r->request_start;
669 r->request_line.data = r->request_start;
670
Igor Sysoeva1c8a922004-01-19 18:09:14 +0000671 if (rc == NGX_HTTP_PARSE_INVALID_METHOD) {
672 r->http_version = NGX_HTTP_VERSION_10;
673 }
674
Igor Sysoeva2aca9a2004-01-18 21:09:21 +0000675 ngx_http_client_error(r, rc,
676 (rc == NGX_HTTP_PARSE_INVALID_METHOD) ?
677 NGX_HTTP_NOT_IMPLEMENTED:
678 NGX_HTTP_BAD_REQUEST);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000679 return;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000680 }
681
Igor Sysoev0dad6292003-03-05 17:30:51 +0000682 /* NGX_AGAIN: a request line parsing is still not complete */
683
Igor Sysoevb7387572003-03-11 20:38:13 +0000684 if (r->header_in->last == r->header_in->end) {
Igor Sysoev1af7c822002-09-13 14:47:42 +0000685
Igor Sysoev0a280a32003-10-12 16:49:16 +0000686 /*
687 * If it's a pipelined request and a request line is not complete
Igor Sysoev67f450d2004-06-01 06:04:46 +0000688 * then we have to copy it to the start of the r->header_in buf.
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000689 * We have to copy it here only if the large client headers
Igor Sysoev0a280a32003-10-12 16:49:16 +0000690 * are enabled otherwise a request line had been already copied
Igor Sysoev67f450d2004-06-01 06:04:46 +0000691 * to the start of the r->header_in buf in ngx_http_set_keepalive().
Igor Sysoev0a280a32003-10-12 16:49:16 +0000692 */
Igor Sysoev0dad6292003-03-05 17:30:51 +0000693
Igor Sysoev6253ca12003-05-27 12:18:54 +0000694 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoeva9830112003-05-19 16:39:14 +0000695
Igor Sysoev187fcd82003-05-23 11:53:01 +0000696 if (cscf->large_client_header) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000697 offset = r->request_start - r->header_in->start;
698
699 if (offset == 0) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000700 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
701 NGX_HTTP_REQUEST_URI_TOO_LARGE);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000702 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000703 }
704
705 ngx_memcpy(r->header_in->start, r->request_start,
Igor Sysoevb7387572003-03-11 20:38:13 +0000706 r->header_in->last - r->request_start);
Igor Sysoev0dad6292003-03-05 17:30:51 +0000707
Igor Sysoevb7387572003-03-11 20:38:13 +0000708 r->header_in->pos -= offset;
709 r->header_in->last -= offset;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000710 r->request_start = r->header_in->start;
711 r->request_end -= offset;
712 r->uri_start -= offset;
713 r->uri_end -= offset;
714 if (r->uri_ext) {
715 r->uri_ext -= offset;
716 }
717 if (r->args_start) {
718 r->args_start -= offset;
719 }
720
721 } else {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000722 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
723 NGX_HTTP_REQUEST_URI_TOO_LARGE);
Igor Sysoev0dad6292003-03-05 17:30:51 +0000724 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000725 }
726
Igor Sysoev6b863e32003-05-12 15:52:24 +0000727 return;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000728}
729
Igor Sysoev1af7c822002-09-13 14:47:42 +0000730
Igor Sysoev6b863e32003-05-12 15:52:24 +0000731static void ngx_http_process_request_headers(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000732{
Igor Sysoev187fcd82003-05-23 11:53:01 +0000733 ssize_t n;
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000734 ngx_int_t rc, i, offset;
Igor Sysoev980a9242004-09-05 19:54:02 +0000735 ngx_table_elt_t *h, **cookie;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000736 ngx_connection_t *c;
737 ngx_http_request_t *r;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000738 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000739
Igor Sysoeva9830112003-05-19 16:39:14 +0000740 c = rev->data;
741 r = c->data;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000742
Igor Sysoev865c1502003-11-30 20:03:18 +0000743 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
744 "http process request header line");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000745
Igor Sysoev6b863e32003-05-12 15:52:24 +0000746 if (rev->timedout) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000747 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000748 return;
749 }
750
Igor Sysoev6253ca12003-05-27 12:18:54 +0000751 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
752
Igor Sysoevd581fd52003-05-13 16:02:32 +0000753 rc = NGX_AGAIN;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000754
Igor Sysoev016b8522002-08-29 16:59:54 +0000755 for ( ;; ) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000756 if (rc == NGX_AGAIN) {
757 n = ngx_http_read_request_header(r);
758
759 if (n == NGX_AGAIN || n == NGX_ERROR) {
760 return;
761 }
762 }
763
Igor Sysoev980a9242004-09-05 19:54:02 +0000764 if (r->headers_n > 100) {
765 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_MANY_HEADERS,
766 NGX_HTTP_BAD_REQUEST);
767 return;
768 }
769
Igor Sysoeve6779222003-10-03 15:50:53 +0000770 rc = ngx_http_parse_header_line(r, r->header_in);
Igor Sysoev016b8522002-08-29 16:59:54 +0000771
Igor Sysoev0dad6292003-03-05 17:30:51 +0000772 if (rc == NGX_OK) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000773
774 /* a header line has been parsed successfully */
775
Igor Sysoev980a9242004-09-05 19:54:02 +0000776 r->headers_n++;
777
Igor Sysoevaab4d8c2004-09-06 18:45:00 +0000778 if (!(h = ngx_list_push(&r->headers_in.headers))) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000779 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
780 ngx_http_close_connection(c);
781 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000782 }
783
Igor Sysoevd581fd52003-05-13 16:02:32 +0000784 h->key.len = r->header_name_end - r->header_name_start;
785 h->value.len = r->header_end - r->header_start;
786
787 /* if the large client headers are enabled then
788 we need to copy the header name and value */
789
Igor Sysoev187fcd82003-05-23 11:53:01 +0000790 if (cscf->large_client_header) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000791 h->key.data = ngx_palloc(r->pool,
792 h->key.len + 1 + h->value.len + 1);
793 if (h->key.data == NULL) {
794 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
795 ngx_http_close_connection(c);
796 return;
797 }
798
799 h->value.data = h->key.data + h->key.len + 1;
800 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
801 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
802
803 } else {
804 h->key.data = r->header_name_start;
805 h->key.data[h->key.len] = '\0';
806 h->value.data = r->header_start;
807 h->value.data[h->value.len] = '\0';
808 }
809
Igor Sysoev967fd632004-08-27 15:40:59 +0000810 if (h->key.len == sizeof("Cookie") - 1
811 && ngx_strcasecmp(h->key.data, "Cookie") == 0)
812 {
813 if (!(cookie = ngx_push_array(&r->headers_in.cookies))) {
814 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
815 ngx_http_close_connection(c);
816 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000817 }
818
Igor Sysoev980a9242004-09-05 19:54:02 +0000819 *cookie = h;
Igor Sysoev967fd632004-08-27 15:40:59 +0000820
821 } else {
822
823 for (i = 0; ngx_http_headers_in[i].name.len != 0; i++) {
824 if (ngx_http_headers_in[i].name.len != h->key.len) {
825 continue;
826 }
827
828 if (ngx_strcasecmp(ngx_http_headers_in[i].name.data,
829 h->key.data) == 0)
830 {
831 *((ngx_table_elt_t **) ((char *) &r->headers_in
Igor Sysoevb5faed22003-10-29 08:30:44 +0000832 + ngx_http_headers_in[i].offset)) = h;
Igor Sysoev967fd632004-08-27 15:40:59 +0000833 break;
834 }
Igor Sysoevd581fd52003-05-13 16:02:32 +0000835 }
836 }
837
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000838 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoevfc68ea62003-12-22 17:27:24 +0000839 "http header: \"%s: %s\"",
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000840 h->key.data, h->value.data);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000841
Igor Sysoev187fcd82003-05-23 11:53:01 +0000842 if (cscf->large_client_header
Igor Sysoevdc479b42003-03-20 16:09:44 +0000843 && r->header_in->pos == r->header_in->last)
844 {
845 r->header_in->pos = r->header_in->last = r->header_in->start;
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000846 }
847
Igor Sysoev6253ca12003-05-27 12:18:54 +0000848 continue;
849
Igor Sysoev1af7c822002-09-13 14:47:42 +0000850 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000851
852 /* a whole header has been parsed successfully */
853
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000854 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
855 "http header done");
Igor Sysoev42feecb2002-12-15 06:25:09 +0000856
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000857 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
858
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000859 rc = ngx_http_process_request_header(r);
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000860
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000861 if (rc != NGX_OK) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000862 ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST);
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000863 return;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000864 }
865
Igor Sysoev425a42c2003-10-27 16:16:17 +0000866 if (rev->timer_set) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000867 ngx_del_timer(rev);
868 }
869
Igor Sysoevdc3b2a72004-09-14 19:39:54 +0000870#if (NGX_STAT_STUB)
871 (*ngx_stat_reading)--;
872 (*ngx_stat_writing)++;
873#endif
874
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000875 rev->event_handler = ngx_http_block_read;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000876 ngx_http_handler(r);
877 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000878
Igor Sysoev0dad6292003-03-05 17:30:51 +0000879 } else if (rc != NGX_AGAIN) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000880
881 /* there was error while a header line parsing */
882
Igor Sysoev732a2712004-04-21 18:54:33 +0000883#if (NGX_DEBUG)
884 if (rc == NGX_HTTP_PARSE_INVALID_HEADER
885 && (rev->log->log_level & NGX_LOG_DEBUG_HTTP))
886 {
Igor Sysoev10a543a2004-03-16 07:10:12 +0000887 u_char *p;
Igor Sysoev669e3312003-12-22 09:40:48 +0000888 for (p = r->header_name_start;
889 p < r->header_in->last - 1;
890 p++)
891 {
Igor Sysoev76f7b5e2004-01-29 17:06:07 +0000892 if (*p == LF) {
Igor Sysoev669e3312003-12-22 09:40:48 +0000893 break;
894 }
895 }
896 *p = '\0';
897 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
898 "http invalid header: \"%s\"",
899 r->header_name_start);
900 }
901#endif
902
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000903 ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000904 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000905 }
906
907 /* NGX_AGAIN: a header line parsing is still not complete */
908
Igor Sysoevb7387572003-03-11 20:38:13 +0000909 if (r->header_in->last == r->header_in->end) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000910
Igor Sysoev67f450d2004-06-01 06:04:46 +0000911 /*
912 * if the large client headers are enabled then
913 * we need to compact r->header_in buf
914 */
Igor Sysoev0dad6292003-03-05 17:30:51 +0000915
Igor Sysoev187fcd82003-05-23 11:53:01 +0000916 if (cscf->large_client_header) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000917 offset = r->header_name_start - r->header_in->start;
918
919 if (offset == 0) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000920 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER,
921 NGX_HTTP_BAD_REQUEST);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000922 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000923 }
924
925 ngx_memcpy(r->header_in->start, r->header_name_start,
Igor Sysoevb7387572003-03-11 20:38:13 +0000926 r->header_in->last - r->header_name_start);
Igor Sysoev0dad6292003-03-05 17:30:51 +0000927
Igor Sysoevb7387572003-03-11 20:38:13 +0000928 r->header_in->last -= offset;
929 r->header_in->pos -= offset;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000930 r->header_name_start = r->header_in->start;
931 r->header_name_end -= offset;
932 r->header_start -= offset;
933 r->header_end -= offset;
934
935 } else {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000936 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER,
937 NGX_HTTP_BAD_REQUEST);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000938 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000939 }
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000940 }
941 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000942}
943
Igor Sysoevb0869052002-12-10 18:05:12 +0000944
Igor Sysoev6b863e32003-05-12 15:52:24 +0000945static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
946{
Igor Sysoev187fcd82003-05-23 11:53:01 +0000947 ssize_t n;
948 ngx_event_t *rev;
949 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000950
Igor Sysoev239baac2003-06-11 15:28:34 +0000951 rev = r->connection->read;
952
Igor Sysoev6b863e32003-05-12 15:52:24 +0000953 n = r->header_in->last - r->header_in->pos;
954
955 if (n > 0) {
956 return n;
957 }
958
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000959 if (!rev->ready) {
960 return NGX_AGAIN;
961 }
962
Igor Sysoev74a5ddb2004-07-18 19:11:20 +0000963 n = r->connection->recv(r->connection, r->header_in->last,
964 r->header_in->end - r->header_in->last);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000965
966 if (n == NGX_AGAIN) {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000967 if (!r->header_timeout_set) {
Igor Sysoevf38e0462004-07-16 17:11:43 +0000968 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev187fcd82003-05-23 11:53:01 +0000969 ngx_add_timer(rev, cscf->client_header_timeout);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000970 r->header_timeout_set = 1;
971 }
972
Igor Sysoevb5faed22003-10-29 08:30:44 +0000973 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000974 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
975 ngx_http_close_connection(r->connection);
976 return NGX_ERROR;
977 }
978
Igor Sysoev6b863e32003-05-12 15:52:24 +0000979 return NGX_AGAIN;
980 }
981
982 if (n == 0) {
983 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
984 "client closed prematurely connection");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000985 }
Igor Sysoev6b863e32003-05-12 15:52:24 +0000986
987 if (n == 0 || n == NGX_ERROR) {
988 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000989 ngx_http_close_connection(r->connection);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000990 return NGX_ERROR;
991 }
992
993 r->header_in->last += n;
994
995 return n;
996}
997
998
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000999static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r)
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001000{
Igor Sysoev2f657222004-06-16 15:32:11 +00001001 u_char *ua;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001002 size_t len;
Igor Sysoev10a543a2004-03-16 07:10:12 +00001003 ngx_uint_t i;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001004 ngx_http_server_name_t *name;
Igor Sysoev3043bfc2004-05-14 16:51:47 +00001005 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001006 ngx_http_core_loc_conf_t *clcf;
1007
1008 if (r->headers_in.host) {
1009 for (len = 0; len < r->headers_in.host->value.len; len++) {
1010 if (r->headers_in.host->value.data[len] == ':') {
1011 break;
1012 }
1013 }
1014 r->headers_in.host_name_len = len;
1015
1016 /* find the name based server configuration */
1017
1018 name = r->virtual_names->elts;
1019 for (i = 0; i < r->virtual_names->nelts; i++) {
1020 if (r->headers_in.host_name_len != name[i].name.len) {
1021 continue;
1022 }
1023
1024 if (ngx_strncasecmp(r->headers_in.host->value.data,
1025 name[i].name.data,
1026 r->headers_in.host_name_len) == 0)
1027 {
1028 r->srv_conf = name[i].core_srv_conf->ctx->srv_conf;
1029 r->loc_conf = name[i].core_srv_conf->ctx->loc_conf;
Igor Sysoev5aeeb2d2004-05-04 17:56:58 +00001030 r->server_name = &name[i].name;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001031
1032 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1033 r->connection->log->file = clcf->err_log->file;
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001034 if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION))
1035 {
1036 r->connection->log->log_level = clcf->err_log->log_level;
1037 }
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001038
1039 break;
1040 }
1041 }
1042
Igor Sysoev3043bfc2004-05-14 16:51:47 +00001043 if (i == r->virtual_names->nelts) {
1044 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1045
1046 if (cscf->restrict_host_names != NGX_HTTP_RESTRICT_HOST_OFF) {
1047 return NGX_HTTP_PARSE_INVALID_HOST;
1048 }
1049 }
1050
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001051 } else {
1052 if (r->http_version > NGX_HTTP_VERSION_10) {
1053 return NGX_HTTP_PARSE_NO_HOST_HEADER;
1054 }
1055 r->headers_in.host_name_len = 0;
1056 }
1057
1058 if (r->headers_in.content_length) {
1059 r->headers_in.content_length_n =
1060 ngx_atoi(r->headers_in.content_length->value.data,
1061 r->headers_in.content_length->value.len);
1062
1063 if (r->headers_in.content_length_n == NGX_ERROR) {
1064 return NGX_HTTP_PARSE_INVALID_CL_HEADER;
1065 }
1066 }
1067
Igor Sysoev6881bfb2004-03-30 06:27:36 +00001068 if (r->method == NGX_HTTP_POST && r->headers_in.content_length_n <= 0) {
1069 return NGX_HTTP_PARSE_POST_WO_CL_HEADER;
1070 }
1071
Igor Sysoevf38e0462004-07-16 17:11:43 +00001072 if (r->plain_http) {
1073 return NGX_HTTP_PARSE_HTTP_TO_HTTPS;
1074 }
1075
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001076 if (r->headers_in.connection) {
1077 if (r->headers_in.connection->value.len == 5
1078 && ngx_strcasecmp(r->headers_in.connection->value.data, "close")
1079 == 0)
1080 {
1081 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1082
1083 } else if (r->headers_in.connection->value.len == 10
1084 && ngx_strcasecmp(r->headers_in.connection->value.data,
1085 "keep-alive") == 0)
1086 {
1087 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1088
1089 if (r->headers_in.keep_alive) {
1090 r->headers_in.keep_alive_n =
1091 ngx_atoi(r->headers_in.keep_alive->value.data,
1092 r->headers_in.keep_alive->value.len);
1093 }
1094 }
1095 }
1096
Igor Sysoev2f657222004-06-16 15:32:11 +00001097 if (r->headers_in.user_agent) {
1098
1099 /*
1100 * check some widespread browsers while the headers are still
1101 * in CPU cache
1102 */
1103
Igor Sysoev415b1ce2004-06-17 17:18:53 +00001104 ua = (u_char *) ngx_strstr(r->headers_in.user_agent->value.data,
1105 "MSIE");
Igor Sysoev2f657222004-06-16 15:32:11 +00001106 if (ua
1107 && ua + 8 < r->headers_in.user_agent->value.data
1108 + r->headers_in.user_agent->value.len)
1109 {
1110 r->headers_in.msie = 1;
1111 if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') {
1112 r->headers_in.msie4 = 1;
1113 }
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001114
1115#if 0
1116 /* MSIE ignores the SSL "close notify" alert */
1117
1118 ngx_ssl_set_nosendshut(r->connection->ssl);
1119#endif
Igor Sysoev2f657222004-06-16 15:32:11 +00001120 }
1121 }
1122
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001123 return NGX_OK;
1124}
1125
1126
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001127void ngx_http_finalize_request(ngx_http_request_t *r, int rc)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001128{
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001129 ngx_http_core_loc_conf_t *clcf;
1130
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001131 /* r can be already destroyed when rc == NGX_DONE */
Igor Sysoevd581fd52003-05-13 16:02:32 +00001132
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001133 if (rc == NGX_DONE || r->main) {
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001134 return;
1135 }
1136
Igor Sysoevae02c192004-03-19 05:25:53 +00001137 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1138 "http finalize request: %d", rc);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001139
Igor Sysoevd581fd52003-05-13 16:02:32 +00001140 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
1141
Igor Sysoev0a280a32003-10-12 16:49:16 +00001142 if (r->connection->read->timer_set) {
1143 ngx_del_timer(r->connection->read);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001144 }
1145
Igor Sysoev0a280a32003-10-12 16:49:16 +00001146 if (r->connection->write->timer_set) {
1147 ngx_del_timer(r->connection->write);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001148 }
1149
Igor Sysoev89690bf2004-03-23 06:01:52 +00001150 if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST || r->closed) {
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00001151
1152#if (NGX_STAT_STUB)
1153 (*ngx_stat_writing)--;
1154#endif
1155
Igor Sysoev89690bf2004-03-23 06:01:52 +00001156 ngx_http_close_request(r, 0);
1157 ngx_http_close_connection(r->connection);
1158 return;
1159 }
1160
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001161 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
Igor Sysoev239baac2003-06-11 15:28:34 +00001162
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001163 return;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001164
Igor Sysoev239baac2003-06-11 15:28:34 +00001165 } else if (rc == NGX_ERROR) {
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00001166
1167#if (NGX_STAT_STUB)
1168 (*ngx_stat_writing)--;
1169#endif
1170
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001171 ngx_http_close_request(r, 0);
1172 ngx_http_close_connection(r->connection);
1173 return;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001174
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001175 } else if (rc == NGX_AGAIN) {
1176 ngx_http_set_write_handler(r);
1177 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001178 }
1179
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00001180#if (NGX_STAT_STUB)
1181 (*ngx_stat_writing)--;
1182#endif
1183
Igor Sysoev0a280a32003-10-12 16:49:16 +00001184 if (r->connection->read->timer_set) {
1185 ngx_del_timer(r->connection->read);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001186 }
1187
Igor Sysoev0a280a32003-10-12 16:49:16 +00001188 if (r->connection->write->timer_set) {
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001189 r->connection->write->delayed = 0;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001190 ngx_del_timer(r->connection->write);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001191 }
1192
Igor Sysoev98c1cf12004-07-02 15:54:34 +00001193 if (r->connection->read->pending_eof) {
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001194#if (NGX_KQUEUE)
1195 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log,
1196 r->connection->read->kq_errno,
Igor Sysoev7af6b162004-02-09 07:46:43 +00001197 "kevent() reported about an closed connection");
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001198#endif
1199 ngx_http_close_request(r, 0);
1200 ngx_http_close_connection(r->connection);
1201 return;
1202 }
1203
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001204 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1205
Igor Sysoevc5991982004-01-16 06:15:48 +00001206 if (!ngx_terminate
Igor Sysoev3f4685f2004-04-25 20:13:21 +00001207 && !ngx_exiting
Igor Sysoevc5991982004-01-16 06:15:48 +00001208 && r->keepalive != 0
1209 && clcf->keepalive_timeout > 0)
1210 {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001211 ngx_http_set_keepalive(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001212 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001213
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001214 } else if (r->lingering_close && clcf->lingering_timeout > 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001215 ngx_http_set_lingering_close(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001216 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001217 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001218
Igor Sysoevc5991982004-01-16 06:15:48 +00001219 ngx_http_close_request(r, 0);
1220 ngx_http_close_connection(r->connection);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001221}
1222
1223
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001224static void ngx_http_set_write_handler(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001225{
Igor Sysoevd581fd52003-05-13 16:02:32 +00001226 ngx_event_t *wev;
Igor Sysoeva9830112003-05-19 16:39:14 +00001227 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001228
1229 wev = r->connection->write;
1230 wev->event_handler = ngx_http_writer;
1231
Igor Sysoevb1af9bb2004-06-25 14:42:03 +00001232 r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
1233
Igor Sysoevef066482004-06-21 15:59:32 +00001234 if (wev->ready && wev->delayed) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001235 return;
1236 }
1237
Igor Sysoev6253ca12003-05-27 12:18:54 +00001238 clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
1239 ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001240 if (!wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001241 ngx_add_timer(wev, clcf->send_timeout);
1242 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001243
Igor Sysoev222a2ad2003-11-18 16:49:00 +00001244 wev->available = clcf->send_lowat;
1245 if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001246 ngx_http_close_request(r, 0);
1247 ngx_http_close_connection(r->connection);
1248 }
1249
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001250 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001251}
1252
1253
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001254void ngx_http_writer(ngx_event_t *wev)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001255{
1256 int rc;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001257 ngx_connection_t *c;
1258 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001259 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001260
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001261 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http writer handler");
Igor Sysoev160d7742003-11-19 16:26:41 +00001262
Igor Sysoev6253ca12003-05-27 12:18:54 +00001263 c = wev->data;
1264 r = c->data;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001265
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001266 if (wev->timedout) {
Igor Sysoevef066482004-06-21 15:59:32 +00001267 if (!wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001268 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
1269 return;
1270 }
1271
1272 wev->timedout = 0;
Igor Sysoevef066482004-06-21 15:59:32 +00001273 wev->delayed = 0;
Igor Sysoev73a73b52004-06-20 19:54:15 +00001274
1275 if (!wev->ready) {
1276 clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
1277 ngx_http_core_module);
1278 ngx_add_timer(wev, clcf->send_timeout);
1279
1280 wev->available = clcf->send_lowat;
1281
1282 if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
1283 ngx_http_close_request(r, 0);
1284 ngx_http_close_connection(r->connection);
1285 }
1286
1287 return;
1288 }
1289
1290 } else {
Igor Sysoevef066482004-06-21 15:59:32 +00001291 if (wev->delayed) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001292 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1293 "http writer delayed");
Igor Sysoevef066482004-06-21 15:59:32 +00001294
1295 clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
1296 ngx_http_core_module);
1297 wev->available = clcf->send_lowat;
1298
1299 if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
1300 ngx_http_close_request(r, 0);
1301 ngx_http_close_connection(r->connection);
1302 }
1303
Igor Sysoev73a73b52004-06-20 19:54:15 +00001304 return;
1305 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001306 }
1307
Igor Sysoevd581fd52003-05-13 16:02:32 +00001308 rc = ngx_http_output_filter(r, NULL);
1309
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001310 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1311 "http writer output filter: %d", rc);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001312
1313 if (rc == NGX_AGAIN) {
Igor Sysoev73a73b52004-06-20 19:54:15 +00001314 clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
1315 ngx_http_core_module);
Igor Sysoevef066482004-06-21 15:59:32 +00001316 if (!wev->ready && !wev->delayed) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001317 ngx_add_timer(wev, clcf->send_timeout);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001318 }
1319
Igor Sysoev73a73b52004-06-20 19:54:15 +00001320 wev->available = clcf->send_lowat;
1321
1322 if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001323 ngx_http_close_request(r, 0);
1324 ngx_http_close_connection(r->connection);
1325 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001326
1327 return;
1328 }
1329
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001330 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http writer done");
Igor Sysoevd581fd52003-05-13 16:02:32 +00001331
Igor Sysoev0a280a32003-10-12 16:49:16 +00001332 ngx_http_finalize_request(r, rc);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001333}
1334
1335
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001336static void ngx_http_block_read(ngx_event_t *rev)
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001337{
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001338 ngx_connection_t *c;
1339 ngx_http_request_t *r;
1340
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001341 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http read blocked");
Igor Sysoev42feecb2002-12-15 06:25:09 +00001342
Igor Sysoev73009772003-02-06 17:21:13 +00001343 /* aio does not call this handler */
1344
Igor Sysoev0a280a32003-10-12 16:49:16 +00001345 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001346 if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001347 c = rev->data;
1348 r = c->data;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001349 ngx_http_close_request(r, 0);
1350 ngx_http_close_connection(c);
1351 }
Igor Sysoev73009772003-02-06 17:21:13 +00001352 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001353}
1354
1355
Igor Sysoev2f657222004-06-16 15:32:11 +00001356ngx_int_t ngx_http_discard_body(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001357{
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001358 ssize_t size;
1359 ngx_event_t *rev;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001360
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001361 rev = r->connection->read;
Igor Sysoev9b25d692003-01-26 21:08:14 +00001362
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001363 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body");
Igor Sysoev9b25d692003-01-26 21:08:14 +00001364
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001365 if (rev->timer_set) {
1366 ngx_del_timer(rev);
Igor Sysoev9b25d692003-01-26 21:08:14 +00001367 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001368
Igor Sysoev0a280a32003-10-12 16:49:16 +00001369 if (r->headers_in.content_length_n <= 0) {
1370 return NGX_OK;
1371 }
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001372
Igor Sysoev0a280a32003-10-12 16:49:16 +00001373 size = r->header_in->last - r->header_in->pos;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001374
Igor Sysoev0a280a32003-10-12 16:49:16 +00001375 if (size) {
1376 if (r->headers_in.content_length_n > size) {
1377 r->headers_in.content_length_n -= size;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001378
Igor Sysoev0a280a32003-10-12 16:49:16 +00001379 } else {
1380 r->header_in->pos += r->headers_in.content_length_n;
1381 r->headers_in.content_length_n = 0;
1382 return NGX_OK;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001383 }
Igor Sysoev73009772003-02-06 17:21:13 +00001384 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001385
Igor Sysoev0a280a32003-10-12 16:49:16 +00001386 rev->event_handler = ngx_http_read_discarded_body_event;
1387
1388 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1389 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1390 }
1391
1392 return ngx_http_read_discarded_body(r);
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001393}
1394
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001395
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001396static void ngx_http_read_discarded_body_event(ngx_event_t *rev)
Igor Sysoev42feecb2002-12-15 06:25:09 +00001397{
Igor Sysoev980a9242004-09-05 19:54:02 +00001398 ngx_int_t rc;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001399 ngx_connection_t *c;
1400 ngx_http_request_t *r;
1401
Igor Sysoev6253ca12003-05-27 12:18:54 +00001402 c = rev->data;
1403 r = c->data;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001404
1405 rc = ngx_http_read_discarded_body(r);
1406
Igor Sysoev0a280a32003-10-12 16:49:16 +00001407 if (rc == NGX_AGAIN) {
1408 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1409 ngx_http_close_request(r, rc);
1410 ngx_http_close_connection(c);
1411 return;
1412 }
1413 }
1414
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001415 if (rc != NGX_OK) {
1416 ngx_http_close_request(r, rc);
1417 ngx_http_close_connection(c);
1418 }
1419}
1420
1421
Igor Sysoev2f657222004-06-16 15:32:11 +00001422static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r)
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001423{
Igor Sysoev09159772003-06-12 05:54:39 +00001424 ssize_t size, n;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001425 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev42feecb2002-12-15 06:25:09 +00001426
Igor Sysoeve04084c2004-01-26 08:52:49 +00001427 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1428 "http read discarded body");
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001429
Igor Sysoev0a280a32003-10-12 16:49:16 +00001430 if (r->headers_in.content_length_n == 0) {
1431 return NGX_OK;
1432 }
1433
Igor Sysoev6253ca12003-05-27 12:18:54 +00001434 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001435
Igor Sysoevdc479b42003-03-20 16:09:44 +00001436 if (r->discarded_buffer == NULL) {
Igor Sysoev6253ca12003-05-27 12:18:54 +00001437 r->discarded_buffer = ngx_palloc(r->pool, clcf->discarded_buffer_size);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001438 if (r->discarded_buffer == NULL) {
1439 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1440 }
Igor Sysoevdc479b42003-03-20 16:09:44 +00001441 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001442
Igor Sysoeva09f08d2003-04-25 14:43:13 +00001443 size = r->headers_in.content_length_n;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001444
Igor Sysoev10a543a2004-03-16 07:10:12 +00001445 if (size > (ssize_t) clcf->discarded_buffer_size) {
1446 size = (ssize_t) clcf->discarded_buffer_size;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001447 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001448
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001449 n = r->connection->recv(r->connection, r->discarded_buffer, size);
1450
Igor Sysoevdc479b42003-03-20 16:09:44 +00001451 if (n == NGX_ERROR) {
Igor Sysoev89690bf2004-03-23 06:01:52 +00001452
1453 r->closed = 1;
1454
1455 /*
1456 * when a client request body is discarded then we already set
1457 * some HTTP response code for client and we can ignore the error
1458 */
1459
1460 return NGX_OK;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001461 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001462
Igor Sysoevdc479b42003-03-20 16:09:44 +00001463 if (n == NGX_AGAIN) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001464 return NGX_AGAIN;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001465 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001466
Igor Sysoeva09f08d2003-04-25 14:43:13 +00001467 r->headers_in.content_length_n -= n;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001468
Igor Sysoev42feecb2002-12-15 06:25:09 +00001469 return NGX_OK;
1470}
1471
1472
Igor Sysoevd581fd52003-05-13 16:02:32 +00001473static void ngx_http_set_keepalive(ngx_http_request_t *r)
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001474{
Igor Sysoev980a9242004-09-05 19:54:02 +00001475 size_t len;
Igor Sysoev369145c2004-05-28 15:49:23 +00001476 ngx_buf_t *b;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001477 ngx_event_t *rev, *wev;
1478 ngx_connection_t *c;
1479 ngx_http_log_ctx_t *ctx;
1480 ngx_http_core_srv_conf_t *cscf;
1481 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001482
Igor Sysoev6253ca12003-05-27 12:18:54 +00001483 c = r->connection;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001484 rev = c->read;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001485
Igor Sysoeve04084c2004-01-26 08:52:49 +00001486 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001487
Igor Sysoev6a644c62003-03-04 06:33:48 +00001488 ctx = (ngx_http_log_ctx_t *) c->log->data;
1489 ctx->action = "closing request";
Igor Sysoevdc479b42003-03-20 16:09:44 +00001490 ngx_http_close_request(r, 0);
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001491
Igor Sysoev6253ca12003-05-27 12:18:54 +00001492 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoevfa73aac2003-05-21 13:28:21 +00001493 ngx_add_timer(rev, clcf->keepalive_timeout);
1494
Igor Sysoev0a280a32003-10-12 16:49:16 +00001495 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1496 ngx_http_close_connection(c);
1497 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00001498 }
1499
Igor Sysoev369145c2004-05-28 15:49:23 +00001500 b = c->buffer;
Igor Sysoev7b6062a2004-02-12 20:57:10 +00001501 wev = c->write;
1502 wev->event_handler = ngx_http_empty_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001503
Igor Sysoev6881bfb2004-03-30 06:27:36 +00001504
Igor Sysoev369145c2004-05-28 15:49:23 +00001505 if (b->pos < b->last) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001506
Igor Sysoev74e95c22003-11-09 20:03:38 +00001507 /*
Igor Sysoev6881bfb2004-03-30 06:27:36 +00001508 * The pipelined request.
Igor Sysoev0a280a32003-10-12 16:49:16 +00001509 *
Igor Sysoeva2aca9a2004-01-18 21:09:21 +00001510 * We do not know here whether the pipelined request is complete
Igor Sysoev0a280a32003-10-12 16:49:16 +00001511 * so if the large client headers are not enabled
1512 * we need to copy the data to the start of c->buffer.
1513 * This copy should be rare because clients that support
1514 * pipelined requests (Mozilla 1.x, Opera 6.x+) are still rare.
1515 */
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001516
Igor Sysoev6253ca12003-05-27 12:18:54 +00001517 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoeva9830112003-05-19 16:39:14 +00001518
Igor Sysoev187fcd82003-05-23 11:53:01 +00001519 if (!cscf->large_client_header) {
Igor Sysoev369145c2004-05-28 15:49:23 +00001520 len = b->last - b->pos;
1521 ngx_memcpy(b->start, b->pos, len);
1522 b->pos = b->start;
1523 b->last = b->start + len;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001524 }
1525
Igor Sysoeve04084c2004-01-26 08:52:49 +00001526 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
Igor Sysoev6253ca12003-05-27 12:18:54 +00001527
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001528 c->pipeline = 1;
1529 ctx->action = "reading client pipelined request line";
Igor Sysoevd581fd52003-05-13 16:02:32 +00001530 ngx_http_init_request(rev);
1531 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001532 }
1533
1534 c->pipeline = 0;
1535
Igor Sysoev369145c2004-05-28 15:49:23 +00001536 b->pos = b->last = b->start;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001537 rev->event_handler = ngx_http_keepalive_handler;
1538
Igor Sysoevd9d0ca12003-11-21 06:30:49 +00001539 if (wev->active) {
1540 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
1541 if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_DISABLE_EVENT)
1542 == NGX_ERROR)
1543 {
1544 ngx_http_close_connection(c);
1545 return;
1546 }
1547
1548 } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
1549 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
1550 ngx_http_close_connection(c);
1551 return;
1552 }
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001553 }
1554 }
1555
Igor Sysoev6a644c62003-03-04 06:33:48 +00001556 ctx->action = "keepalive";
1557
Igor Sysoev67f450d2004-06-01 06:04:46 +00001558 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
Igor Sysoev9cf78302003-06-04 17:28:33 +00001559 if (ngx_tcp_push(c->fd) == NGX_ERROR) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00001560 ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
1561 ngx_http_close_connection(c);
1562 return;
Igor Sysoev9cf78302003-06-04 17:28:33 +00001563 }
Igor Sysoev67f450d2004-06-01 06:04:46 +00001564 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
Igor Sysoev9cf78302003-06-04 17:28:33 +00001565 }
1566
Igor Sysoevc83f6832004-06-24 07:53:37 +00001567 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
1568
Igor Sysoevb5faed22003-10-29 08:30:44 +00001569 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001570 ngx_http_keepalive_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00001571 }
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001572}
1573
1574
Igor Sysoevd581fd52003-05-13 16:02:32 +00001575static void ngx_http_keepalive_handler(ngx_event_t *rev)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001576{
Igor Sysoev0a280a32003-10-12 16:49:16 +00001577 ssize_t n;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001578 ngx_connection_t *c;
Igor Sysoev160d7742003-11-19 16:26:41 +00001579 ngx_http_log_ctx_t *ctx;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001580
Igor Sysoev0ad25372004-07-16 06:33:35 +00001581 c = rev->data;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001582
Igor Sysoeve04084c2004-01-26 08:52:49 +00001583 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
Igor Sysoev1af7c822002-09-13 14:47:42 +00001584
Igor Sysoevdc479b42003-03-20 16:09:44 +00001585 if (rev->timedout) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001586 ngx_http_close_connection(c);
1587 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00001588 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001589
Igor Sysoev0a280a32003-10-12 16:49:16 +00001590 /*
1591 * MSIE closes a keepalive connection with RST flag
1592 * so we ignore ECONNRESET here.
1593 */
Igor Sysoevb7387572003-03-11 20:38:13 +00001594
Igor Sysoevc7a2f682004-02-10 16:23:38 +00001595 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
Igor Sysoevb7387572003-03-11 20:38:13 +00001596 ngx_set_socket_errno(0);
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001597
1598 n = c->recv(c, c->buffer->last, c->buffer->end - c->buffer->last);
Igor Sysoevc7a2f682004-02-10 16:23:38 +00001599 c->log_error = NGX_ERROR_INFO;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001600
Igor Sysoevd581fd52003-05-13 16:02:32 +00001601 if (n == NGX_AGAIN) {
1602 return;
1603 }
1604
1605 if (n == NGX_ERROR) {
1606 ngx_http_close_connection(c);
1607 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00001608 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001609
Igor Sysoev160d7742003-11-19 16:26:41 +00001610 ctx = (ngx_http_log_ctx_t *) rev->log->data;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001611 rev->log->handler = NULL;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001612
1613 if (n == 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +00001614 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
Igor Sysoev160d7742003-11-19 16:26:41 +00001615 "client %s closed keepalive connection", ctx->client);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001616 ngx_http_close_connection(c);
1617 return;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001618 }
1619
Igor Sysoevb7387572003-03-11 20:38:13 +00001620 c->buffer->last += n;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001621 rev->log->handler = ngx_http_log_error;
Igor Sysoev160d7742003-11-19 16:26:41 +00001622 ctx->action = "reading client request line";
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001623
Igor Sysoevd581fd52003-05-13 16:02:32 +00001624 ngx_http_init_request(rev);
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001625}
1626
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001627
Igor Sysoevd581fd52003-05-13 16:02:32 +00001628static void ngx_http_set_lingering_close(ngx_http_request_t *r)
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001629{
Igor Sysoev0a280a32003-10-12 16:49:16 +00001630 ngx_event_t *rev, *wev;
Igor Sysoevb7387572003-03-11 20:38:13 +00001631 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001632 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001633
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001634 c = r->connection;
Igor Sysoev9b25d692003-01-26 21:08:14 +00001635
Igor Sysoev6253ca12003-05-27 12:18:54 +00001636 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001637
Igor Sysoev0a280a32003-10-12 16:49:16 +00001638 rev = c->read;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001639 rev->event_handler = ngx_http_lingering_close_handler;
Igor Sysoev42feecb2002-12-15 06:25:09 +00001640
Igor Sysoevc0247302004-06-27 18:01:57 +00001641 r->lingering_time = ngx_time() + clcf->lingering_time / 1000;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001642 ngx_add_timer(rev, clcf->lingering_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +00001643
Igor Sysoev0a280a32003-10-12 16:49:16 +00001644 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1645 ngx_http_close_request(r, 0);
1646 ngx_http_close_connection(c);
1647 return;
1648 }
1649
1650 wev = c->write;
1651 wev->event_handler = ngx_http_empty_handler;
1652
Igor Sysoevd9d0ca12003-11-21 06:30:49 +00001653 if (wev->active) {
1654 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
1655 if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_DISABLE_EVENT)
1656 == NGX_ERROR)
1657 {
1658 ngx_http_close_connection(c);
1659 return;
1660 }
1661
1662 } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
1663 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
1664 ngx_http_close_connection(c);
1665 return;
1666 }
Igor Sysoevb7387572003-03-11 20:38:13 +00001667 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001668 }
1669
Igor Sysoevb7387572003-03-11 20:38:13 +00001670 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
Igor Sysoev4cec79f2004-04-28 06:14:50 +00001671 ngx_connection_error(c, ngx_socket_errno,
1672 ngx_shutdown_socket_n " failed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00001673 ngx_http_close_request(r, 0);
1674 ngx_http_close_connection(c);
1675 return;
Igor Sysoev42feecb2002-12-15 06:25:09 +00001676 }
1677
Igor Sysoevb5faed22003-10-29 08:30:44 +00001678 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001679 ngx_http_lingering_close_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00001680 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001681}
1682
1683
Igor Sysoevd581fd52003-05-13 16:02:32 +00001684static void ngx_http_lingering_close_handler(ngx_event_t *rev)
Igor Sysoev42feecb2002-12-15 06:25:09 +00001685{
Igor Sysoevdc479b42003-03-20 16:09:44 +00001686 ssize_t n;
1687 ngx_msec_t timer;
1688 ngx_connection_t *c;
1689 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001690 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1af7c822002-09-13 14:47:42 +00001691
Igor Sysoev6253ca12003-05-27 12:18:54 +00001692 c = rev->data;
1693 r = c->data;
Igor Sysoev86de4cb2003-01-30 07:28:09 +00001694
Igor Sysoeve04084c2004-01-26 08:52:49 +00001695 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1696 "http lingering close handler");
Igor Sysoevdc479b42003-03-20 16:09:44 +00001697
1698 if (rev->timedout) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001699 ngx_http_close_request(r, 0);
1700 ngx_http_close_connection(c);
1701 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001702 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001703
Igor Sysoevc0247302004-06-27 18:01:57 +00001704 timer = r->lingering_time - ngx_time();
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001705 if (timer <= 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001706 ngx_http_close_request(r, 0);
1707 ngx_http_close_connection(c);
1708 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001709 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001710
Igor Sysoev6253ca12003-05-27 12:18:54 +00001711 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001712
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001713 if (r->discarded_buffer == NULL) {
Igor Sysoevb7387572003-03-11 20:38:13 +00001714
1715 /* TODO: r->header_in->start (if large headers are enabled)
1716 or the end of parsed header (otherwise)
1717 instead of r->header_in->last */
1718
Igor Sysoev09159772003-06-12 05:54:39 +00001719 if (r->header_in->end - r->header_in->last
Igor Sysoev10a543a2004-03-16 07:10:12 +00001720 >= (ssize_t) clcf->discarded_buffer_size)
1721 {
Igor Sysoevb7387572003-03-11 20:38:13 +00001722 r->discarded_buffer = r->header_in->last;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001723
1724 } else {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001725 r->discarded_buffer = ngx_palloc(c->pool,
Igor Sysoev6253ca12003-05-27 12:18:54 +00001726 clcf->discarded_buffer_size);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001727 if (r->discarded_buffer) {
1728 ngx_http_close_request(r, 0);
1729 ngx_http_close_connection(c);
1730 return;
1731 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001732 }
1733 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001734
Igor Sysoevdc479b42003-03-20 16:09:44 +00001735 do {
Igor Sysoev74a5ddb2004-07-18 19:11:20 +00001736 n = c->recv(c, r->discarded_buffer, clcf->discarded_buffer_size);
Igor Sysoev1af7c822002-09-13 14:47:42 +00001737
Igor Sysoeve04084c2004-01-26 08:52:49 +00001738 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
Igor Sysoev1af7c822002-09-13 14:47:42 +00001739
Igor Sysoevdc479b42003-03-20 16:09:44 +00001740 if (n == NGX_ERROR || n == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001741 ngx_http_close_request(r, 0);
1742 ngx_http_close_connection(c);
1743 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001744 }
1745
1746 } while (rev->ready);
Igor Sysoev1af7c822002-09-13 14:47:42 +00001747
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001748 timer *= 1000;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001749 if (timer > clcf->lingering_timeout) {
1750 timer = clcf->lingering_timeout;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001751 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001752
Igor Sysoevdc479b42003-03-20 16:09:44 +00001753 ngx_add_timer(rev, timer);
Igor Sysoev1af7c822002-09-13 14:47:42 +00001754
Igor Sysoevd581fd52003-05-13 16:02:32 +00001755 return;
Igor Sysoev1af7c822002-09-13 14:47:42 +00001756}
1757
Igor Sysoev2b542382002-08-20 14:48:28 +00001758
Igor Sysoev160d7742003-11-19 16:26:41 +00001759void ngx_http_empty_handler(ngx_event_t *wev)
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001760{
Igor Sysoeve04084c2004-01-26 08:52:49 +00001761 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001762
1763 return;
1764}
1765
1766
Igor Sysoev2f657222004-06-16 15:32:11 +00001767ngx_int_t ngx_http_send_last(ngx_http_request_t *r)
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001768{
Igor Sysoev369145c2004-05-28 15:49:23 +00001769 ngx_buf_t *b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001770 ngx_chain_t out;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001771
Igor Sysoev369145c2004-05-28 15:49:23 +00001772 if (!(b = ngx_calloc_buf(r->pool))) {
1773 return NGX_ERROR;
1774 }
1775
1776 b->last_buf = 1;
1777 out.buf = b;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001778 out.next = NULL;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001779
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001780 return ngx_http_output_filter(r, &out);
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001781}
1782
1783
Igor Sysoevd581fd52003-05-13 16:02:32 +00001784void ngx_http_close_request(ngx_http_request_t *r, int error)
1785{
Igor Sysoev0ab91b92004-06-06 19:49:18 +00001786 ngx_uint_t i;
1787 ngx_log_t *log;
1788 ngx_http_log_ctx_t *ctx;
1789 ngx_http_cleanup_t *cleanup;
1790 ngx_http_core_loc_conf_t *clcf;
1791 struct linger l;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001792
Igor Sysoev865c1502003-11-30 20:03:18 +00001793 log = r->connection->log;
1794
1795 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
Igor Sysoevd581fd52003-05-13 16:02:32 +00001796
1797 if (r->pool == NULL) {
Igor Sysoev865c1502003-11-30 20:03:18 +00001798 ngx_log_error(NGX_LOG_ALERT, log, 0,
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001799 "http request already closed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00001800 return;
1801 }
1802
Igor Sysoev669e3312003-12-22 09:40:48 +00001803 if (error && r->headers_out.status == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001804 r->headers_out.status = error;
1805 }
1806
1807 ngx_http_log_handler(r);
1808
Igor Sysoevc2bba092003-11-28 17:41:47 +00001809 cleanup = r->cleanup.elts;
1810 for (i = 0; i < r->cleanup.nelts; i++) {
Igor Sysoev865c1502003-11-30 20:03:18 +00001811 if (!cleanup[i].valid) {
Igor Sysoevc2bba092003-11-28 17:41:47 +00001812 continue;
1813 }
1814
Igor Sysoev67f88e92004-03-12 16:57:08 +00001815#if (NGX_HTTP_CACHE)
1816
Igor Sysoev865c1502003-11-30 20:03:18 +00001817 if (cleanup[i].cache) {
1818 ngx_http_cache_unlock(cleanup[i].data.cache.hash,
1819 cleanup[i].data.cache.cache, log);
1820 continue;
1821 }
1822
Igor Sysoev67f88e92004-03-12 16:57:08 +00001823#endif
1824
Igor Sysoev865c1502003-11-30 20:03:18 +00001825 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http cleanup fd: %d",
1826 cleanup[i].data.file.fd);
1827
Igor Sysoevc2bba092003-11-28 17:41:47 +00001828 if (ngx_close_file(cleanup[i].data.file.fd) == NGX_FILE_ERROR) {
Igor Sysoev865c1502003-11-30 20:03:18 +00001829 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
Igor Sysoevc2bba092003-11-28 17:41:47 +00001830 ngx_close_file_n " \"%s\" failed",
1831 cleanup[i].data.file.name);
1832 }
1833 }
1834
Igor Sysoev865c1502003-11-30 20:03:18 +00001835 /* STUB */
Igor Sysoevd581fd52003-05-13 16:02:32 +00001836 if (r->file.fd != NGX_INVALID_FILE) {
1837 if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
Igor Sysoev865c1502003-11-30 20:03:18 +00001838 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
Igor Sysoevd581fd52003-05-13 16:02:32 +00001839 ngx_close_file_n " \"%s\" failed", r->file.name.data);
1840 }
1841 }
1842
Igor Sysoev3f4685f2004-04-25 20:13:21 +00001843 if (r->request_body
1844 && r->request_body->temp_file
1845 && r->request_body->temp_file->file.fd != NGX_INVALID_FILE)
1846 {
1847 if (ngx_close_file(r->request_body->temp_file->file.fd)
1848 == NGX_FILE_ERROR)
1849 {
1850 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
1851 ngx_close_file_n " deleted file \"%s\" failed",
1852 r->request_body->temp_file->file.name.data);
1853 }
1854 }
1855
Igor Sysoev0ab91b92004-06-06 19:49:18 +00001856 if (r->connection->timedout) {
1857 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1858
1859 if (clcf->reset_timedout_connection) {
1860 l.l_onoff = 1;
1861 l.l_linger = 0;
1862
1863 if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
1864 (const void *) &l, sizeof(struct linger)) == -1)
1865 {
1866 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
1867 "setsockopt(SO_LINGER) failed");
1868 }
1869 }
1870 }
1871
Igor Sysoevd581fd52003-05-13 16:02:32 +00001872 /* ctx->url was allocated from r->pool */
Igor Sysoev865c1502003-11-30 20:03:18 +00001873 ctx = log->data;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001874 ctx->url = NULL;
1875
Igor Sysoevc83f6832004-06-24 07:53:37 +00001876 r->request_line.len = 0;
1877
Igor Sysoevd581fd52003-05-13 16:02:32 +00001878 ngx_destroy_pool(r->pool);
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001879
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001880 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001881}
1882
1883
Igor Sysoev0ad25372004-07-16 06:33:35 +00001884#if (NGX_HTTP_SSL)
1885
1886void ngx_ssl_close_handler(ngx_event_t *ev)
1887{
1888 ngx_connection_t *c;
1889
1890 c = ev->data;
1891
1892 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, "http ssl close handler");
1893
1894 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
1895 return;
1896 }
1897
1898 ngx_http_close_connection(c);
1899}
1900
1901#endif
1902
1903
Igor Sysoevd581fd52003-05-13 16:02:32 +00001904void ngx_http_close_connection(ngx_connection_t *c)
Igor Sysoev6b863e32003-05-12 15:52:24 +00001905{
Igor Sysoeve04084c2004-01-26 08:52:49 +00001906 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev54498db2004-02-11 17:08:49 +00001907 "close http connection: %d", c->fd);
Igor Sysoev6b863e32003-05-12 15:52:24 +00001908
Igor Sysoevdc3b2a72004-09-14 19:39:54 +00001909#if (NGX_STAT_STUB)
1910 (*ngx_stat_active)--;
1911#endif
1912
Igor Sysoev59cf56c2004-09-07 15:29:22 +00001913 ngx_close_connection(c);
Igor Sysoev2ba1ee02002-10-04 17:58:04 +00001914}
1915
1916
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001917static void ngx_http_client_error(ngx_http_request_t *r,
1918 int client_error, int error)
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001919{
Igor Sysoev3043bfc2004-05-14 16:51:47 +00001920 ngx_http_log_ctx_t *ctx;
1921 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001922
1923 ctx = r->connection->log->data;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001924
1925 if (error == NGX_HTTP_REQUEST_TIME_OUT) {
1926 ngx_log_error(NGX_LOG_INFO, r->connection->log, NGX_ETIMEDOUT,
1927 "client timed out");
Igor Sysoev0ab91b92004-06-06 19:49:18 +00001928 r->connection->timedout = 1;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001929 ngx_http_close_request(r, error);
1930 ngx_http_close_connection(r->connection);
1931 return;
1932 }
1933
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001934 r->connection->log->handler = NULL;
1935
1936 if (ctx->url) {
Igor Sysoevf38e0462004-07-16 17:11:43 +00001937 switch (client_error) {
1938
1939 case NGX_HTTP_PARSE_INVALID_HOST:
Igor Sysoev3043bfc2004-05-14 16:51:47 +00001940 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1941 client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR],
1942 ctx->client, r->headers_in.host->value.data, ctx->url);
1943
1944 error = NGX_HTTP_INVALID_HOST;
1945
1946 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1947
1948 if (cscf->restrict_host_names == NGX_HTTP_RESTRICT_HOST_CLOSE) {
1949 ngx_http_close_request(r, error);
1950 ngx_http_close_connection(r->connection);
1951 return;
1952 }
1953
Igor Sysoevf38e0462004-07-16 17:11:43 +00001954 break;
1955
1956 case NGX_HTTP_PARSE_HTTP_TO_HTTPS:
1957 error = NGX_HTTP_TO_HTTPS;
1958
1959 /* fall through */
1960
1961 default:
Igor Sysoev3043bfc2004-05-14 16:51:47 +00001962 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Igor Sysoev3b30a902003-12-25 20:26:58 +00001963 client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR],
1964 ctx->client, ctx->url);
Igor Sysoev3043bfc2004-05-14 16:51:47 +00001965 }
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001966
1967 } else {
Igor Sysoev3d58f8c2004-01-08 08:47:17 +00001968 if (error == NGX_HTTP_REQUEST_URI_TOO_LARGE) {
1969 r->request_line.len = r->header_in->end - r->request_start;
1970 r->request_line.data = r->request_start;
1971 }
1972
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001973 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Igor Sysoev3b30a902003-12-25 20:26:58 +00001974 client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR],
1975 ctx->client);
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001976 }
1977
1978 r->connection->log->handler = ngx_http_log_error;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001979
1980 ngx_http_finalize_request(r, error);
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001981}
1982
1983
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001984static size_t ngx_http_log_error(void *data, char *buf, size_t len)
1985{
Igor Sysoev160d7742003-11-19 16:26:41 +00001986 ngx_http_log_ctx_t *ctx = data;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +00001987
Igor Sysoev7578ec92003-06-02 15:24:30 +00001988 if (ctx->action && ctx->url) {
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001989 return ngx_snprintf(buf, len, " while %s, client: %s, URL: %s",
1990 ctx->action, ctx->client, ctx->url);
Igor Sysoev7578ec92003-06-02 15:24:30 +00001991
1992 } else if (ctx->action == NULL && ctx->url) {
1993 return ngx_snprintf(buf, len, ", client: %s, URL: %s",
1994 ctx->client, ctx->url);
1995
Igor Sysoevdc479b42003-03-20 16:09:44 +00001996 } else {
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001997 return ngx_snprintf(buf, len, " while %s, client: %s",
1998 ctx->action, ctx->client);
Igor Sysoevdc479b42003-03-20 16:09:44 +00001999 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00002000}