blob: 1697eefaece2b2d4cf8e8eb933c384fa5803c187 [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);
9static void ngx_http_process_request_line(ngx_event_t *rev);
10static void ngx_http_process_request_headers(ngx_event_t *rev);
Igor Sysoev6b863e32003-05-12 15:52:24 +000011static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
Igor Sysoev419f9ac2003-10-21 16:49:56 +000012static int ngx_http_process_request_header(ngx_http_request_t *r);
Igor Sysoev6b863e32003-05-12 15:52:24 +000013
Igor Sysoevb3e73d82003-10-10 15:10:50 +000014static void ngx_http_set_write_handler(ngx_http_request_t *r);
Igor Sysoev6b863e32003-05-12 15:52:24 +000015
Igor Sysoev6ddfbf02003-05-15 15:42:53 +000016static void ngx_http_block_read(ngx_event_t *ev);
17static void ngx_http_read_discarded_body_event(ngx_event_t *rev);
18static int ngx_http_read_discarded_body(ngx_http_request_t *r);
Igor Sysoev3a40d482002-09-12 14:42:29 +000019
Igor Sysoevd581fd52003-05-13 16:02:32 +000020static void ngx_http_set_keepalive(ngx_http_request_t *r);
21static void ngx_http_keepalive_handler(ngx_event_t *ev);
22static void ngx_http_set_lingering_close(ngx_http_request_t *r);
23static void ngx_http_lingering_close_handler(ngx_event_t *ev);
24
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000025static void ngx_http_client_error(ngx_http_request_t *r,
26 int client_error, int error);
Igor Sysoev0ad17c02002-08-26 15:18:19 +000027static size_t ngx_http_log_error(void *data, char *buf, size_t len);
28
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000029
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000030/* NGX_HTTP_PARSE_... errors */
Igor Sysoev0ad17c02002-08-26 15:18:19 +000031
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000032static char *client_header_errors[] = {
Igor Sysoev016b8522002-08-29 16:59:54 +000033 "client %s sent invalid method",
34 "client %s sent invalid request",
Igor Sysoev1af7c822002-09-13 14:47:42 +000035 "client %s sent too long URI",
Igor Sysoev6ddfbf02003-05-15 15:42:53 +000036 "client %s sent invalid method in HTTP/0.9 request",
Igor Sysoev6a644c62003-03-04 06:33:48 +000037
38 "client %s sent invalid header, URL: %s",
39 "client %s sent too long header line, URL: %s",
Igor Sysoeva09f08d2003-04-25 14:43:13 +000040 "client %s sent HTTP/1.1 request without \"Host\" header, URL: %s",
Igor Sysoev6707ba92004-03-30 15:59:50 +000041 "client %s sent invalid \"Content-Length\" header, URL: %s",
Igor Sysoev6881bfb2004-03-30 06:27:36 +000042 "client %s sent POST method without \"Content-Length\" header, URL: %s"
Igor Sysoev016b8522002-08-29 16:59:54 +000043};
44
45
Igor Sysoevdc867cd2003-12-14 20:10:27 +000046#if 0
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000047static void ngx_http_dummy(ngx_event_t *wev)
48{
49 return;
50}
Igor Sysoevdc867cd2003-12-14 20:10:27 +000051#endif
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000052
53
Igor Sysoev6b863e32003-05-12 15:52:24 +000054void ngx_http_init_connection(ngx_connection_t *c)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000055{
Igor Sysoev6253ca12003-05-27 12:18:54 +000056 ngx_event_t *rev;
Igor Sysoev160d7742003-11-19 16:26:41 +000057 ngx_http_log_ctx_t *ctx;
Igor Sysoev6b863e32003-05-12 15:52:24 +000058
Igor Sysoev239baac2003-06-11 15:28:34 +000059 c->addr_text.data = ngx_palloc(c->pool, c->listening->addr_text_max_len);
Igor Sysoev6b863e32003-05-12 15:52:24 +000060 if (c->addr_text.data == NULL) {
61 ngx_http_close_connection(c);
62 return;
63 }
64
Igor Sysoev239baac2003-06-11 15:28:34 +000065 c->addr_text.len = ngx_sock_ntop(c->listening->family, c->sockaddr,
66 c->addr_text.data,
67 c->listening->addr_text_max_len);
Igor Sysoev9c610952004-03-16 13:35:20 +000068
Igor Sysoev6b863e32003-05-12 15:52:24 +000069 if (c->addr_text.len == 0) {
70 ngx_http_close_connection(c);
71 return;
72 }
73
Igor Sysoev160d7742003-11-19 16:26:41 +000074 if (!(ctx = ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t)))) {
Igor Sysoev6b863e32003-05-12 15:52:24 +000075 ngx_http_close_connection(c);
76 return;
77 }
78
Igor Sysoev160d7742003-11-19 16:26:41 +000079 ctx->connection = c->number;
80 ctx->client = c->addr_text.data;
81 ctx->action = "reading client request line";
82 c->log->data = ctx;
Igor Sysoev6b863e32003-05-12 15:52:24 +000083 c->log->handler = ngx_http_log_error;
Igor Sysoevc7a2f682004-02-10 16:23:38 +000084 c->log_error = NGX_ERROR_INFO;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000085
Igor Sysoevdc479b42003-03-20 16:09:44 +000086 rev = c->read;
87 rev->event_handler = ngx_http_init_request;
Igor Sysoev2ba1ee02002-10-04 17:58:04 +000088
Igor Sysoev7b6062a2004-02-12 20:57:10 +000089 /* STUB: epoll edge */ c->write->event_handler = ngx_http_empty_handler;
Igor Sysoev7af6b162004-02-09 07:46:43 +000090
Igor Sysoevdc479b42003-03-20 16:09:44 +000091 if (rev->ready) {
Igor Sysoev7b6062a2004-02-12 20:57:10 +000092 /* deferred accept, aio, iocp */
Igor Sysoev709405b2004-03-31 15:26:46 +000093
94 if (*ngx_accept_mutex) {
95 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
96 ngx_http_close_connection(c);
97 return;
98 }
99
Igor Sysoev3d540612004-04-13 15:08:48 +0000100 ngx_post_event(rev);
Igor Sysoev709405b2004-03-31 15:26:46 +0000101
102 ngx_mutex_unlock(ngx_posted_events_mutex);
103 return;
104 }
105
Igor Sysoev6b863e32003-05-12 15:52:24 +0000106 ngx_http_init_request(rev);
107 return;
Igor Sysoev016b8522002-08-29 16:59:54 +0000108 }
Igor Sysoev73009772003-02-06 17:21:13 +0000109
Igor Sysoev239baac2003-06-11 15:28:34 +0000110 ngx_add_timer(rev, c->listening->post_accept_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000111
Igor Sysoevb5faed22003-10-29 08:30:44 +0000112 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000113 ngx_http_close_connection(c);
114 return;
115 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000116
117#if 0
Igor Sysoevfe0f5cc2003-10-31 16:05:33 +0000118 /* TODO: learn SO_SNDBUF (to use in zerocopy) via kqueue's EV_CLEAR event */
119
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000120 c->write->ready = 0;
121 c->write->event_handler = ngx_http_dummy;
122
123 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
124 ngx_http_close_connection(c);
125 return;
126 }
127#endif
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000128}
129
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000130
Igor Sysoev6b863e32003-05-12 15:52:24 +0000131static void ngx_http_init_request(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000132{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000133 ngx_uint_t i;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000134 socklen_t len;
135 struct sockaddr_in addr_in;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000136 ngx_connection_t *c;
137 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000138 ngx_http_in_port_t *in_port;
139 ngx_http_in_addr_t *in_addr;
140 ngx_http_server_name_t *server_name;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000141 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev890fc962003-07-20 21:15:59 +0000142 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000143
Igor Sysoeva9830112003-05-19 16:39:14 +0000144 c = rev->data;
Igor Sysoeva9830112003-05-19 16:39:14 +0000145
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000146 if (rev->timedout) {
147 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
148 ngx_http_close_connection(c);
149 return;
150 }
151
Igor Sysoev0a280a32003-10-12 16:49:16 +0000152 if (c->data) {
153 r = c->data;
154 ngx_memzero(r, sizeof(ngx_http_request_t));
155
156 } else {
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000157 if (!(r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)))) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000158 ngx_http_close_connection(c);
159 return;
160 }
Igor Sysoev6253ca12003-05-27 12:18:54 +0000161 }
162
Igor Sysoev3b30a902003-12-25 20:26:58 +0000163 r->http_state = NGX_HTTP_INITING_REQUEST_STATE;
164
Igor Sysoev6253ca12003-05-27 12:18:54 +0000165 /* find the server configuration for the address:port */
166
167 /* AF_INET only */
168
169 in_port = c->servers;
170 in_addr = in_port->addrs.elts;
171
172 r->port = in_port->port;
173 r->port_name = &in_port->port_name;
174
175 i = 0;
176
177 if (in_port->addrs.nelts > 1) {
178
Igor Sysoev239baac2003-06-11 15:28:34 +0000179 /*
Igor Sysoev7af6b162004-02-09 07:46:43 +0000180 * There are the several addresses on this port and one of them
Igor Sysoev239baac2003-06-11 15:28:34 +0000181 * is "*:port" so getsockname() is needed to determine
182 * the server address.
183 * AcceptEx() already gave this address.
184 */
Igor Sysoev6253ca12003-05-27 12:18:54 +0000185
Igor Sysoev239baac2003-06-11 15:28:34 +0000186#if (WIN32)
187 if (c->local_sockaddr) {
188 r->in_addr =
189 ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
Igor Sysoev6253ca12003-05-27 12:18:54 +0000190
Igor Sysoev239baac2003-06-11 15:28:34 +0000191 } else {
192#endif
193 len = sizeof(struct sockaddr_in);
194 if (getsockname(c->fd, (struct sockaddr *) &addr_in, &len) == -1) {
195 ngx_log_error(NGX_LOG_CRIT, rev->log, ngx_socket_errno,
196 "getsockname() failed");
197 ngx_http_close_connection(c);
198 return;
199 }
Igor Sysoev10a543a2004-03-16 07:10:12 +0000200
201 r->in_addr = addr_in.sin_addr.s_addr;
202
Igor Sysoev239baac2003-06-11 15:28:34 +0000203#if (WIN32)
Igor Sysoev6253ca12003-05-27 12:18:54 +0000204 }
Igor Sysoev239baac2003-06-11 15:28:34 +0000205#endif
Igor Sysoev6253ca12003-05-27 12:18:54 +0000206
Igor Sysoev6253ca12003-05-27 12:18:54 +0000207 /* the last in_port->addrs address is "*" */
208
209 for ( /* void */ ; i < in_port->addrs.nelts - 1; i++) {
210 if (in_addr[i].addr == r->in_addr) {
211 break;
212 }
213 }
214
215 } else {
216 r->in_addr = in_addr[0].addr;
217 }
218
219 r->virtual_names = &in_addr[i].names;
220
221 /* the default server configuration for the address:port */
222 cscf = in_addr[i].core_srv_conf;
223
224 r->main_conf = cscf->ctx->main_conf;
225 r->srv_conf = cscf->ctx->srv_conf;
226 r->loc_conf = cscf->ctx->loc_conf;
227
228 server_name = cscf->server_names.elts;
229 r->server_name = &server_name->name;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000230
Igor Sysoev890fc962003-07-20 21:15:59 +0000231 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
232 c->log->file = clcf->err_log->file;
Igor Sysoevfff32322004-04-08 15:58:25 +0000233 if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
234 c->log->log_level = clcf->err_log->log_level;
235 }
Igor Sysoev890fc962003-07-20 21:15:59 +0000236
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000237 if (c->buffer == NULL) {
Igor Sysoev7af6b162004-02-09 07:46:43 +0000238 c->buffer = ngx_create_temp_hunk(c->pool,
239 cscf->client_header_buffer_size);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000240 if (c->buffer == NULL) {
241 ngx_http_close_connection(c);
242 return;
243 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000244 }
245
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000246 if (!(r->pool = ngx_create_pool(cscf->request_pool_size, c->log))) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000247 ngx_http_close_connection(c);
248 return;
249 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000250
Igor Sysoevc2bba092003-11-28 17:41:47 +0000251 r->cleanup.elts = ngx_palloc(r->pool, 5 * sizeof(ngx_http_cleanup_t));
252 if (r->cleanup.elts == NULL) {
253 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
254 ngx_http_close_connection(c);
255 return;
256 }
257 /*
258 * set by ngx_pcalloc():
259 *
260 * r->cleanup.nelts = 0;
261 */
262 r->cleanup.nalloc = 5;
263 r->cleanup.size = sizeof(ngx_http_cleanup_t);
264 r->cleanup.pool = r->pool;
265
Igor Sysoev89690bf2004-03-23 06:01:52 +0000266
267 /* init the r->headers_out.headers table */
268
269 r->headers_out.headers.elts = ngx_pcalloc(r->pool,
270 20 * sizeof(ngx_table_elt_t));
271 if (r->headers_out.headers.elts == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000272 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
273 ngx_http_close_connection(c);
274 return;
275 }
Igor Sysoev89690bf2004-03-23 06:01:52 +0000276 /* r->headers_out.headers.nelts = 0; */
277 r->headers_out.headers.nalloc = 20;
278 r->headers_out.headers.size = sizeof(ngx_table_elt_t);
279 r->headers_out.headers.pool = r->pool;
280
Igor Sysoev6b863e32003-05-12 15:52:24 +0000281
282 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
283 if (r->ctx == NULL) {
284 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
285 ngx_http_close_connection(c);
286 return;
287 }
Igor Sysoeve0268b92002-09-11 15:18:33 +0000288
Igor Sysoev6b863e32003-05-12 15:52:24 +0000289 c->sent = 0;
290 c->data = r;
291 r->connection = c;
292 r->pipeline = c->pipeline;
293 r->header_in = c->buffer;
294
295 r->file.fd = NGX_INVALID_FILE;
296
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000297 r->headers_in.content_length_n = -1;
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000298 r->headers_in.keep_alive_n = -1;
299 r->headers_out.content_length_n = -1;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000300 r->headers_out.last_modified_time = -1;
301
Igor Sysoev6b863e32003-05-12 15:52:24 +0000302 rev->event_handler = ngx_http_process_request_line;
303 ngx_http_process_request_line(rev);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000304}
305
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000306
Igor Sysoev6b863e32003-05-12 15:52:24 +0000307static void ngx_http_process_request_line(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000308{
Igor Sysoev10a543a2004-03-16 07:10:12 +0000309 u_char *p;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000310 ssize_t n;
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000311 ngx_int_t rc, offset;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000312 ngx_connection_t *c;
313 ngx_http_request_t *r;
Igor Sysoev160d7742003-11-19 16:26:41 +0000314 ngx_http_log_ctx_t *ctx;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000315 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000316
Igor Sysoeva9830112003-05-19 16:39:14 +0000317 c = rev->data;
318 r = c->data;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000319
Igor Sysoev2b58fbf2003-12-09 15:08:11 +0000320 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
321 "http process request line");
Igor Sysoevdc479b42003-03-20 16:09:44 +0000322
323 if (rev->timedout) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000324 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000325 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000326 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000327
Igor Sysoev6b863e32003-05-12 15:52:24 +0000328 n = ngx_http_read_request_header(r);
Igor Sysoev016b8522002-08-29 16:59:54 +0000329
Igor Sysoev6b863e32003-05-12 15:52:24 +0000330 if (n == NGX_AGAIN || n == NGX_ERROR) {
331 return;
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000332 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000333
Igor Sysoeve6779222003-10-03 15:50:53 +0000334 rc = ngx_http_parse_request_line(r);
Igor Sysoevdc479b42003-03-20 16:09:44 +0000335
Igor Sysoev016b8522002-08-29 16:59:54 +0000336 if (rc == NGX_OK) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000337
Igor Sysoev6b863e32003-05-12 15:52:24 +0000338 /* the request line has been parsed successfully */
339
Igor Sysoeva3677242004-04-14 05:57:36 +0000340#if 0
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000341 /* TODO: we need to handle proxy URIs */
Igor Sysoevc2bba092003-11-28 17:41:47 +0000342 if (r->unusual_uri) {
Igor Sysoev1c104622003-06-03 15:42:58 +0000343 r->request_line.len = r->request_end - r->request_start;
344 r->request_line.data = r->request_start;
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000345#if 0
Igor Sysoev1c104622003-06-03 15:42:58 +0000346 r->request_line.data[r->request_line.len] = '\0';
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000347#endif
Igor Sysoev1c104622003-06-03 15:42:58 +0000348
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000349 ngx_http_client_error(r, NGX_HTTP_PARSE_INVALID_REQUEST,
350 NGX_HTTP_BAD_REQUEST);
Igor Sysoev7578ec92003-06-02 15:24:30 +0000351 return;
352 }
Igor Sysoeva3677242004-04-14 05:57:36 +0000353#endif
Igor Sysoev7578ec92003-06-02 15:24:30 +0000354
Igor Sysoev6253ca12003-05-27 12:18:54 +0000355 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoeva9830112003-05-19 16:39:14 +0000356
Igor Sysoeve2a31542003-04-08 15:40:10 +0000357 if (r->http_version >= NGX_HTTP_VERSION_10
Igor Sysoev187fcd82003-05-23 11:53:01 +0000358 && cscf->large_client_header == 0
Igor Sysoeve2a31542003-04-08 15:40:10 +0000359 && r->header_in->pos == r->header_in->end)
360 {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000361 /* no space for "\r\n" at the end of the header */
362
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000363 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
364 NGX_HTTP_REQUEST_URI_TOO_LARGE);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000365 return;
Igor Sysoeve2a31542003-04-08 15:40:10 +0000366 }
367
Igor Sysoev6414b962003-10-24 16:10:38 +0000368
Igor Sysoevc2bba092003-11-28 17:41:47 +0000369 /* copy unparsed URI */
370
371 r->unparsed_uri.len = r->uri_end - r->uri_start;
372 r->unparsed_uri.data = ngx_palloc(r->pool, r->unparsed_uri.len + 1);
373 if (r->unparsed_uri.data == NULL) {
374 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
375 ngx_http_close_connection(c);
376 return;
377 }
378
379 ngx_cpystrn(r->unparsed_uri.data, r->uri_start,
380 r->unparsed_uri.len + 1);
381
382
Igor Sysoev6a644c62003-03-04 06:33:48 +0000383 /* copy URI */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000384
385 if (r->args_start) {
386 r->uri.len = r->args_start - 1 - r->uri_start;
387 } else {
388 r->uri.len = r->uri_end - r->uri_start;
389 }
390
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000391 if (!(r->uri.data = ngx_palloc(r->pool, r->uri.len + 1))) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000392 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
393 ngx_http_close_connection(c);
394 return;
395 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000396
Igor Sysoevc2bba092003-11-28 17:41:47 +0000397 if (r->complex_uri) {
398 rc = ngx_http_parse_complex_uri(r);
Igor Sysoev016b8522002-08-29 16:59:54 +0000399
Igor Sysoev865c1502003-11-30 20:03:18 +0000400 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
401 ngx_http_close_request(r, rc);
402 ngx_http_close_connection(c);
403 return;
404 }
405
406 if (rc != NGX_OK) {
407 r->request_line.len = r->request_end - r->request_start;
408 r->request_line.data = r->request_start;
Igor Sysoev865c1502003-11-30 20:03:18 +0000409
410 ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST);
411 return;
412 }
413
Igor Sysoevc2bba092003-11-28 17:41:47 +0000414 } else {
415 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1);
Igor Sysoeva9830112003-05-19 16:39:14 +0000416 }
417
Igor Sysoeva9830112003-05-19 16:39:14 +0000418
Igor Sysoevdc479b42003-03-20 16:09:44 +0000419 r->request_line.len = r->request_end - r->request_start;
420
Igor Sysoev187fcd82003-05-23 11:53:01 +0000421 if (cscf->large_client_header) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000422
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000423 /*
424 * if the large client headers are enabled then
Igor Sysoeva2aca9a2004-01-18 21:09:21 +0000425 * we need to copy the request line
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000426 */
427
Igor Sysoev6b863e32003-05-12 15:52:24 +0000428 r->request_line.data = ngx_palloc(r->pool, r->request_line.len + 1);
429 if (r->request_line.data == NULL) {
430 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
431 ngx_http_close_connection(c);
432 return;
433 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000434
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000435 ngx_cpystrn(r->request_line.data, r->request_start,
Igor Sysoev6a644c62003-03-04 06:33:48 +0000436 r->request_line.len + 1);
437
438 } else {
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000439 r->request_line.data = r->request_start;
Igor Sysoev6a644c62003-03-04 06:33:48 +0000440 r->request_line.data[r->request_line.len] = '\0';
441 }
442
Igor Sysoeva3677242004-04-14 05:57:36 +0000443 if (r->method == 0) {
444 r->method_name.len = r->method_end - r->request_start + 1;
445 r->method_name.data = r->request_line.data;
446 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000447
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000448 if (r->uri_ext) {
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000449
450 /* copy URI extention */
451
Igor Sysoevdc479b42003-03-20 16:09:44 +0000452 if (r->args_start) {
453 r->exten.len = r->args_start - 1 - r->uri_ext;
454 } else {
455 r->exten.len = r->uri_end - r->uri_ext;
456 }
457
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000458 if (!(r->exten.data = ngx_palloc(r->pool, r->exten.len + 1))) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000459 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
460 ngx_http_close_connection(c);
461 return;
462 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000463
Igor Sysoevb0869052002-12-10 18:05:12 +0000464 ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000465 }
466
Igor Sysoevdc479b42003-03-20 16:09:44 +0000467 if (r->args_start && r->uri_end > r->args_start) {
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000468
469 /* copy URI arguments */
470
Igor Sysoevdc479b42003-03-20 16:09:44 +0000471 r->args.len = r->uri_end - r->args_start;
472
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000473 if (!(r->args.data = ngx_palloc(r->pool, r->args.len + 1))) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000474 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
475 ngx_http_close_connection(c);
476 return;
477 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000478
479 ngx_cpystrn(r->args.data, r->args_start, r->args.len + 1);
480 }
481
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000482 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
483 "http request line: \"%s\"", r->request_line.data);
484
485 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
486 "http uri: \"%s\"", r->uri.data);
487
488 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev10a543a2004-03-16 07:10:12 +0000489 "http args: \"%s\"",
490 r->args.data ? r->args.data : (u_char *) "");
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000491
492 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
493 "http exten: \"%s\"",
Igor Sysoev10a543a2004-03-16 07:10:12 +0000494 r->exten.data ? r->exten.data : (u_char *) "");
Igor Sysoev016b8522002-08-29 16:59:54 +0000495
Igor Sysoev7578ec92003-06-02 15:24:30 +0000496 if (r->http_version < NGX_HTTP_VERSION_10) {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000497 rev->event_handler = ngx_http_block_read;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000498 ngx_http_handler(r);
499 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000500 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000501
Igor Sysoev89690bf2004-03-23 06:01:52 +0000502
503 /* init the r->headers_in.headers table */
504
505 r->headers_in.headers.elts = ngx_pcalloc(r->pool,
506 20 * sizeof(ngx_table_elt_t));
507 if (r->headers_in.headers.elts == NULL) {
508 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
509 ngx_http_close_connection(c);
510 return;
511 }
512
513 /* r->headers_in.headers.elts = NULL; */
514 /* r->headers_in.headers.nelts = 0; */
515 r->headers_in.headers.size = sizeof(ngx_table_elt_t);
516 r->headers_in.headers.nalloc = 20;
517 r->headers_in.headers.pool = r->pool;
518
Igor Sysoev160d7742003-11-19 16:26:41 +0000519 ctx = c->log->data;
520 ctx->action = "reading client request headers";
521 ctx->url = r->unparsed_uri.data;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000522
Igor Sysoev187fcd82003-05-23 11:53:01 +0000523 if (cscf->large_client_header
Igor Sysoevdc479b42003-03-20 16:09:44 +0000524 && r->header_in->pos == r->header_in->last)
525 {
526 r->header_in->pos = r->header_in->last = r->header_in->start;
527 }
Igor Sysoev016b8522002-08-29 16:59:54 +0000528
Igor Sysoevd581fd52003-05-13 16:02:32 +0000529 rev->event_handler = ngx_http_process_request_headers;
530 ngx_http_process_request_headers(rev);
531
532 return;
533
Igor Sysoev0dad6292003-03-05 17:30:51 +0000534 } else if (rc != NGX_AGAIN) {
Igor Sysoev6b863e32003-05-12 15:52:24 +0000535
536 /* there was error while a request line parsing */
537
Igor Sysoev3d58f8c2004-01-08 08:47:17 +0000538 for (p = r->request_start; p < r->header_in->last; p++) {
539 if (*p == CR || *p == LF) {
540 break;
541 }
542 }
543
544 r->request_line.len = p - r->request_start;
545 r->request_line.data = r->request_start;
546
Igor Sysoeva1c8a922004-01-19 18:09:14 +0000547 if (rc == NGX_HTTP_PARSE_INVALID_METHOD) {
548 r->http_version = NGX_HTTP_VERSION_10;
549 }
550
Igor Sysoeva2aca9a2004-01-18 21:09:21 +0000551 ngx_http_client_error(r, rc,
552 (rc == NGX_HTTP_PARSE_INVALID_METHOD) ?
553 NGX_HTTP_NOT_IMPLEMENTED:
554 NGX_HTTP_BAD_REQUEST);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000555 return;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000556 }
557
Igor Sysoev0dad6292003-03-05 17:30:51 +0000558 /* NGX_AGAIN: a request line parsing is still not complete */
559
Igor Sysoevb7387572003-03-11 20:38:13 +0000560 if (r->header_in->last == r->header_in->end) {
Igor Sysoev1af7c822002-09-13 14:47:42 +0000561
Igor Sysoev0a280a32003-10-12 16:49:16 +0000562 /*
563 * If it's a pipelined request and a request line is not complete
Igor Sysoevbb6ec8c2003-11-20 07:05:50 +0000564 * then we have to copy it to the start of the r->header_in hunk.
565 * We have to copy it here only if the large client headers
Igor Sysoev0a280a32003-10-12 16:49:16 +0000566 * are enabled otherwise a request line had been already copied
567 * to the start of the r->header_in hunk in ngx_http_set_keepalive().
568 */
Igor Sysoev0dad6292003-03-05 17:30:51 +0000569
Igor Sysoev6253ca12003-05-27 12:18:54 +0000570 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoeva9830112003-05-19 16:39:14 +0000571
Igor Sysoev187fcd82003-05-23 11:53:01 +0000572 if (cscf->large_client_header) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000573 offset = r->request_start - r->header_in->start;
574
575 if (offset == 0) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000576 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
577 NGX_HTTP_REQUEST_URI_TOO_LARGE);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000578 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000579 }
580
581 ngx_memcpy(r->header_in->start, r->request_start,
Igor Sysoevb7387572003-03-11 20:38:13 +0000582 r->header_in->last - r->request_start);
Igor Sysoev0dad6292003-03-05 17:30:51 +0000583
Igor Sysoevb7387572003-03-11 20:38:13 +0000584 r->header_in->pos -= offset;
585 r->header_in->last -= offset;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000586 r->request_start = r->header_in->start;
587 r->request_end -= offset;
588 r->uri_start -= offset;
589 r->uri_end -= offset;
590 if (r->uri_ext) {
591 r->uri_ext -= offset;
592 }
593 if (r->args_start) {
594 r->args_start -= offset;
595 }
596
597 } else {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000598 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
599 NGX_HTTP_REQUEST_URI_TOO_LARGE);
Igor Sysoev0dad6292003-03-05 17:30:51 +0000600 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000601 }
602
Igor Sysoev6b863e32003-05-12 15:52:24 +0000603 return;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000604}
605
Igor Sysoev1af7c822002-09-13 14:47:42 +0000606
Igor Sysoev6b863e32003-05-12 15:52:24 +0000607static void ngx_http_process_request_headers(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000608{
Igor Sysoev187fcd82003-05-23 11:53:01 +0000609 ssize_t n;
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000610 ngx_int_t rc, i, offset;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000611 ngx_table_elt_t *h;
612 ngx_connection_t *c;
613 ngx_http_request_t *r;
Igor Sysoev187fcd82003-05-23 11:53:01 +0000614 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000615
Igor Sysoeva9830112003-05-19 16:39:14 +0000616 c = rev->data;
617 r = c->data;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000618
Igor Sysoev865c1502003-11-30 20:03:18 +0000619 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
620 "http process request header line");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000621
Igor Sysoev6b863e32003-05-12 15:52:24 +0000622 if (rev->timedout) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000623 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000624 return;
625 }
626
Igor Sysoev6253ca12003-05-27 12:18:54 +0000627 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
628
Igor Sysoevd581fd52003-05-13 16:02:32 +0000629 rc = NGX_AGAIN;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000630
Igor Sysoev016b8522002-08-29 16:59:54 +0000631 for ( ;; ) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000632 if (rc == NGX_AGAIN) {
633 n = ngx_http_read_request_header(r);
634
635 if (n == NGX_AGAIN || n == NGX_ERROR) {
636 return;
637 }
638 }
639
Igor Sysoeve6779222003-10-03 15:50:53 +0000640 rc = ngx_http_parse_header_line(r, r->header_in);
Igor Sysoev016b8522002-08-29 16:59:54 +0000641
Igor Sysoev0dad6292003-03-05 17:30:51 +0000642 if (rc == NGX_OK) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000643
644 /* a header line has been parsed successfully */
645
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000646 h = ngx_http_add_header(&r->headers_in, ngx_http_headers_in);
647 if (h == NULL) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000648 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
649 ngx_http_close_connection(c);
650 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000651 }
652
Igor Sysoevd581fd52003-05-13 16:02:32 +0000653 h->key.len = r->header_name_end - r->header_name_start;
654 h->value.len = r->header_end - r->header_start;
655
656 /* if the large client headers are enabled then
657 we need to copy the header name and value */
658
Igor Sysoev187fcd82003-05-23 11:53:01 +0000659 if (cscf->large_client_header) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000660 h->key.data = ngx_palloc(r->pool,
661 h->key.len + 1 + h->value.len + 1);
662 if (h->key.data == NULL) {
663 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
664 ngx_http_close_connection(c);
665 return;
666 }
667
668 h->value.data = h->key.data + h->key.len + 1;
669 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
670 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
671
672 } else {
673 h->key.data = r->header_name_start;
674 h->key.data[h->key.len] = '\0';
675 h->value.data = r->header_start;
676 h->value.data[h->value.len] = '\0';
677 }
678
Igor Sysoevb5faed22003-10-29 08:30:44 +0000679 for (i = 0; ngx_http_headers_in[i].name.len != 0; i++) {
680 if (ngx_http_headers_in[i].name.len != h->key.len) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000681 continue;
682 }
683
Igor Sysoevb5faed22003-10-29 08:30:44 +0000684 if (ngx_strcasecmp(ngx_http_headers_in[i].name.data,
685 h->key.data) == 0)
686 {
687 *((ngx_table_elt_t **) ((char *) &r->headers_in
688 + ngx_http_headers_in[i].offset)) = h;
Igor Sysoev9760a132003-10-21 07:47:21 +0000689 break;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000690 }
691 }
692
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000693 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
Igor Sysoevfc68ea62003-12-22 17:27:24 +0000694 "http header: \"%s: %s\"",
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000695 h->key.data, h->value.data);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000696
Igor Sysoev187fcd82003-05-23 11:53:01 +0000697 if (cscf->large_client_header
Igor Sysoevdc479b42003-03-20 16:09:44 +0000698 && r->header_in->pos == r->header_in->last)
699 {
700 r->header_in->pos = r->header_in->last = r->header_in->start;
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000701 }
702
Igor Sysoev6253ca12003-05-27 12:18:54 +0000703 continue;
704
Igor Sysoev1af7c822002-09-13 14:47:42 +0000705 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000706
707 /* a whole header has been parsed successfully */
708
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000709 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
710 "http header done");
Igor Sysoev42feecb2002-12-15 06:25:09 +0000711
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000712 rc = ngx_http_process_request_header(r);
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000713
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000714 if (rc != NGX_OK) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000715 ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST);
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000716 return;
Igor Sysoeva09f08d2003-04-25 14:43:13 +0000717 }
718
Igor Sysoev425a42c2003-10-27 16:16:17 +0000719 if (rev->timer_set) {
Igor Sysoev0a280a32003-10-12 16:49:16 +0000720 ngx_del_timer(rev);
721 }
722
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000723 rev->event_handler = ngx_http_block_read;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000724 ngx_http_handler(r);
725 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000726
Igor Sysoev0dad6292003-03-05 17:30:51 +0000727 } else if (rc != NGX_AGAIN) {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000728
729 /* there was error while a header line parsing */
730
Igor Sysoev732a2712004-04-21 18:54:33 +0000731#if (NGX_DEBUG)
732 if (rc == NGX_HTTP_PARSE_INVALID_HEADER
733 && (rev->log->log_level & NGX_LOG_DEBUG_HTTP))
734 {
Igor Sysoev10a543a2004-03-16 07:10:12 +0000735 u_char *p;
Igor Sysoev669e3312003-12-22 09:40:48 +0000736 for (p = r->header_name_start;
737 p < r->header_in->last - 1;
738 p++)
739 {
Igor Sysoev76f7b5e2004-01-29 17:06:07 +0000740 if (*p == LF) {
Igor Sysoev669e3312003-12-22 09:40:48 +0000741 break;
742 }
743 }
744 *p = '\0';
745 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
746 "http invalid header: \"%s\"",
747 r->header_name_start);
748 }
749#endif
750
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000751 ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000752 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000753 }
754
755 /* NGX_AGAIN: a header line parsing is still not complete */
756
Igor Sysoevb7387572003-03-11 20:38:13 +0000757 if (r->header_in->last == r->header_in->end) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000758
Igor Sysoevb7387572003-03-11 20:38:13 +0000759 /* if the large client headers are enabled then
Igor Sysoev0dad6292003-03-05 17:30:51 +0000760 we need to compact r->header_in hunk */
761
Igor Sysoev187fcd82003-05-23 11:53:01 +0000762 if (cscf->large_client_header) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000763 offset = r->header_name_start - r->header_in->start;
764
765 if (offset == 0) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000766 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER,
767 NGX_HTTP_BAD_REQUEST);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000768 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000769 }
770
771 ngx_memcpy(r->header_in->start, r->header_name_start,
Igor Sysoevb7387572003-03-11 20:38:13 +0000772 r->header_in->last - r->header_name_start);
Igor Sysoev0dad6292003-03-05 17:30:51 +0000773
Igor Sysoevb7387572003-03-11 20:38:13 +0000774 r->header_in->last -= offset;
775 r->header_in->pos -= offset;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000776 r->header_name_start = r->header_in->start;
777 r->header_name_end -= offset;
778 r->header_start -= offset;
779 r->header_end -= offset;
780
781 } else {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000782 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER,
783 NGX_HTTP_BAD_REQUEST);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000784 return;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000785 }
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000786 }
787 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000788}
789
Igor Sysoevb0869052002-12-10 18:05:12 +0000790
Igor Sysoev6b863e32003-05-12 15:52:24 +0000791static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
792{
Igor Sysoev187fcd82003-05-23 11:53:01 +0000793 ssize_t n;
794 ngx_event_t *rev;
795 ngx_http_core_srv_conf_t *cscf;
Igor Sysoev6b863e32003-05-12 15:52:24 +0000796
Igor Sysoev239baac2003-06-11 15:28:34 +0000797 rev = r->connection->read;
798
Igor Sysoev6b863e32003-05-12 15:52:24 +0000799 n = r->header_in->last - r->header_in->pos;
800
801 if (n > 0) {
802 return n;
803 }
804
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000805 if (!rev->ready) {
806 return NGX_AGAIN;
807 }
808
Igor Sysoev239baac2003-06-11 15:28:34 +0000809 n = ngx_recv(r->connection, r->header_in->last,
810 r->header_in->end - r->header_in->last);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000811
812 if (n == NGX_AGAIN) {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000813 if (!r->header_timeout_set) {
Igor Sysoev6253ca12003-05-27 12:18:54 +0000814 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoev187fcd82003-05-23 11:53:01 +0000815 ngx_add_timer(rev, cscf->client_header_timeout);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000816 r->header_timeout_set = 1;
817 }
818
Igor Sysoevb5faed22003-10-29 08:30:44 +0000819 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000820 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
821 ngx_http_close_connection(r->connection);
822 return NGX_ERROR;
823 }
824
Igor Sysoev6b863e32003-05-12 15:52:24 +0000825 return NGX_AGAIN;
826 }
827
828 if (n == 0) {
829 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
830 "client closed prematurely connection");
Igor Sysoevd581fd52003-05-13 16:02:32 +0000831 }
Igor Sysoev6b863e32003-05-12 15:52:24 +0000832
833 if (n == 0 || n == NGX_ERROR) {
834 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000835 ngx_http_close_connection(r->connection);
Igor Sysoev6b863e32003-05-12 15:52:24 +0000836 return NGX_ERROR;
837 }
838
839 r->header_in->last += n;
840
841 return n;
842}
843
844
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000845static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r)
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000846{
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000847 size_t len;
Igor Sysoev10a543a2004-03-16 07:10:12 +0000848 ngx_uint_t i;
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000849 ngx_http_server_name_t *name;
850 ngx_http_core_loc_conf_t *clcf;
851
852 if (r->headers_in.host) {
853 for (len = 0; len < r->headers_in.host->value.len; len++) {
854 if (r->headers_in.host->value.data[len] == ':') {
855 break;
856 }
857 }
858 r->headers_in.host_name_len = len;
859
860 /* find the name based server configuration */
861
862 name = r->virtual_names->elts;
863 for (i = 0; i < r->virtual_names->nelts; i++) {
864 if (r->headers_in.host_name_len != name[i].name.len) {
865 continue;
866 }
867
868 if (ngx_strncasecmp(r->headers_in.host->value.data,
869 name[i].name.data,
870 r->headers_in.host_name_len) == 0)
871 {
872 r->srv_conf = name[i].core_srv_conf->ctx->srv_conf;
873 r->loc_conf = name[i].core_srv_conf->ctx->loc_conf;
874
875 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
876 r->connection->log->file = clcf->err_log->file;
877 r->connection->log->log_level = clcf->err_log->log_level;
878
879 break;
880 }
881 }
882
883 } else {
884 if (r->http_version > NGX_HTTP_VERSION_10) {
885 return NGX_HTTP_PARSE_NO_HOST_HEADER;
886 }
887 r->headers_in.host_name_len = 0;
888 }
889
890 if (r->headers_in.content_length) {
891 r->headers_in.content_length_n =
892 ngx_atoi(r->headers_in.content_length->value.data,
893 r->headers_in.content_length->value.len);
894
895 if (r->headers_in.content_length_n == NGX_ERROR) {
896 return NGX_HTTP_PARSE_INVALID_CL_HEADER;
897 }
898 }
899
Igor Sysoev6881bfb2004-03-30 06:27:36 +0000900 if (r->method == NGX_HTTP_POST && r->headers_in.content_length_n <= 0) {
901 return NGX_HTTP_PARSE_POST_WO_CL_HEADER;
902 }
903
Igor Sysoev419f9ac2003-10-21 16:49:56 +0000904 if (r->headers_in.connection) {
905 if (r->headers_in.connection->value.len == 5
906 && ngx_strcasecmp(r->headers_in.connection->value.data, "close")
907 == 0)
908 {
909 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
910
911 } else if (r->headers_in.connection->value.len == 10
912 && ngx_strcasecmp(r->headers_in.connection->value.data,
913 "keep-alive") == 0)
914 {
915 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
916
917 if (r->headers_in.keep_alive) {
918 r->headers_in.keep_alive_n =
919 ngx_atoi(r->headers_in.keep_alive->value.data,
920 r->headers_in.keep_alive->value.len);
921 }
922 }
923 }
924
925 return NGX_OK;
926}
927
928
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000929void ngx_http_finalize_request(ngx_http_request_t *r, int rc)
Igor Sysoevd581fd52003-05-13 16:02:32 +0000930{
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000931 ngx_http_core_loc_conf_t *clcf;
932
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000933 /* r can be already destroyed when rc == NGX_DONE */
Igor Sysoevd581fd52003-05-13 16:02:32 +0000934
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000935 if (rc == NGX_DONE || r->main) {
Igor Sysoev1342d9c2003-10-09 07:00:45 +0000936 return;
937 }
938
Igor Sysoevae02c192004-03-19 05:25:53 +0000939 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
940 "http finalize request: %d", rc);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000941
Igor Sysoevd581fd52003-05-13 16:02:32 +0000942 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
943
Igor Sysoev0a280a32003-10-12 16:49:16 +0000944 if (r->connection->read->timer_set) {
945 ngx_del_timer(r->connection->read);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +0000946 }
947
Igor Sysoev0a280a32003-10-12 16:49:16 +0000948 if (r->connection->write->timer_set) {
949 ngx_del_timer(r->connection->write);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000950 }
951
Igor Sysoev89690bf2004-03-23 06:01:52 +0000952 if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST || r->closed) {
953 ngx_http_close_request(r, 0);
954 ngx_http_close_connection(r->connection);
955 return;
956 }
957
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000958 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
Igor Sysoev239baac2003-06-11 15:28:34 +0000959
Igor Sysoev1342d9c2003-10-09 07:00:45 +0000960 return;
Igor Sysoev1342d9c2003-10-09 07:00:45 +0000961
Igor Sysoev239baac2003-06-11 15:28:34 +0000962 } else if (rc == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000963 ngx_http_close_request(r, 0);
964 ngx_http_close_connection(r->connection);
965 return;
Igor Sysoev1342d9c2003-10-09 07:00:45 +0000966
Igor Sysoevb3e73d82003-10-10 15:10:50 +0000967 } else if (rc == NGX_AGAIN) {
968 ngx_http_set_write_handler(r);
969 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +0000970 }
971
Igor Sysoev0a280a32003-10-12 16:49:16 +0000972 if (r->connection->read->timer_set) {
973 ngx_del_timer(r->connection->read);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000974 }
975
Igor Sysoev0a280a32003-10-12 16:49:16 +0000976 if (r->connection->write->timer_set) {
977 ngx_del_timer(r->connection->write);
Igor Sysoevd581fd52003-05-13 16:02:32 +0000978 }
979
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000980 if (r->connection->read->kq_eof) {
981#if (NGX_KQUEUE)
982 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log,
983 r->connection->read->kq_errno,
Igor Sysoev7af6b162004-02-09 07:46:43 +0000984 "kevent() reported about an closed connection");
Igor Sysoev3c3ca172004-01-05 20:55:48 +0000985#endif
986 ngx_http_close_request(r, 0);
987 ngx_http_close_connection(r->connection);
988 return;
989 }
990
Igor Sysoevdc867cd2003-12-14 20:10:27 +0000991 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
992
Igor Sysoevc5991982004-01-16 06:15:48 +0000993 if (!ngx_terminate
994 && !ngx_quit
995 && r->keepalive != 0
996 && clcf->keepalive_timeout > 0)
997 {
Igor Sysoevd581fd52003-05-13 16:02:32 +0000998 ngx_http_set_keepalive(r);
Igor Sysoevc5991982004-01-16 06:15:48 +0000999 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001000
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001001 } else if (r->lingering_close && clcf->lingering_timeout > 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001002 ngx_http_set_lingering_close(r);
Igor Sysoevc5991982004-01-16 06:15:48 +00001003 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001004 }
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001005
Igor Sysoevc5991982004-01-16 06:15:48 +00001006 ngx_http_close_request(r, 0);
1007 ngx_http_close_connection(r->connection);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001008}
1009
1010
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001011static void ngx_http_set_write_handler(ngx_http_request_t *r)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001012{
Igor Sysoevd581fd52003-05-13 16:02:32 +00001013 ngx_event_t *wev;
Igor Sysoeva9830112003-05-19 16:39:14 +00001014 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001015
1016 wev = r->connection->write;
1017 wev->event_handler = ngx_http_writer;
1018
1019 if (wev->delayed && wev->ready) {
1020 return;
1021 }
1022
Igor Sysoev6253ca12003-05-27 12:18:54 +00001023 clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
1024 ngx_http_core_module);
Igor Sysoeva9830112003-05-19 16:39:14 +00001025 ngx_add_timer(wev, clcf->send_timeout);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001026
Igor Sysoev222a2ad2003-11-18 16:49:00 +00001027 wev->available = clcf->send_lowat;
1028 if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001029 ngx_http_close_request(r, 0);
1030 ngx_http_close_connection(r->connection);
1031 }
1032
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001033 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001034}
1035
1036
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001037void ngx_http_writer(ngx_event_t *wev)
Igor Sysoevd581fd52003-05-13 16:02:32 +00001038{
1039 int rc;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001040 ngx_connection_t *c;
1041 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001042 ngx_http_core_loc_conf_t *clcf;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001043
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001044 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http writer handler");
Igor Sysoev160d7742003-11-19 16:26:41 +00001045
Igor Sysoev6253ca12003-05-27 12:18:54 +00001046 c = wev->data;
1047 r = c->data;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001048
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001049#if 0 /* TODO: THINK */
1050 if (wev->delayed) {
1051 return;
1052 }
1053#endif
1054
1055 if (wev->timedout) {
1056 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
1057 return;
1058 }
1059
Igor Sysoevd581fd52003-05-13 16:02:32 +00001060 rc = ngx_http_output_filter(r, NULL);
1061
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001062 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1063 "http writer output filter: %d", rc);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001064
1065 if (rc == NGX_AGAIN) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001066 if (!wev->ready) {
1067 clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
1068 ngx_http_core_module);
1069 ngx_add_timer(wev, clcf->send_timeout);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001070 }
1071
Igor Sysoev0a280a32003-10-12 16:49:16 +00001072 if (ngx_handle_level_write_event(wev) == NGX_ERROR) {
1073 ngx_http_close_request(r, 0);
1074 ngx_http_close_connection(r->connection);
1075 }
Igor Sysoevd581fd52003-05-13 16:02:32 +00001076
1077 return;
1078 }
1079
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001080 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http writer done");
Igor Sysoevd581fd52003-05-13 16:02:32 +00001081
Igor Sysoev0a280a32003-10-12 16:49:16 +00001082 ngx_http_finalize_request(r, rc);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001083}
1084
1085
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001086static void ngx_http_block_read(ngx_event_t *rev)
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001087{
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001088 ngx_connection_t *c;
1089 ngx_http_request_t *r;
1090
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001091 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http read blocked");
Igor Sysoev42feecb2002-12-15 06:25:09 +00001092
Igor Sysoev73009772003-02-06 17:21:13 +00001093 /* aio does not call this handler */
1094
Igor Sysoev0a280a32003-10-12 16:49:16 +00001095 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001096 if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001097 c = rev->data;
1098 r = c->data;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001099 ngx_http_close_request(r, 0);
1100 ngx_http_close_connection(c);
1101 }
Igor Sysoev73009772003-02-06 17:21:13 +00001102 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001103}
1104
1105
Igor Sysoevd581fd52003-05-13 16:02:32 +00001106int ngx_http_discard_body(ngx_http_request_t *r)
1107{
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001108 ssize_t size;
1109 ngx_event_t *rev;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001110
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001111 rev = r->connection->read;
Igor Sysoev9b25d692003-01-26 21:08:14 +00001112
Igor Sysoevdc867cd2003-12-14 20:10:27 +00001113 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body");
Igor Sysoev9b25d692003-01-26 21:08:14 +00001114
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001115 if (rev->timer_set) {
1116 ngx_del_timer(rev);
Igor Sysoev9b25d692003-01-26 21:08:14 +00001117 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001118
Igor Sysoev0a280a32003-10-12 16:49:16 +00001119 if (r->headers_in.content_length_n <= 0) {
1120 return NGX_OK;
1121 }
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001122
Igor Sysoev0a280a32003-10-12 16:49:16 +00001123 size = r->header_in->last - r->header_in->pos;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001124
Igor Sysoev0a280a32003-10-12 16:49:16 +00001125 if (size) {
1126 if (r->headers_in.content_length_n > size) {
1127 r->headers_in.content_length_n -= size;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001128
Igor Sysoev0a280a32003-10-12 16:49:16 +00001129 } else {
1130 r->header_in->pos += r->headers_in.content_length_n;
1131 r->headers_in.content_length_n = 0;
1132 return NGX_OK;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001133 }
Igor Sysoev73009772003-02-06 17:21:13 +00001134 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001135
Igor Sysoev0a280a32003-10-12 16:49:16 +00001136 rev->event_handler = ngx_http_read_discarded_body_event;
1137
1138 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1139 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1140 }
1141
1142 return ngx_http_read_discarded_body(r);
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001143}
1144
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001145
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001146static void ngx_http_read_discarded_body_event(ngx_event_t *rev)
Igor Sysoev42feecb2002-12-15 06:25:09 +00001147{
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001148 int rc;
1149 ngx_connection_t *c;
1150 ngx_http_request_t *r;
1151
Igor Sysoev6253ca12003-05-27 12:18:54 +00001152 c = rev->data;
1153 r = c->data;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001154
1155 rc = ngx_http_read_discarded_body(r);
1156
Igor Sysoev0a280a32003-10-12 16:49:16 +00001157 if (rc == NGX_AGAIN) {
1158 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1159 ngx_http_close_request(r, rc);
1160 ngx_http_close_connection(c);
1161 return;
1162 }
1163 }
1164
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001165 if (rc != NGX_OK) {
1166 ngx_http_close_request(r, rc);
1167 ngx_http_close_connection(c);
1168 }
1169}
1170
1171
1172static int ngx_http_read_discarded_body(ngx_http_request_t *r)
1173{
Igor Sysoev09159772003-06-12 05:54:39 +00001174 ssize_t size, n;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001175 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev42feecb2002-12-15 06:25:09 +00001176
Igor Sysoeve04084c2004-01-26 08:52:49 +00001177 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1178 "http read discarded body");
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001179
Igor Sysoev0a280a32003-10-12 16:49:16 +00001180 if (r->headers_in.content_length_n == 0) {
1181 return NGX_OK;
1182 }
1183
Igor Sysoev6253ca12003-05-27 12:18:54 +00001184 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001185
Igor Sysoevdc479b42003-03-20 16:09:44 +00001186 if (r->discarded_buffer == NULL) {
Igor Sysoev6253ca12003-05-27 12:18:54 +00001187 r->discarded_buffer = ngx_palloc(r->pool, clcf->discarded_buffer_size);
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001188 if (r->discarded_buffer == NULL) {
1189 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1190 }
Igor Sysoevdc479b42003-03-20 16:09:44 +00001191 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001192
Igor Sysoeva09f08d2003-04-25 14:43:13 +00001193 size = r->headers_in.content_length_n;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001194
Igor Sysoev10a543a2004-03-16 07:10:12 +00001195 if (size > (ssize_t) clcf->discarded_buffer_size) {
1196 size = (ssize_t) clcf->discarded_buffer_size;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001197 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001198
Igor Sysoev239baac2003-06-11 15:28:34 +00001199 n = ngx_recv(r->connection, r->discarded_buffer, size);
Igor Sysoevdc479b42003-03-20 16:09:44 +00001200 if (n == NGX_ERROR) {
Igor Sysoev89690bf2004-03-23 06:01:52 +00001201
1202 r->closed = 1;
1203
1204 /*
1205 * when a client request body is discarded then we already set
1206 * some HTTP response code for client and we can ignore the error
1207 */
1208
1209 return NGX_OK;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001210 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001211
Igor Sysoevdc479b42003-03-20 16:09:44 +00001212 if (n == NGX_AGAIN) {
Igor Sysoev0a280a32003-10-12 16:49:16 +00001213 return NGX_AGAIN;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001214 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001215
Igor Sysoeva09f08d2003-04-25 14:43:13 +00001216 r->headers_in.content_length_n -= n;
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001217
Igor Sysoev42feecb2002-12-15 06:25:09 +00001218 return NGX_OK;
1219}
1220
1221
Igor Sysoevd581fd52003-05-13 16:02:32 +00001222static void ngx_http_set_keepalive(ngx_http_request_t *r)
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001223{
Igor Sysoev0a280a32003-10-12 16:49:16 +00001224 int len;
Igor Sysoev187fcd82003-05-23 11:53:01 +00001225 ngx_hunk_t *h;
1226 ngx_event_t *rev, *wev;
1227 ngx_connection_t *c;
1228 ngx_http_log_ctx_t *ctx;
1229 ngx_http_core_srv_conf_t *cscf;
1230 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001231
Igor Sysoev6253ca12003-05-27 12:18:54 +00001232 c = r->connection;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001233 rev = c->read;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001234
Igor Sysoeve04084c2004-01-26 08:52:49 +00001235 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001236
Igor Sysoev6a644c62003-03-04 06:33:48 +00001237 ctx = (ngx_http_log_ctx_t *) c->log->data;
1238 ctx->action = "closing request";
Igor Sysoevdc479b42003-03-20 16:09:44 +00001239 ngx_http_close_request(r, 0);
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001240
Igor Sysoev6253ca12003-05-27 12:18:54 +00001241 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoevfa73aac2003-05-21 13:28:21 +00001242 ngx_add_timer(rev, clcf->keepalive_timeout);
1243
Igor Sysoev0a280a32003-10-12 16:49:16 +00001244 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1245 ngx_http_close_connection(c);
1246 return;
Igor Sysoevb7387572003-03-11 20:38:13 +00001247 }
1248
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001249 h = c->buffer;
Igor Sysoev7b6062a2004-02-12 20:57:10 +00001250 wev = c->write;
1251 wev->event_handler = ngx_http_empty_handler;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001252
Igor Sysoev6881bfb2004-03-30 06:27:36 +00001253
Igor Sysoevb7387572003-03-11 20:38:13 +00001254 if (h->pos < h->last) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001255
Igor Sysoev74e95c22003-11-09 20:03:38 +00001256 /*
Igor Sysoev6881bfb2004-03-30 06:27:36 +00001257 * The pipelined request.
Igor Sysoev0a280a32003-10-12 16:49:16 +00001258 *
Igor Sysoeva2aca9a2004-01-18 21:09:21 +00001259 * We do not know here whether the pipelined request is complete
Igor Sysoev0a280a32003-10-12 16:49:16 +00001260 * so if the large client headers are not enabled
1261 * we need to copy the data to the start of c->buffer.
1262 * This copy should be rare because clients that support
1263 * pipelined requests (Mozilla 1.x, Opera 6.x+) are still rare.
1264 */
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001265
Igor Sysoev6253ca12003-05-27 12:18:54 +00001266 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
Igor Sysoeva9830112003-05-19 16:39:14 +00001267
Igor Sysoev187fcd82003-05-23 11:53:01 +00001268 if (!cscf->large_client_header) {
1269 len = h->last - h->pos;
Igor Sysoevb7387572003-03-11 20:38:13 +00001270 ngx_memcpy(h->start, h->pos, len);
1271 h->pos = h->start;
1272 h->last = h->start + len;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001273 }
1274
Igor Sysoeve04084c2004-01-26 08:52:49 +00001275 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
Igor Sysoev6253ca12003-05-27 12:18:54 +00001276
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001277 c->pipeline = 1;
1278 ctx->action = "reading client pipelined request line";
Igor Sysoevd581fd52003-05-13 16:02:32 +00001279 ngx_http_init_request(rev);
1280 return;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001281 }
1282
1283 c->pipeline = 0;
1284
Igor Sysoevb7387572003-03-11 20:38:13 +00001285 h->pos = h->last = h->start;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001286 rev->event_handler = ngx_http_keepalive_handler;
1287
Igor Sysoevd9d0ca12003-11-21 06:30:49 +00001288 if (wev->active) {
1289 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
1290 if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_DISABLE_EVENT)
1291 == NGX_ERROR)
1292 {
1293 ngx_http_close_connection(c);
1294 return;
1295 }
1296
1297 } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
1298 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
1299 ngx_http_close_connection(c);
1300 return;
1301 }
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001302 }
1303 }
1304
Igor Sysoev6a644c62003-03-04 06:33:48 +00001305 ctx->action = "keepalive";
1306
Igor Sysoev3c3ca172004-01-05 20:55:48 +00001307 if (c->tcp_nopush == 1) {
Igor Sysoev9cf78302003-06-04 17:28:33 +00001308 if (ngx_tcp_push(c->fd) == NGX_ERROR) {
1309 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
1310 ngx_tcp_push_n " failed");
1311 ngx_http_close_connection(c);
1312 return;
1313 }
1314 c->tcp_nopush = 0;
1315 }
1316
Igor Sysoevb5faed22003-10-29 08:30:44 +00001317 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001318 ngx_http_keepalive_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00001319 }
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001320}
1321
1322
Igor Sysoevd581fd52003-05-13 16:02:32 +00001323static void ngx_http_keepalive_handler(ngx_event_t *rev)
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001324{
Igor Sysoev0a280a32003-10-12 16:49:16 +00001325 ssize_t n;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001326 ngx_connection_t *c;
Igor Sysoev160d7742003-11-19 16:26:41 +00001327 ngx_http_log_ctx_t *ctx;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001328
Igor Sysoevdc479b42003-03-20 16:09:44 +00001329 c = (ngx_connection_t *) rev->data;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001330
Igor Sysoeve04084c2004-01-26 08:52:49 +00001331 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
Igor Sysoev1af7c822002-09-13 14:47:42 +00001332
Igor Sysoevdc479b42003-03-20 16:09:44 +00001333 if (rev->timedout) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001334 ngx_http_close_connection(c);
1335 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00001336 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001337
Igor Sysoev0a280a32003-10-12 16:49:16 +00001338 /*
1339 * MSIE closes a keepalive connection with RST flag
1340 * so we ignore ECONNRESET here.
1341 */
Igor Sysoevb7387572003-03-11 20:38:13 +00001342
Igor Sysoevc7a2f682004-02-10 16:23:38 +00001343 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
Igor Sysoevb7387572003-03-11 20:38:13 +00001344 ngx_set_socket_errno(0);
Igor Sysoev239baac2003-06-11 15:28:34 +00001345 n = ngx_recv(c, c->buffer->last, c->buffer->end - c->buffer->last);
Igor Sysoevc7a2f682004-02-10 16:23:38 +00001346 c->log_error = NGX_ERROR_INFO;
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001347
Igor Sysoevd581fd52003-05-13 16:02:32 +00001348 if (n == NGX_AGAIN) {
1349 return;
1350 }
1351
1352 if (n == NGX_ERROR) {
1353 ngx_http_close_connection(c);
1354 return;
Igor Sysoev90ace682003-03-12 17:32:22 +00001355 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001356
Igor Sysoev160d7742003-11-19 16:26:41 +00001357 ctx = (ngx_http_log_ctx_t *) rev->log->data;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001358 rev->log->handler = NULL;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001359
1360 if (n == 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +00001361 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
Igor Sysoev160d7742003-11-19 16:26:41 +00001362 "client %s closed keepalive connection", ctx->client);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001363 ngx_http_close_connection(c);
1364 return;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001365 }
1366
Igor Sysoevb7387572003-03-11 20:38:13 +00001367 c->buffer->last += n;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001368 rev->log->handler = ngx_http_log_error;
Igor Sysoev160d7742003-11-19 16:26:41 +00001369 ctx->action = "reading client request line";
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001370
Igor Sysoevd581fd52003-05-13 16:02:32 +00001371 ngx_http_init_request(rev);
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001372}
1373
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001374
Igor Sysoevd581fd52003-05-13 16:02:32 +00001375static void ngx_http_set_lingering_close(ngx_http_request_t *r)
Igor Sysoev1af7c822002-09-13 14:47:42 +00001376{
Igor Sysoev0a280a32003-10-12 16:49:16 +00001377 ngx_event_t *rev, *wev;
Igor Sysoevb7387572003-03-11 20:38:13 +00001378 ngx_connection_t *c;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001379 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001380
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001381 c = r->connection;
Igor Sysoev9b25d692003-01-26 21:08:14 +00001382
Igor Sysoev6253ca12003-05-27 12:18:54 +00001383 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001384
Igor Sysoev0a280a32003-10-12 16:49:16 +00001385 rev = c->read;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001386 rev->event_handler = ngx_http_lingering_close_handler;
Igor Sysoev42feecb2002-12-15 06:25:09 +00001387
Igor Sysoeve89c4582003-12-19 08:15:11 +00001388 r->lingering_time = ngx_cached_time + clcf->lingering_time / 1000;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001389 ngx_add_timer(rev, clcf->lingering_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +00001390
Igor Sysoev0a280a32003-10-12 16:49:16 +00001391 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1392 ngx_http_close_request(r, 0);
1393 ngx_http_close_connection(c);
1394 return;
1395 }
1396
1397 wev = c->write;
1398 wev->event_handler = ngx_http_empty_handler;
1399
Igor Sysoevd9d0ca12003-11-21 06:30:49 +00001400 if (wev->active) {
1401 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
1402 if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_DISABLE_EVENT)
1403 == NGX_ERROR)
1404 {
1405 ngx_http_close_connection(c);
1406 return;
1407 }
1408
1409 } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
1410 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
1411 ngx_http_close_connection(c);
1412 return;
1413 }
Igor Sysoevb7387572003-03-11 20:38:13 +00001414 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001415 }
1416
Igor Sysoevb7387572003-03-11 20:38:13 +00001417 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
1418 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
Igor Sysoev42feecb2002-12-15 06:25:09 +00001419 ngx_shutdown_socket_n " failed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00001420 ngx_http_close_request(r, 0);
1421 ngx_http_close_connection(c);
1422 return;
Igor Sysoev42feecb2002-12-15 06:25:09 +00001423 }
1424
Igor Sysoevb5faed22003-10-29 08:30:44 +00001425 if (rev->ready) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001426 ngx_http_lingering_close_handler(rev);
Igor Sysoevb7387572003-03-11 20:38:13 +00001427 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001428}
1429
1430
Igor Sysoevd581fd52003-05-13 16:02:32 +00001431static void ngx_http_lingering_close_handler(ngx_event_t *rev)
Igor Sysoev42feecb2002-12-15 06:25:09 +00001432{
Igor Sysoevdc479b42003-03-20 16:09:44 +00001433 ssize_t n;
1434 ngx_msec_t timer;
1435 ngx_connection_t *c;
1436 ngx_http_request_t *r;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001437 ngx_http_core_loc_conf_t *clcf;
Igor Sysoev1af7c822002-09-13 14:47:42 +00001438
Igor Sysoev6253ca12003-05-27 12:18:54 +00001439 c = rev->data;
1440 r = c->data;
Igor Sysoev86de4cb2003-01-30 07:28:09 +00001441
Igor Sysoeve04084c2004-01-26 08:52:49 +00001442 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1443 "http lingering close handler");
Igor Sysoevdc479b42003-03-20 16:09:44 +00001444
1445 if (rev->timedout) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001446 ngx_http_close_request(r, 0);
1447 ngx_http_close_connection(c);
1448 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001449 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001450
Igor Sysoeve89c4582003-12-19 08:15:11 +00001451 timer = r->lingering_time - ngx_cached_time;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001452 if (timer <= 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001453 ngx_http_close_request(r, 0);
1454 ngx_http_close_connection(c);
1455 return;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001456 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001457
Igor Sysoev6253ca12003-05-27 12:18:54 +00001458 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001459
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001460 if (r->discarded_buffer == NULL) {
Igor Sysoevb7387572003-03-11 20:38:13 +00001461
1462 /* TODO: r->header_in->start (if large headers are enabled)
1463 or the end of parsed header (otherwise)
1464 instead of r->header_in->last */
1465
Igor Sysoev09159772003-06-12 05:54:39 +00001466 if (r->header_in->end - r->header_in->last
Igor Sysoev10a543a2004-03-16 07:10:12 +00001467 >= (ssize_t) clcf->discarded_buffer_size)
1468 {
Igor Sysoevb7387572003-03-11 20:38:13 +00001469 r->discarded_buffer = r->header_in->last;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001470
1471 } else {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001472 r->discarded_buffer = ngx_palloc(c->pool,
Igor Sysoev6253ca12003-05-27 12:18:54 +00001473 clcf->discarded_buffer_size);
Igor Sysoevd581fd52003-05-13 16:02:32 +00001474 if (r->discarded_buffer) {
1475 ngx_http_close_request(r, 0);
1476 ngx_http_close_connection(c);
1477 return;
1478 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001479 }
1480 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001481
Igor Sysoevdc479b42003-03-20 16:09:44 +00001482 do {
Igor Sysoev239baac2003-06-11 15:28:34 +00001483 n = ngx_recv(c, r->discarded_buffer, clcf->discarded_buffer_size);
Igor Sysoev1af7c822002-09-13 14:47:42 +00001484
Igor Sysoeve04084c2004-01-26 08:52:49 +00001485 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
Igor Sysoev1af7c822002-09-13 14:47:42 +00001486
Igor Sysoevdc479b42003-03-20 16:09:44 +00001487 if (n == NGX_ERROR || n == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001488 ngx_http_close_request(r, 0);
1489 ngx_http_close_connection(c);
1490 return;
Igor Sysoevdc479b42003-03-20 16:09:44 +00001491 }
1492
1493 } while (rev->ready);
Igor Sysoev1af7c822002-09-13 14:47:42 +00001494
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001495 timer *= 1000;
Igor Sysoev6253ca12003-05-27 12:18:54 +00001496 if (timer > clcf->lingering_timeout) {
1497 timer = clcf->lingering_timeout;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001498 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001499
Igor Sysoevdc479b42003-03-20 16:09:44 +00001500 ngx_add_timer(rev, timer);
Igor Sysoev1af7c822002-09-13 14:47:42 +00001501
Igor Sysoevd581fd52003-05-13 16:02:32 +00001502 return;
Igor Sysoev1af7c822002-09-13 14:47:42 +00001503}
1504
Igor Sysoev2b542382002-08-20 14:48:28 +00001505
Igor Sysoev160d7742003-11-19 16:26:41 +00001506void ngx_http_empty_handler(ngx_event_t *wev)
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001507{
Igor Sysoeve04084c2004-01-26 08:52:49 +00001508 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001509
1510 return;
1511}
1512
1513
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001514int ngx_http_send_last(ngx_http_request_t *r)
1515{
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001516 ngx_hunk_t *h;
1517 ngx_chain_t out;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001518
1519 ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
1520 h->type = NGX_HUNK_LAST;
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001521 out.hunk = h;
1522 out.next = NULL;
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001523
Igor Sysoev419f9ac2003-10-21 16:49:56 +00001524 return ngx_http_output_filter(r, &out);
Igor Sysoev1342d9c2003-10-09 07:00:45 +00001525}
1526
1527
Igor Sysoevd581fd52003-05-13 16:02:32 +00001528void ngx_http_close_request(ngx_http_request_t *r, int error)
1529{
Igor Sysoev10a543a2004-03-16 07:10:12 +00001530 ngx_uint_t i;
Igor Sysoev865c1502003-11-30 20:03:18 +00001531 ngx_log_t *log;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001532 ngx_http_log_ctx_t *ctx;
Igor Sysoevc2bba092003-11-28 17:41:47 +00001533 ngx_http_cleanup_t *cleanup;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001534
Igor Sysoev865c1502003-11-30 20:03:18 +00001535 log = r->connection->log;
1536
1537 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
Igor Sysoevd581fd52003-05-13 16:02:32 +00001538
1539 if (r->pool == NULL) {
Igor Sysoev865c1502003-11-30 20:03:18 +00001540 ngx_log_error(NGX_LOG_ALERT, log, 0,
Igor Sysoev6ddfbf02003-05-15 15:42:53 +00001541 "http request already closed");
Igor Sysoevd581fd52003-05-13 16:02:32 +00001542 return;
1543 }
1544
Igor Sysoev669e3312003-12-22 09:40:48 +00001545 if (error && r->headers_out.status == 0) {
Igor Sysoevd581fd52003-05-13 16:02:32 +00001546 r->headers_out.status = error;
1547 }
1548
1549 ngx_http_log_handler(r);
1550
Igor Sysoevc2bba092003-11-28 17:41:47 +00001551 cleanup = r->cleanup.elts;
1552 for (i = 0; i < r->cleanup.nelts; i++) {
Igor Sysoev865c1502003-11-30 20:03:18 +00001553 if (!cleanup[i].valid) {
Igor Sysoevc2bba092003-11-28 17:41:47 +00001554 continue;
1555 }
1556
Igor Sysoev67f88e92004-03-12 16:57:08 +00001557#if (NGX_HTTP_CACHE)
1558
Igor Sysoev865c1502003-11-30 20:03:18 +00001559 if (cleanup[i].cache) {
1560 ngx_http_cache_unlock(cleanup[i].data.cache.hash,
1561 cleanup[i].data.cache.cache, log);
1562 continue;
1563 }
1564
Igor Sysoev67f88e92004-03-12 16:57:08 +00001565#endif
1566
Igor Sysoev865c1502003-11-30 20:03:18 +00001567 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http cleanup fd: %d",
1568 cleanup[i].data.file.fd);
1569
Igor Sysoevc2bba092003-11-28 17:41:47 +00001570 if (ngx_close_file(cleanup[i].data.file.fd) == NGX_FILE_ERROR) {
Igor Sysoev865c1502003-11-30 20:03:18 +00001571 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
Igor Sysoevc2bba092003-11-28 17:41:47 +00001572 ngx_close_file_n " \"%s\" failed",
1573 cleanup[i].data.file.name);
1574 }
1575 }
1576
Igor Sysoev865c1502003-11-30 20:03:18 +00001577 /* STUB */
Igor Sysoevd581fd52003-05-13 16:02:32 +00001578 if (r->file.fd != NGX_INVALID_FILE) {
1579 if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
Igor Sysoev865c1502003-11-30 20:03:18 +00001580 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
Igor Sysoevd581fd52003-05-13 16:02:32 +00001581 ngx_close_file_n " \"%s\" failed", r->file.name.data);
1582 }
1583 }
1584
1585 /* ctx->url was allocated from r->pool */
Igor Sysoev865c1502003-11-30 20:03:18 +00001586 ctx = log->data;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001587 ctx->url = NULL;
1588
1589 ngx_destroy_pool(r->pool);
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001590
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001591 return;
Igor Sysoevd581fd52003-05-13 16:02:32 +00001592}
1593
1594
1595void ngx_http_close_connection(ngx_connection_t *c)
Igor Sysoev6b863e32003-05-12 15:52:24 +00001596{
Igor Sysoeve04084c2004-01-26 08:52:49 +00001597 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
Igor Sysoev54498db2004-02-11 17:08:49 +00001598 "close http connection: %d", c->fd);
Igor Sysoev6b863e32003-05-12 15:52:24 +00001599
Igor Sysoevd581fd52003-05-13 16:02:32 +00001600 if (c->pool == NULL) {
Igor Sysoev6b863e32003-05-12 15:52:24 +00001601 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
1602 return;
1603 }
1604
1605 if (c->read->timer_set) {
1606 ngx_del_timer(c->read);
Igor Sysoev6b863e32003-05-12 15:52:24 +00001607 }
1608
Igor Sysoev6b863e32003-05-12 15:52:24 +00001609 if (c->write->timer_set) {
1610 ngx_del_timer(c->write);
Igor Sysoev6b863e32003-05-12 15:52:24 +00001611 }
1612
Igor Sysoev6253ca12003-05-27 12:18:54 +00001613 if (ngx_del_conn) {
Igor Sysoev22a7c502004-02-17 21:11:27 +00001614 ngx_del_conn(c, NGX_CLOSE_EVENT);
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001615
1616 } else {
Igor Sysoev3d540612004-04-13 15:08:48 +00001617 if (c->read->active || c->read->posted || c->read->disabled) {
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001618 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
1619 }
1620
Igor Sysoev3d540612004-04-13 15:08:48 +00001621 if (c->write->active || c->write->posted || c->write->disabled) {
Igor Sysoev6a1cc902003-05-22 15:23:47 +00001622 ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
1623 }
Igor Sysoev6b863e32003-05-12 15:52:24 +00001624 }
1625
1626 if (ngx_close_socket(c->fd) == -1) {
1627 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
1628 ngx_close_socket_n " failed");
1629 }
1630
Igor Sysoev10a543a2004-03-16 07:10:12 +00001631 c->fd = (ngx_socket_t) -1;
Igor Sysoev3b30a902003-12-25 20:26:58 +00001632 c->data = NULL;
Igor Sysoev6b863e32003-05-12 15:52:24 +00001633
1634 ngx_destroy_pool(c->pool);
Igor Sysoevb3e73d82003-10-10 15:10:50 +00001635
1636 return;
Igor Sysoev2ba1ee02002-10-04 17:58:04 +00001637}
1638
1639
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001640static void ngx_http_client_error(ngx_http_request_t *r,
1641 int client_error, int error)
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001642{
1643 ngx_http_log_ctx_t *ctx;
1644
1645 ctx = r->connection->log->data;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001646
1647 if (error == NGX_HTTP_REQUEST_TIME_OUT) {
1648 ngx_log_error(NGX_LOG_INFO, r->connection->log, NGX_ETIMEDOUT,
1649 "client timed out");
1650 ngx_http_close_request(r, error);
1651 ngx_http_close_connection(r->connection);
1652 return;
1653 }
1654
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001655 r->connection->log->handler = NULL;
1656
1657 if (ctx->url) {
Igor Sysoev89690bf2004-03-23 06:01:52 +00001658 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Igor Sysoev3b30a902003-12-25 20:26:58 +00001659 client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR],
1660 ctx->client, ctx->url);
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001661
1662 } else {
Igor Sysoev3d58f8c2004-01-08 08:47:17 +00001663 if (error == NGX_HTTP_REQUEST_URI_TOO_LARGE) {
1664 r->request_line.len = r->header_in->end - r->request_start;
1665 r->request_line.data = r->request_start;
1666 }
1667
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001668 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Igor Sysoev3b30a902003-12-25 20:26:58 +00001669 client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR],
1670 ctx->client);
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001671 }
1672
1673 r->connection->log->handler = ngx_http_log_error;
Igor Sysoev0a280a32003-10-12 16:49:16 +00001674
1675 ngx_http_finalize_request(r, error);
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001676}
1677
1678
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001679static size_t ngx_http_log_error(void *data, char *buf, size_t len)
1680{
Igor Sysoev160d7742003-11-19 16:26:41 +00001681 ngx_http_log_ctx_t *ctx = data;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +00001682
Igor Sysoev7578ec92003-06-02 15:24:30 +00001683 if (ctx->action && ctx->url) {
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001684 return ngx_snprintf(buf, len, " while %s, client: %s, URL: %s",
1685 ctx->action, ctx->client, ctx->url);
Igor Sysoev7578ec92003-06-02 15:24:30 +00001686
1687 } else if (ctx->action == NULL && ctx->url) {
1688 return ngx_snprintf(buf, len, ", client: %s, URL: %s",
1689 ctx->client, ctx->url);
1690
Igor Sysoevdc479b42003-03-20 16:09:44 +00001691 } else {
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001692 return ngx_snprintf(buf, len, " while %s, client: %s",
1693 ctx->action, ctx->client);
Igor Sysoevdc479b42003-03-20 16:09:44 +00001694 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00001695}