blob: 76377a4d7b4d36bc9a8c10becde61e6cd705c576 [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>
4#include <ngx_string.h>
Igor Sysoeva58e3ca2002-09-02 14:48:24 +00005#include <ngx_files.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00006#include <ngx_log.h>
7#include <ngx_alloc.h>
Igor Sysoeva0bb31f2002-12-02 16:09:40 +00008#include <ngx_array.h>
9#include <ngx_table.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000010#include <ngx_hunk.h>
11#include <ngx_connection.h>
Igor Sysoevfcce8d52003-01-23 18:47:54 +000012#include <ngx_event.h>
13#include <ngx_event_timer.h>
Igor Sysoev42feecb2002-12-15 06:25:09 +000014#include <ngx_inet.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000015#include <ngx_http.h>
Igor Sysoeve0268b92002-09-11 15:18:33 +000016#include <ngx_http_config.h>
Igor Sysoev4e9393a2003-01-09 05:36:00 +000017#include <ngx_http_core_module.h>
Igor Sysoev73009772003-02-06 17:21:13 +000018#include <ngx_http_output_filter.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000019
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000020
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000021static int ngx_http_init_request(ngx_event_t *ev);
Igor Sysoevdc479b42003-03-20 16:09:44 +000022static int ngx_http_process_request(ngx_event_t *ev);
Igor Sysoev016b8522002-08-29 16:59:54 +000023static int ngx_http_process_request_line(ngx_http_request_t *r);
Igor Sysoevb0869052002-12-10 18:05:12 +000024static int ngx_http_process_request_headers(ngx_http_request_t *r);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000025static int ngx_http_process_request_header_line(ngx_http_request_t *r);
Igor Sysoevdc479b42003-03-20 16:09:44 +000026static int ngx_http_request_handler(ngx_http_request_t *r, int error);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000027
28static int ngx_http_writer(ngx_event_t *ev);
Igor Sysoev42feecb2002-12-15 06:25:09 +000029static int ngx_http_block_read(ngx_event_t *ev);
30static int ngx_http_read_discarded_body(ngx_event_t *ev);
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +000031static int ngx_http_set_keepalive(ngx_http_request_t *r);
Igor Sysoev1af7c822002-09-13 14:47:42 +000032static int ngx_http_keepalive_handler(ngx_event_t *ev);
Igor Sysoev42feecb2002-12-15 06:25:09 +000033static int ngx_http_set_lingering_close(ngx_http_request_t *r);
34static int ngx_http_lingering_close_handler(ngx_event_t *ev);
Igor Sysoev3a40d482002-09-12 14:42:29 +000035
Igor Sysoev2ba1ee02002-10-04 17:58:04 +000036static int ngx_http_close_connection(ngx_event_t *ev);
Igor Sysoevdc479b42003-03-20 16:09:44 +000037static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err);
Igor Sysoev0ad17c02002-08-26 15:18:19 +000038static size_t ngx_http_log_error(void *data, char *buf, size_t len);
39
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000040
Igor Sysoev0ad17c02002-08-26 15:18:19 +000041
Igor Sysoev016b8522002-08-29 16:59:54 +000042static char *header_errors[] = {
43 "client %s sent invalid method",
44 "client %s sent invalid request",
Igor Sysoev1af7c822002-09-13 14:47:42 +000045 "client %s sent too long URI",
Igor Sysoev6a644c62003-03-04 06:33:48 +000046 "client %s sent HEAD method in HTTP/0.9 request",
47
48 "client %s sent invalid header, URL: %s",
49 "client %s sent too long header line, URL: %s",
50 "client %s sent HTTP/1.1 request without \"Host\" header, URL: %s"
Igor Sysoev016b8522002-08-29 16:59:54 +000051};
52
53
Igor Sysoev6a644c62003-03-04 06:33:48 +000054
Igor Sysoeva0bb31f2002-12-02 16:09:40 +000055static ngx_http_header_t headers_in[] = {
Igor Sysoevdc479b42003-03-20 16:09:44 +000056 { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host) },
57 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection) },
58 { ngx_string("If-Modified-Since"),
59 offsetof(ngx_http_headers_in_t,if_modified_since) },
Igor Sysoeva0bb31f2002-12-02 16:09:40 +000060
Igor Sysoevdc479b42003-03-20 16:09:44 +000061 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) },
Igor Sysoeva0bb31f2002-12-02 16:09:40 +000062
Igor Sysoevdc479b42003-03-20 16:09:44 +000063 { ngx_null_string, 0 }
Igor Sysoeva0bb31f2002-12-02 16:09:40 +000064};
65
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000066
67int ngx_http_init_connection(ngx_connection_t *c)
68{
Igor Sysoevdc479b42003-03-20 16:09:44 +000069 ngx_event_t *rev;
Igor Sysoev0ad17c02002-08-26 15:18:19 +000070 ngx_http_log_ctx_t *ctx;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000071
Igor Sysoevdc479b42003-03-20 16:09:44 +000072 rev = c->read;
73 rev->event_handler = ngx_http_init_request;
Igor Sysoev2ba1ee02002-10-04 17:58:04 +000074
Igor Sysoevdc479b42003-03-20 16:09:44 +000075 rev->close_handler = ngx_http_close_connection;
Igor Sysoev2ba1ee02002-10-04 17:58:04 +000076 c->write->close_handler = ngx_http_close_connection;
77
Igor Sysoev4e9393a2003-01-09 05:36:00 +000078 ngx_test_null(c->addr_text.data, ngx_palloc(c->pool, c->addr_text_max_len),
Igor Sysoev0ad17c02002-08-26 15:18:19 +000079 NGX_ERROR);
Igor Sysoevb0869052002-12-10 18:05:12 +000080
Igor Sysoev86de4cb2003-01-30 07:28:09 +000081 c->addr_text.len = ngx_sock_ntop(c->family, c->sockaddr,
Igor Sysoev4e9393a2003-01-09 05:36:00 +000082 c->addr_text.data, c->addr_text_max_len);
Igor Sysoev86de4cb2003-01-30 07:28:09 +000083
84 if (c->addr_text.len == 0) {
85 return NGX_ERROR;
86 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +000087
88 ngx_test_null(ctx, ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t)),
89 NGX_ERROR);
Igor Sysoevb0869052002-12-10 18:05:12 +000090 ctx->client = c->addr_text.data;
Igor Sysoev0ad17c02002-08-26 15:18:19 +000091 ctx->action = "reading client request line";
92 c->log->data = ctx;
93 c->log->handler = ngx_http_log_error;
94
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000095#if (HAVE_DEFERRED_ACCEPT)
Igor Sysoev73009772003-02-06 17:21:13 +000096
Igor Sysoevdc479b42003-03-20 16:09:44 +000097 if (rev->ready) {
98 return ngx_http_init_request(rev);
Igor Sysoev016b8522002-08-29 16:59:54 +000099 }
Igor Sysoev73009772003-02-06 17:21:13 +0000100
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000101#endif
Igor Sysoev9b25d692003-01-26 21:08:14 +0000102
Igor Sysoevdc479b42003-03-20 16:09:44 +0000103 ngx_add_timer(rev, c->post_accept_timeout);
104 rev->timer_set = 1;
Igor Sysoev9b25d692003-01-26 21:08:14 +0000105
106#if (USE_KQUEUE)
107
Igor Sysoevdc479b42003-03-20 16:09:44 +0000108 return ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000109
110#else
111
Igor Sysoevdc479b42003-03-20 16:09:44 +0000112 /* kqueue */
Igor Sysoev73009772003-02-06 17:21:13 +0000113
Igor Sysoev9b25d692003-01-26 21:08:14 +0000114 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000115 return ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000116 }
Igor Sysoev73009772003-02-06 17:21:13 +0000117
Igor Sysoevdc479b42003-03-20 16:09:44 +0000118 /* aio, iocp, epoll */
Igor Sysoev9b25d692003-01-26 21:08:14 +0000119
Igor Sysoevdc479b42003-03-20 16:09:44 +0000120 if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
121 return ngx_http_init_request(rev);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000122 }
Igor Sysoev73009772003-02-06 17:21:13 +0000123
Igor Sysoev73009772003-02-06 17:21:13 +0000124 /* select, poll, /dev/poll */
Igor Sysoev9b25d692003-01-26 21:08:14 +0000125
Igor Sysoevdc479b42003-03-20 16:09:44 +0000126 return ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000127
128#endif /* USE_KQUEUE */
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000129}
130
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000131
Igor Sysoevdc479b42003-03-20 16:09:44 +0000132static int ngx_http_init_request(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000133{
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000134 ngx_connection_t *c;
135 ngx_http_request_t *r;
136 ngx_http_conf_ctx_t *ctx;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000137
Igor Sysoevdc479b42003-03-20 16:09:44 +0000138 c = (ngx_connection_t *) rev->data;
Igor Sysoevad22e012003-01-15 07:02:27 +0000139 c->sent = 0;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000140
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000141 ngx_test_null(r, ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)),
142 NGX_ERROR);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000143
144 c->data = r;
145 r->connection = c;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000146 r->file.fd = NGX_INVALID_FILE;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000147
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000148 if (c->buffer == NULL) {
149 ngx_test_null(c->buffer,
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000150 ngx_create_temp_hunk(c->pool,
151 ngx_http_client_header_buffer_size,
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000152 0, 0),
153 NGX_ERROR);
154 } else {
155 r->header_read = 1;
156 }
157
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000158 r->pipeline = c->pipeline;
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000159 r->header_in = c->buffer;
160
Igor Sysoevdc479b42003-03-20 16:09:44 +0000161 ngx_test_null(r->pool, ngx_create_pool(ngx_http_request_pool_size, c->log),
Igor Sysoev90ace682003-03-12 17:32:22 +0000162 NGX_ERROR);
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000163
Igor Sysoev207ed5a2002-12-26 16:26:23 +0000164 ngx_test_null(r->ctx,
165 ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module),
Igor Sysoevdc479b42003-03-20 16:09:44 +0000166 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR));
Igor Sysoeve0268b92002-09-11 15:18:33 +0000167
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000168 ctx = (ngx_http_conf_ctx_t *) c->ctx;
169 r->srv_conf = ctx->srv_conf;
170 r->loc_conf = ctx->loc_conf;
171
Igor Sysoev42feecb2002-12-15 06:25:09 +0000172 r->headers_out.headers = ngx_create_table(r->pool, 10);
173 r->headers_out.content_length = -1;
174 r->headers_out.last_modified_time = -1;
175
Igor Sysoevdc479b42003-03-20 16:09:44 +0000176 rev->event_handler = ngx_http_process_request;
Igor Sysoev016b8522002-08-29 16:59:54 +0000177 r->state_handler = ngx_http_process_request_line;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000178
Igor Sysoevdc479b42003-03-20 16:09:44 +0000179 return ngx_http_process_request(rev);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000180}
181
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000182
Igor Sysoevdc479b42003-03-20 16:09:44 +0000183static int ngx_http_process_request(ngx_event_t *rev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000184{
Igor Sysoevdc479b42003-03-20 16:09:44 +0000185 int n, rc;
Igor Sysoev9b25d692003-01-26 21:08:14 +0000186 ngx_connection_t *c;
187 ngx_http_request_t *r;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000188 ngx_http_log_ctx_t *lcx;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000189
Igor Sysoevdc479b42003-03-20 16:09:44 +0000190 c = (ngx_connection_t *) rev->data;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000191 r = (ngx_http_request_t *) c->data;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000192
Igor Sysoevdc479b42003-03-20 16:09:44 +0000193 ngx_log_debug(c->log, "http process request");
194
195 if (rev->timedout) {
196 return ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
197 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000198
Igor Sysoev016b8522002-08-29 16:59:54 +0000199 do {
Igor Sysoev016b8522002-08-29 16:59:54 +0000200
Igor Sysoev73009772003-02-06 17:21:13 +0000201 if (r->header_read) {
202 r->header_read = 0;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000203 ngx_log_debug(c->log, "http preread %d" _
Igor Sysoevb7387572003-03-11 20:38:13 +0000204 r->header_in->last - r->header_in->pos);
Igor Sysoev016b8522002-08-29 16:59:54 +0000205
Igor Sysoev73009772003-02-06 17:21:13 +0000206 } else {
Igor Sysoevb7387572003-03-11 20:38:13 +0000207 n = ngx_event_recv(c, r->header_in->last,
208 r->header_in->end - r->header_in->last);
Igor Sysoev73009772003-02-06 17:21:13 +0000209
210 if (n == NGX_AGAIN) {
211 if (!r->header_timeout_set) {
212
Igor Sysoevdc479b42003-03-20 16:09:44 +0000213 if (rev->timer_set) {
214 ngx_del_timer(rev);
Igor Sysoev73009772003-02-06 17:21:13 +0000215 } else {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000216 rev->timer_set = 1;
Igor Sysoev73009772003-02-06 17:21:13 +0000217 }
218
Igor Sysoevdc479b42003-03-20 16:09:44 +0000219 ngx_add_timer(rev, ngx_http_client_header_timeout);
Igor Sysoev73009772003-02-06 17:21:13 +0000220 r->header_timeout_set = 1;
221 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000222
Igor Sysoev73009772003-02-06 17:21:13 +0000223 return NGX_AGAIN;
224 }
225
Igor Sysoevb7387572003-03-11 20:38:13 +0000226 if (n == NGX_ERROR) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000227 return ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoevb7387572003-03-11 20:38:13 +0000228 }
Igor Sysoev73009772003-02-06 17:21:13 +0000229
Igor Sysoevdc479b42003-03-20 16:09:44 +0000230 ngx_log_debug(c->log, "http read %d" _ n);
Igor Sysoev73009772003-02-06 17:21:13 +0000231
232 if (n == 0) {
233 ngx_log_error(NGX_LOG_INFO, c->log, 0,
Igor Sysoevdc479b42003-03-20 16:09:44 +0000234 "client closed prematurely connection");
235 return ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev73009772003-02-06 17:21:13 +0000236 }
237
Igor Sysoevb7387572003-03-11 20:38:13 +0000238 r->header_in->last += n;
Igor Sysoev73009772003-02-06 17:21:13 +0000239 }
240
Igor Sysoev0dad6292003-03-05 17:30:51 +0000241 /* the state_handlers are called in the following order:
Igor Sysoev73009772003-02-06 17:21:13 +0000242 ngx_http_process_request_line(r)
243 ngx_http_process_request_headers(r) */
244
245 do {
246 rc = (r->state_handler)(r);
247
Igor Sysoevb7387572003-03-11 20:38:13 +0000248 } while (rc == NGX_AGAIN && r->header_in->pos < r->header_in->last);
Igor Sysoev73009772003-02-06 17:21:13 +0000249
Igor Sysoevdc479b42003-03-20 16:09:44 +0000250 } while (rc == NGX_AGAIN
251 && (rev->ready || ngx_event_flags & NGX_HAVE_AIO_EVENT));
Igor Sysoevb7387572003-03-11 20:38:13 +0000252
Igor Sysoevdc479b42003-03-20 16:09:44 +0000253 if (rc >= NGX_OK) {
Igor Sysoevb7387572003-03-11 20:38:13 +0000254
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000255 /* HTTP header done */
Igor Sysoev016b8522002-08-29 16:59:54 +0000256
Igor Sysoevdc479b42003-03-20 16:09:44 +0000257 rev->event_handler = ngx_http_block_read;
258
259 if (rc != NGX_OK) {
260 return ngx_http_finalize_request(r, rc);
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000261 }
262
Igor Sysoevdc479b42003-03-20 16:09:44 +0000263 lcx = r->connection->log->data;
264 lcx->action = "processing client request";
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000265
Igor Sysoevdc479b42003-03-20 16:09:44 +0000266 rc = ngx_http_handler(r);
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000267
Igor Sysoevdc479b42003-03-20 16:09:44 +0000268 /* a handler is still busy */
269 if (rc == NGX_BUSY) {
270 return rc;
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000271 }
272
Igor Sysoevdc479b42003-03-20 16:09:44 +0000273 if (rc == NGX_ERROR) {
274 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
275 }
276
277 return ngx_http_finalize_request(r, rc);
278
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000279 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000280
281 /* NGX_AGAIN */
282
283 if (!r->header_timeout_set) {
284
285 if (rev->timer_set) {
286 ngx_del_timer(rev);
287 } else {
288 rev->timer_set = 1;
289 }
290
291 ngx_add_timer(rev, ngx_http_client_header_timeout);
292 r->header_timeout_set = 1;
293 }
294
295 return rc;
Igor Sysoev016b8522002-08-29 16:59:54 +0000296}
297
Igor Sysoev1af7c822002-09-13 14:47:42 +0000298
Igor Sysoev016b8522002-08-29 16:59:54 +0000299static int ngx_http_process_request_line(ngx_http_request_t *r)
300{
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000301 int rc, offset;
Igor Sysoev2ba1ee02002-10-04 17:58:04 +0000302 ngx_connection_t *c;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000303 ngx_http_log_ctx_t *lcx;
Igor Sysoev016b8522002-08-29 16:59:54 +0000304
305 rc = ngx_read_http_request_line(r);
306
Igor Sysoev2ba1ee02002-10-04 17:58:04 +0000307 c = r->connection;
308
Igor Sysoev0dad6292003-03-05 17:30:51 +0000309 /* a request line has been parsed successfully */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000310
Igor Sysoev016b8522002-08-29 16:59:54 +0000311 if (rc == NGX_OK) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000312
Igor Sysoev6a644c62003-03-04 06:33:48 +0000313 /* copy URI */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000314
315 if (r->args_start) {
316 r->uri.len = r->args_start - 1 - r->uri_start;
317 } else {
318 r->uri.len = r->uri_end - r->uri_start;
319 }
320
Igor Sysoevb0869052002-12-10 18:05:12 +0000321 ngx_test_null(r->uri.data, ngx_palloc(r->pool, r->uri.len + 1),
Igor Sysoevdc479b42003-03-20 16:09:44 +0000322 NGX_HTTP_INTERNAL_SERVER_ERROR);
323
Igor Sysoevb0869052002-12-10 18:05:12 +0000324 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1);
Igor Sysoev016b8522002-08-29 16:59:54 +0000325
Igor Sysoevdc479b42003-03-20 16:09:44 +0000326 r->request_line.len = r->request_end - r->request_start;
327
Igor Sysoevb7387572003-03-11 20:38:13 +0000328 /* if the large client headers are enabled then
Igor Sysoev0dad6292003-03-05 17:30:51 +0000329 we need to copy a request line */
Igor Sysoev2d0d9092002-12-03 15:45:38 +0000330
Igor Sysoev6a644c62003-03-04 06:33:48 +0000331 if (ngx_http_large_client_header) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000332
Igor Sysoev6a644c62003-03-04 06:33:48 +0000333 ngx_test_null(r->request_line.data,
334 ngx_palloc(r->pool, r->request_line.len + 1),
Igor Sysoevdc479b42003-03-20 16:09:44 +0000335 NGX_HTTP_INTERNAL_SERVER_ERROR);
336
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000337 ngx_cpystrn(r->request_line.data, r->request_start,
Igor Sysoev6a644c62003-03-04 06:33:48 +0000338 r->request_line.len + 1);
339
340 } else {
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000341 r->request_line.data = r->request_start;
Igor Sysoev6a644c62003-03-04 06:33:48 +0000342 r->request_line.data[r->request_line.len] = '\0';
343 }
344
345 /* copy URI extention if it exists */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000346
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000347 if (r->uri_ext) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000348 if (r->args_start) {
349 r->exten.len = r->args_start - 1 - r->uri_ext;
350 } else {
351 r->exten.len = r->uri_end - r->uri_ext;
352 }
353
Igor Sysoevb0869052002-12-10 18:05:12 +0000354 ngx_test_null(r->exten.data,
355 ngx_palloc(r->pool, r->exten.len + 1),
Igor Sysoevdc479b42003-03-20 16:09:44 +0000356 NGX_HTTP_INTERNAL_SERVER_ERROR);
357
Igor Sysoevb0869052002-12-10 18:05:12 +0000358 ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000359 }
360
Igor Sysoevdc479b42003-03-20 16:09:44 +0000361 /* copy URI arguments if they exist */
362
363 if (r->args_start && r->uri_end > r->args_start) {
364 r->args.len = r->uri_end - r->args_start;
365
366 ngx_test_null(r->args.data,
367 ngx_palloc(r->pool, r->args.len + 1),
368 NGX_HTTP_INTERNAL_SERVER_ERROR);
369
370 ngx_cpystrn(r->args.data, r->args_start, r->args.len + 1);
371 }
372
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000373#if 1
374 if (r->exten.data == NULL) {
375 r->exten.data = "";
376 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000377 if (r->args.data == NULL) {
378 r->args.data = "";
379 }
380 ngx_log_debug(r->connection->log, "HTTP: %d, %d, '%s', '%s', '%s'" _
Igor Sysoevb0869052002-12-10 18:05:12 +0000381 r->method _ r->http_version _
Igor Sysoevdc479b42003-03-20 16:09:44 +0000382 r->uri.data _ r->exten.data _ r->args.data);
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000383 if (r->exten.data[0] == '\0') {
384 r->exten.data = NULL;
385 }
Igor Sysoevdc479b42003-03-20 16:09:44 +0000386 if (r->args.data[0] == '\0') {
387 r->args.data = NULL;
388 }
Igor Sysoev295bb632002-12-23 18:22:18 +0000389#endif
Igor Sysoev016b8522002-08-29 16:59:54 +0000390
Igor Sysoevdc479b42003-03-20 16:09:44 +0000391 lcx = r->connection->log->data;
392
Igor Sysoev6a644c62003-03-04 06:33:48 +0000393 if (ngx_http_url_in_error_log) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000394 ngx_test_null(lcx->url,
Igor Sysoev6a644c62003-03-04 06:33:48 +0000395 ngx_palloc(r->pool, r->uri_end - r->uri_start + 1),
Igor Sysoevdc479b42003-03-20 16:09:44 +0000396 NGX_HTTP_INTERNAL_SERVER_ERROR);
397
398 ngx_cpystrn(lcx->url, r->uri_start, r->uri_end - r->uri_start + 1);
Igor Sysoev6a644c62003-03-04 06:33:48 +0000399 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000400
Igor Sysoev0dad6292003-03-05 17:30:51 +0000401 /* if we need to parse the headers then return NGX_AGAIN
402 becuase of HTTP/0.9 has no headers so return NGX_OK */
403
404 if (r->http_version == NGX_HTTP_VERSION_9) {
405 r->state_handler = NULL;
Igor Sysoev6a644c62003-03-04 06:33:48 +0000406 return NGX_OK;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000407 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000408
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000409 r->headers_in.headers = ngx_create_table(r->pool, 10);
410
Igor Sysoevb0869052002-12-10 18:05:12 +0000411 r->state_handler = ngx_http_process_request_headers;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000412 lcx->action = "reading client request headers";
413
414 if (ngx_http_large_client_header
415 && r->header_in->pos == r->header_in->last)
416 {
417 r->header_in->pos = r->header_in->last = r->header_in->start;
418 }
Igor Sysoev016b8522002-08-29 16:59:54 +0000419
Igor Sysoevb0869052002-12-10 18:05:12 +0000420 return NGX_AGAIN;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000421
422 /* there was error while a request line parsing */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000423
Igor Sysoev0dad6292003-03-05 17:30:51 +0000424 } else if (rc != NGX_AGAIN) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000425 ngx_http_header_parse_error(r, rc);
426 return NGX_HTTP_BAD_REQUEST;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000427 }
428
Igor Sysoev0dad6292003-03-05 17:30:51 +0000429 /* NGX_AGAIN: a request line parsing is still not complete */
430
Igor Sysoevb7387572003-03-11 20:38:13 +0000431 if (r->header_in->last == r->header_in->end) {
Igor Sysoev1af7c822002-09-13 14:47:42 +0000432
Igor Sysoev0dad6292003-03-05 17:30:51 +0000433 /* If it's a pipelined request and a request line is not complete
434 then we need to copy it to the start of r->header_in hunk.
Igor Sysoevb7387572003-03-11 20:38:13 +0000435 We need to copy it here only if the large client headers
436 are enabled otherwise a request line had been already copied
Igor Sysoev0dad6292003-03-05 17:30:51 +0000437 to the start of r->header_in hunk in ngx_http_set_keepalive() */
438
439 if (ngx_http_large_client_header) {
440 offset = r->request_start - r->header_in->start;
441
442 if (offset == 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000443 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI);
444 return NGX_HTTP_REQUEST_URI_TOO_LARGE;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000445 }
446
447 ngx_memcpy(r->header_in->start, r->request_start,
Igor Sysoevb7387572003-03-11 20:38:13 +0000448 r->header_in->last - r->request_start);
Igor Sysoev0dad6292003-03-05 17:30:51 +0000449
Igor Sysoevb7387572003-03-11 20:38:13 +0000450 r->header_in->pos -= offset;
451 r->header_in->last -= offset;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000452 r->request_start = r->header_in->start;
453 r->request_end -= offset;
454 r->uri_start -= offset;
455 r->uri_end -= offset;
456 if (r->uri_ext) {
457 r->uri_ext -= offset;
458 }
459 if (r->args_start) {
460 r->args_start -= offset;
461 }
462
463 } else {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000464 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI);
465 return NGX_HTTP_REQUEST_URI_TOO_LARGE;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000466 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000467 }
468
Igor Sysoev0dad6292003-03-05 17:30:51 +0000469 return NGX_AGAIN;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000470}
471
Igor Sysoev1af7c822002-09-13 14:47:42 +0000472
Igor Sysoevb0869052002-12-10 18:05:12 +0000473static int ngx_http_process_request_headers(ngx_http_request_t *r)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000474{
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000475 int rc, offset;
Igor Sysoev73009772003-02-06 17:21:13 +0000476 size_t len;
Igor Sysoev016b8522002-08-29 16:59:54 +0000477 ngx_http_log_ctx_t *ctx;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000478
Igor Sysoev016b8522002-08-29 16:59:54 +0000479 for ( ;; ) {
Igor Sysoevb0869052002-12-10 18:05:12 +0000480 rc = ngx_read_http_header_line(r, r->header_in);
Igor Sysoev016b8522002-08-29 16:59:54 +0000481
Igor Sysoev0dad6292003-03-05 17:30:51 +0000482 /* a header line has been parsed successfully */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000483
Igor Sysoev0dad6292003-03-05 17:30:51 +0000484 if (rc == NGX_OK) {
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000485 if (ngx_http_process_request_header_line(r) == NGX_ERROR) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000486 return NGX_HTTP_INTERNAL_SERVER_ERROR;
487 }
488
489 if (ngx_http_large_client_header
490 && r->header_in->pos == r->header_in->last)
491 {
492 r->header_in->pos = r->header_in->last = r->header_in->start;
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000493 }
494
495 return NGX_AGAIN;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000496
Igor Sysoevb7387572003-03-11 20:38:13 +0000497 /* a whole header has been parsed successfully */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000498
Igor Sysoev1af7c822002-09-13 14:47:42 +0000499 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000500 ngx_log_debug(r->connection->log, "HTTP header done");
Igor Sysoev42feecb2002-12-15 06:25:09 +0000501
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000502 if (r->headers_in.host) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000503 for (len = 0; len < r->headers_in.host->value.len; len++) {
504 if (r->headers_in.host->value.data[len] == ':') {
505 break;
506 }
507 }
508 r->headers_in.host_name_len = len;
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000509
Igor Sysoev42feecb2002-12-15 06:25:09 +0000510 } else {
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000511 if (r->http_version > NGX_HTTP_VERSION_10) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000512 ngx_http_header_parse_error(r,
513 NGX_HTTP_PARSE_NO_HOST_HEADER);
514 return NGX_HTTP_BAD_REQUEST;
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000515 }
516 r->headers_in.host_name_len = 0;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000517 }
Igor Sysoev016b8522002-08-29 16:59:54 +0000518
Igor Sysoev0dad6292003-03-05 17:30:51 +0000519 r->state_handler = NULL;
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000520 return NGX_OK;
Igor Sysoev6a644c62003-03-04 06:33:48 +0000521
Igor Sysoev0dad6292003-03-05 17:30:51 +0000522 /* there was error while a header line parsing */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000523
Igor Sysoev0dad6292003-03-05 17:30:51 +0000524 } else if (rc != NGX_AGAIN) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000525 ngx_http_header_parse_error(r, rc);
526 return NGX_HTTP_BAD_REQUEST;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000527 }
528
529 /* NGX_AGAIN: a header line parsing is still not complete */
530
Igor Sysoevb7387572003-03-11 20:38:13 +0000531 if (r->header_in->last == r->header_in->end) {
Igor Sysoev0dad6292003-03-05 17:30:51 +0000532
Igor Sysoevb7387572003-03-11 20:38:13 +0000533 /* if the large client headers are enabled then
Igor Sysoev0dad6292003-03-05 17:30:51 +0000534 we need to compact r->header_in hunk */
535
536 if (ngx_http_large_client_header) {
537 offset = r->header_name_start - r->header_in->start;
538
539 if (offset == 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000540 ngx_http_header_parse_error(r,
541 NGX_HTTP_PARSE_TOO_LONG_HEADER);
542 return NGX_HTTP_BAD_REQUEST;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000543 }
544
545 ngx_memcpy(r->header_in->start, r->header_name_start,
Igor Sysoevb7387572003-03-11 20:38:13 +0000546 r->header_in->last - r->header_name_start);
Igor Sysoev0dad6292003-03-05 17:30:51 +0000547
Igor Sysoevb7387572003-03-11 20:38:13 +0000548 r->header_in->last -= offset;
549 r->header_in->pos -= offset;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000550 r->header_name_start = r->header_in->start;
551 r->header_name_end -= offset;
552 r->header_start -= offset;
553 r->header_end -= offset;
554
555 } else {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000556 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER);
557 return NGX_HTTP_BAD_REQUEST;
Igor Sysoev0dad6292003-03-05 17:30:51 +0000558 }
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000559
Igor Sysoev016b8522002-08-29 16:59:54 +0000560 }
Igor Sysoev0dad6292003-03-05 17:30:51 +0000561
562 return NGX_AGAIN;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000563 }
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000564}
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000565
Igor Sysoev1af7c822002-09-13 14:47:42 +0000566
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000567static int ngx_http_process_request_header_line(ngx_http_request_t *r)
568{
Igor Sysoevdc479b42003-03-20 16:09:44 +0000569 int i;
570 ngx_table_elt_t *h;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000571
Igor Sysoev2d0d9092002-12-03 15:45:38 +0000572 ngx_test_null(h, ngx_push_table(r->headers_in.headers), NGX_ERROR);
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000573
Igor Sysoev6a644c62003-03-04 06:33:48 +0000574 h->key.len = r->header_name_end - r->header_name_start;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000575 h->value.len = r->header_end - r->header_start;
Igor Sysoev6a644c62003-03-04 06:33:48 +0000576
Igor Sysoevdc479b42003-03-20 16:09:44 +0000577 /* if the large client headers are enabled then
578 we need to copy the header name and value */
579
Igor Sysoev6a644c62003-03-04 06:33:48 +0000580 if (ngx_http_large_client_header) {
581 ngx_test_null(h->key.data, ngx_palloc(r->pool, h->key.len + 1),
582 NGX_ERROR);
583 ngx_test_null(h->value.data, ngx_palloc(r->pool, h->value.len + 1),
584 NGX_ERROR);
585 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
586 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
587
588 } else {
589 h->key.data = r->header_name_start;
590 h->key.data[h->key.len] = '\0';
591 h->value.data = r->header_start;
592 h->value.data[h->value.len] = '\0';
593 }
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000594
Igor Sysoevdc479b42003-03-20 16:09:44 +0000595 for (i = 0; headers_in[i].name.len != 0; i++) {
596 if (headers_in[i].name.len != h->key.len) {
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000597 continue;
598 }
599
Igor Sysoevdc479b42003-03-20 16:09:44 +0000600 if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) {
Igor Sysoeva19a85e2003-01-28 15:56:37 +0000601 *((ngx_table_elt_t **)
602 ((char *) &r->headers_in + headers_in[i].offset)) = h;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000603 }
604 }
605
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000606 ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000607 h->key.data _ h->value.data);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000608
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000609 return NGX_OK;
610}
611
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000612
Igor Sysoevdc479b42003-03-20 16:09:44 +0000613int ngx_http_finalize_request(ngx_http_request_t *r, int error)
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000614{
Igor Sysoevdc479b42003-03-20 16:09:44 +0000615 int rc, event;
616 ngx_msec_t timeout;
617 ngx_event_t *rev, *wev;
618 ngx_http_core_loc_conf_t *lcf;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000619
Igor Sysoevdc479b42003-03-20 16:09:44 +0000620 rc = error;
Igor Sysoev9b25d692003-01-26 21:08:14 +0000621
Igor Sysoevdc479b42003-03-20 16:09:44 +0000622 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
Igor Sysoevb0869052002-12-10 18:05:12 +0000623
Igor Sysoevdc479b42003-03-20 16:09:44 +0000624 rev = r->connection->read;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000625
Igor Sysoevdc479b42003-03-20 16:09:44 +0000626 if (rev->timer_set) {
627 ngx_del_timer(rev);
Igor Sysoev96f83772002-09-07 10:14:25 +0000628 } else {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000629 rev->timer_set = 1;
Igor Sysoev96f83772002-09-07 10:14:25 +0000630 }
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000631
Igor Sysoevdc479b42003-03-20 16:09:44 +0000632 rc = ngx_http_special_response_handler(r, rc);
633 }
634
635 /* a handler has done its work completely */
636
637 if (rc == NGX_OK) {
638
639 if (r->keepalive != 0) {
640 return ngx_http_set_keepalive(r);
641 }
642
643 if (r->lingering_close) {
644 return ngx_http_set_lingering_close(r);
645 }
646
647 return ngx_http_close_request(r, 0);
648 }
649
650 /* NGX_AGAIN: a handler has done its work
651 but the transfer is still not completed */
652
653 lcf = (ngx_http_core_loc_conf_t *)
654 ngx_http_get_module_loc_conf(r->main ? r->main : r,
655 ngx_http_core_module);
656 wev = r->connection->write;
657 wev->event_handler = ngx_http_writer;
658 wev->timer_set = 1;
659 ngx_add_timer(wev, lcf->send_timeout);
Igor Sysoev73009772003-02-06 17:21:13 +0000660
661#if (USE_KQUEUE)
662
Igor Sysoev6a644c62003-03-04 06:33:48 +0000663#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */
Igor Sysoevdc479b42003-03-20 16:09:44 +0000664 wev->lowat = lcf->send_lowat;
Igor Sysoev6a644c62003-03-04 06:33:48 +0000665#endif
666
Igor Sysoevdc479b42003-03-20 16:09:44 +0000667 if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) == NGX_ERROR) {
668 return ngx_http_close_request(r, 0);
669 }
Igor Sysoev73009772003-02-06 17:21:13 +0000670
Igor Sysoevdc479b42003-03-20 16:09:44 +0000671 return rc;
Igor Sysoev73009772003-02-06 17:21:13 +0000672
673#else
674
Igor Sysoevdc479b42003-03-20 16:09:44 +0000675 /* aio, iocp, epoll */
Igor Sysoev73009772003-02-06 17:21:13 +0000676
Igor Sysoevdc479b42003-03-20 16:09:44 +0000677 if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
678 return rc;
679 }
Igor Sysoev73009772003-02-06 17:21:13 +0000680
Igor Sysoev6a644c62003-03-04 06:33:48 +0000681#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */
682
Igor Sysoevdc479b42003-03-20 16:09:44 +0000683 if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) {
684 wev->lowat = lcf->send_lowat;
685 }
Igor Sysoev6a644c62003-03-04 06:33:48 +0000686
687#endif
688
Igor Sysoevdc479b42003-03-20 16:09:44 +0000689 /* kqueue */
Igor Sysoev73009772003-02-06 17:21:13 +0000690
Igor Sysoevdc479b42003-03-20 16:09:44 +0000691 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
692 event = NGX_CLEAR_EVENT;
Igor Sysoev73009772003-02-06 17:21:13 +0000693
Igor Sysoevdc479b42003-03-20 16:09:44 +0000694 /* select, poll, /dev/poll */
Igor Sysoev73009772003-02-06 17:21:13 +0000695
Igor Sysoevdc479b42003-03-20 16:09:44 +0000696 } else {
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +0000697 event = NGX_LEVEL_EVENT;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000698 }
Igor Sysoev73009772003-02-06 17:21:13 +0000699
Igor Sysoevdc479b42003-03-20 16:09:44 +0000700 if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) {
701 return ngx_http_close_request(r, 0);
702 }
Igor Sysoev73009772003-02-06 17:21:13 +0000703
Igor Sysoevdc479b42003-03-20 16:09:44 +0000704 return rc;
Igor Sysoev73009772003-02-06 17:21:13 +0000705
706#endif /* USE_KQUEUE */
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000707}
708
Igor Sysoevb0869052002-12-10 18:05:12 +0000709
Igor Sysoevdc479b42003-03-20 16:09:44 +0000710static int ngx_http_writer(ngx_event_t *wev)
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000711{
Igor Sysoevdc479b42003-03-20 16:09:44 +0000712 int rc;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000713 ngx_msec_t timeout;
714 ngx_connection_t *c;
715 ngx_http_request_t *r;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000716 ngx_http_core_loc_conf_t *lcf;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000717
Igor Sysoevdc479b42003-03-20 16:09:44 +0000718 c = (ngx_connection_t *) wev->data;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000719 r = (ngx_http_request_t *) c->data;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000720
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000721 rc = ngx_http_output_filter(r, NULL);
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000722
Igor Sysoevdc479b42003-03-20 16:09:44 +0000723 ngx_log_debug(c->log, "output filter in writer: %d" _ rc);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000724
725 if (rc == NGX_AGAIN) {
726
Igor Sysoevdc479b42003-03-20 16:09:44 +0000727 lcf = (ngx_http_core_loc_conf_t *)
728 ngx_http_get_module_loc_conf(r->main ? r->main : r,
729 ngx_http_core_module);
730 if (wev->timer_set) {
731 ngx_del_timer(wev);
732 } else {
733 wev->timer_set = 1;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000734 }
735
Igor Sysoevdc479b42003-03-20 16:09:44 +0000736 ngx_add_timer(wev, lcf->send_timeout);
737
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000738 return rc;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000739 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000740
741 if (rc == NGX_ERROR)
742 return rc;
743
744 /* rc == NGX_OK */
745
Igor Sysoevdc479b42003-03-20 16:09:44 +0000746 ngx_log_debug(c->log, "http writer done");
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000747
Igor Sysoevdc479b42003-03-20 16:09:44 +0000748 if (r->keepalive != 0) {
749 return ngx_http_set_keepalive(r);
Igor Sysoev3a40d482002-09-12 14:42:29 +0000750 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000751
Igor Sysoevdc479b42003-03-20 16:09:44 +0000752 if (r->lingering_close) {
753 return ngx_http_set_lingering_close(r);
754 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000755
Igor Sysoevdc479b42003-03-20 16:09:44 +0000756 return ngx_http_close_request(r, 0);
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000757}
758
Igor Sysoevb0869052002-12-10 18:05:12 +0000759
Igor Sysoev42feecb2002-12-15 06:25:09 +0000760static int ngx_http_block_read(ngx_event_t *ev)
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000761{
Igor Sysoev42feecb2002-12-15 06:25:09 +0000762 ngx_log_debug(ev->log, "http read blocked");
763
Igor Sysoev73009772003-02-06 17:21:13 +0000764 /* aio does not call this handler */
765
766#if (USE_KQUEUE)
767
768 return NGX_OK;
769
770#else
771
Igor Sysoevb7387572003-03-11 20:38:13 +0000772 if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { /* select, poll, /dev/poll */
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000773 ev->blocked = 1;
774 return ngx_del_event(ev, NGX_READ_EVENT, 0);
Igor Sysoev73009772003-02-06 17:21:13 +0000775
Igor Sysoevb7387572003-03-11 20:38:13 +0000776 } else { /* kqueue, epoll */
Igor Sysoev73009772003-02-06 17:21:13 +0000777 return NGX_OK;
778 }
779
Igor Sysoev73009772003-02-06 17:21:13 +0000780#endif /* USE_KQUEUE */
Igor Sysoev42feecb2002-12-15 06:25:09 +0000781}
782
783
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +0000784/* TODO */
Igor Sysoev42feecb2002-12-15 06:25:09 +0000785int ngx_http_discard_body(ngx_http_request_t *r)
786{
Igor Sysoev9b25d692003-01-26 21:08:14 +0000787 ngx_event_t *ev;
788
789 ev = r->connection->read;
790
Igor Sysoev42feecb2002-12-15 06:25:09 +0000791 ngx_log_debug(r->connection->log, "set discard body");
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000792
Igor Sysoev9b25d692003-01-26 21:08:14 +0000793 if (ev->timer_set) {
794 ngx_del_timer(ev);
795 ev->timer_set = 0;
796 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000797
Igor Sysoev73009772003-02-06 17:21:13 +0000798 if (r->client_content_length) {
Igor Sysoev9b25d692003-01-26 21:08:14 +0000799 ev->event_handler = ngx_http_read_discarded_body;
Igor Sysoev73009772003-02-06 17:21:13 +0000800 /* if blocked - read */
801 /* else add timer */
802 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000803
804 return NGX_OK;
805}
806
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000807
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +0000808/* TODO */
Igor Sysoev42feecb2002-12-15 06:25:09 +0000809static int ngx_http_read_discarded_body(ngx_event_t *ev)
810{
811 size_t size;
812 ssize_t n;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000813 ngx_connection_t *c;
814 ngx_http_request_t *r;
815 ngx_http_core_loc_conf_t *lcf;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000816
817 ngx_log_debug(ev->log, "http read discarded body");
818
Igor Sysoevdc479b42003-03-20 16:09:44 +0000819 if (ev->timedout) {
Igor Sysoev42feecb2002-12-15 06:25:09 +0000820 return NGX_ERROR;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000821 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000822
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000823 c = (ngx_connection_t *) ev->data;
824 r = (ngx_http_request_t *) c->data;
825
826 lcf = (ngx_http_core_loc_conf_t *)
Igor Sysoevdc479b42003-03-20 16:09:44 +0000827 ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000828
Igor Sysoevdc479b42003-03-20 16:09:44 +0000829 if (r->discarded_buffer == NULL) {
Igor Sysoev42feecb2002-12-15 06:25:09 +0000830 ngx_test_null(r->discarded_buffer,
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000831 ngx_palloc(r->pool, lcf->discarded_buffer_size),
Igor Sysoev42feecb2002-12-15 06:25:09 +0000832 NGX_ERROR);
Igor Sysoevdc479b42003-03-20 16:09:44 +0000833 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000834
835 size = r->client_content_length;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000836 if (size > lcf->discarded_buffer_size) {
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000837 size = lcf->discarded_buffer_size;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000838 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000839
840 n = ngx_event_recv(c, r->discarded_buffer, size);
Igor Sysoevdc479b42003-03-20 16:09:44 +0000841 if (n == NGX_ERROR) {
Igor Sysoev42feecb2002-12-15 06:25:09 +0000842 return NGX_ERROR;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000843 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000844
Igor Sysoevdc479b42003-03-20 16:09:44 +0000845 if (n == NGX_AGAIN) {
Igor Sysoev42feecb2002-12-15 06:25:09 +0000846 return NGX_OK;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000847 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000848
849 r->client_content_length -= n;
850 /* XXX: what if r->client_content_length == 0 ? */
851 return NGX_OK;
852}
853
854
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +0000855static int ngx_http_set_keepalive(ngx_http_request_t *r)
856{
Igor Sysoevb7387572003-03-11 20:38:13 +0000857 int len, blocked;
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000858 ngx_hunk_t *h;
859 ngx_event_t *rev, *wev;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +0000860 ngx_connection_t *c;
Igor Sysoev6a644c62003-03-04 06:33:48 +0000861 ngx_http_log_ctx_t *ctx;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +0000862
863 c = (ngx_connection_t *) r->connection;
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000864 rev = c->read;
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +0000865
Igor Sysoev6a644c62003-03-04 06:33:48 +0000866 ctx = (ngx_http_log_ctx_t *) c->log->data;
867 ctx->action = "closing request";
Igor Sysoevdc479b42003-03-20 16:09:44 +0000868 ngx_http_close_request(r, 0);
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +0000869
Igor Sysoevb7387572003-03-11 20:38:13 +0000870 if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
871 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
872 return NGX_ERROR;
873 }
874 blocked = 1;
875 rev->blocked = 0;
876
877 } else {
878 blocked = 0;
879 }
880
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000881 h = c->buffer;
882
883 /* pipelined request */
Igor Sysoevb7387572003-03-11 20:38:13 +0000884 if (h->pos < h->last) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000885
Igor Sysoevdc479b42003-03-20 16:09:44 +0000886 /* We do not know here whether a pipelined request is complete
887 so if the large client headers are not enabled
Igor Sysoevb7387572003-03-11 20:38:13 +0000888 we need to copy the data to the start of c->buffer.
889 This copy should be rare because clients that support
890 pipelined requests (Mozilla 1.x, Opera 6.x) are still rare */
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000891
892 if (!ngx_http_large_client_header) {
Igor Sysoevb7387572003-03-11 20:38:13 +0000893 len = h->last - h->pos;
894 ngx_memcpy(h->start, h->pos, len);
895 h->pos = h->start;
896 h->last = h->start + len;
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000897 }
898
899 c->pipeline = 1;
900 ctx->action = "reading client pipelined request line";
901 return ngx_http_init_request(rev);
902 }
903
904 c->pipeline = 0;
905
Igor Sysoevb7387572003-03-11 20:38:13 +0000906 h->pos = h->last = h->start;
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000907 rev->event_handler = ngx_http_keepalive_handler;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000908 wev = c->write;
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000909
Igor Sysoevb7387572003-03-11 20:38:13 +0000910 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000911 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
912 return NGX_ERROR;
913 }
914 }
915
Igor Sysoev6a644c62003-03-04 06:33:48 +0000916 ctx->action = "keepalive";
917
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +0000918#if (HAVE_AIO_EVENT) /* aio, iocp */
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000919
Igor Sysoevb7387572003-03-11 20:38:13 +0000920 if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) || blocked) {
921 return ngx_http_keepalive_handler(rev);
922 }
923
924#else
925
926 if (blocked) {
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000927 return ngx_http_keepalive_handler(rev);
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +0000928 }
Igor Sysoev3d062ad2003-03-05 06:37:42 +0000929
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +0000930#endif
931
932 return NGX_OK;
933}
934
935
Igor Sysoevdc479b42003-03-20 16:09:44 +0000936static int ngx_http_keepalive_handler(ngx_event_t *rev)
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000937{
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000938 ssize_t n;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000939 ngx_connection_t *c;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000940 ngx_http_log_ctx_t *lctx;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000941
Igor Sysoevdc479b42003-03-20 16:09:44 +0000942 c = (ngx_connection_t *) rev->data;
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000943
Igor Sysoevdc479b42003-03-20 16:09:44 +0000944 ngx_log_debug(c->log, "http keepalive handler");
Igor Sysoev1af7c822002-09-13 14:47:42 +0000945
Igor Sysoevdc479b42003-03-20 16:09:44 +0000946 if (rev->timedout) {
Igor Sysoev1af7c822002-09-13 14:47:42 +0000947 return NGX_DONE;
Igor Sysoev90ace682003-03-12 17:32:22 +0000948 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000949
Igor Sysoevdc479b42003-03-20 16:09:44 +0000950 /* MSIE closes a keepalive connection with RST flag
Igor Sysoevb7387572003-03-11 20:38:13 +0000951 so we ignore ECONNRESET here */
952
Igor Sysoevdc479b42003-03-20 16:09:44 +0000953 rev->ignore_econnreset = 1;
Igor Sysoevb7387572003-03-11 20:38:13 +0000954 ngx_set_socket_errno(0);
955 n = ngx_event_recv(c, c->buffer->last, c->buffer->end - c->buffer->last);
Igor Sysoevdc479b42003-03-20 16:09:44 +0000956 rev->ignore_econnreset = 0;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000957
Igor Sysoev90ace682003-03-12 17:32:22 +0000958 if (n == NGX_AGAIN || n == NGX_ERROR) {
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000959 return n;
Igor Sysoev90ace682003-03-12 17:32:22 +0000960 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000961
Igor Sysoevdc479b42003-03-20 16:09:44 +0000962 lctx = (ngx_http_log_ctx_t *) rev->log->data;
963 rev->log->handler = NULL;
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000964
965 if (n == 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +0000966 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
967 "client %s closed keepalive connection", lctx->client);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000968 return NGX_DONE;
969 }
970
Igor Sysoevb7387572003-03-11 20:38:13 +0000971 c->buffer->last += n;
Igor Sysoevdc479b42003-03-20 16:09:44 +0000972 rev->log->handler = ngx_http_log_error;
973 lctx->action = "reading client request line";
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000974
Igor Sysoevdc479b42003-03-20 16:09:44 +0000975 return ngx_http_init_request(rev);
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000976}
977
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000978
Igor Sysoev42feecb2002-12-15 06:25:09 +0000979static int ngx_http_set_lingering_close(ngx_http_request_t *r)
Igor Sysoev1af7c822002-09-13 14:47:42 +0000980{
Igor Sysoevdc479b42003-03-20 16:09:44 +0000981 ngx_event_t *rev;
Igor Sysoevb7387572003-03-11 20:38:13 +0000982 ngx_connection_t *c;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000983 ngx_http_core_loc_conf_t *lcf;
984
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +0000985 c = r->connection;
Igor Sysoevb7387572003-03-11 20:38:13 +0000986 rev = c->read;
Igor Sysoev9b25d692003-01-26 21:08:14 +0000987
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000988 lcf = (ngx_http_core_loc_conf_t *)
Igor Sysoevdc479b42003-03-20 16:09:44 +0000989 ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000990
Igor Sysoevb7387572003-03-11 20:38:13 +0000991 r->lingering_time = ngx_time() + lcf->lingering_time / 1000;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000992 r->connection->read->event_handler = ngx_http_lingering_close_handler;
993
Igor Sysoevb7387572003-03-11 20:38:13 +0000994 if (rev->timer_set) {
995 ngx_del_timer(rev);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000996 } else {
Igor Sysoevb7387572003-03-11 20:38:13 +0000997 rev->timer_set = 1;
Igor Sysoev9b25d692003-01-26 21:08:14 +0000998 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000999
Igor Sysoevb7387572003-03-11 20:38:13 +00001000 ngx_add_timer(rev, lcf->lingering_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +00001001
Igor Sysoevb7387572003-03-11 20:38:13 +00001002 if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
1003 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
Igor Sysoevdc479b42003-03-20 16:09:44 +00001004 return ngx_http_close_request(r, 0);
Igor Sysoevb7387572003-03-11 20:38:13 +00001005 }
Igor Sysoevb7387572003-03-11 20:38:13 +00001006 rev->blocked = 0;
Igor Sysoevb7387572003-03-11 20:38:13 +00001007 }
1008
Igor Sysoevdc479b42003-03-20 16:09:44 +00001009#if !(USE_KQUEUE)
1010
1011 if (c->write->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
1012 if (ngx_del_event(c->write, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
1013 return ngx_http_close_request(r, 0);
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001014 }
Igor Sysoev42feecb2002-12-15 06:25:09 +00001015 }
1016
Igor Sysoevdc479b42003-03-20 16:09:44 +00001017#endif
1018
Igor Sysoevb7387572003-03-11 20:38:13 +00001019 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
1020 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
Igor Sysoev42feecb2002-12-15 06:25:09 +00001021 ngx_shutdown_socket_n " failed");
Igor Sysoevdc479b42003-03-20 16:09:44 +00001022 return ngx_http_close_request(r, 0);
Igor Sysoev42feecb2002-12-15 06:25:09 +00001023 }
1024
Igor Sysoevdc479b42003-03-20 16:09:44 +00001025#if (USE_KQUEUE)
Igor Sysoevb7387572003-03-11 20:38:13 +00001026
Igor Sysoevdc479b42003-03-20 16:09:44 +00001027 if (rev->ready) {
Igor Sysoevb7387572003-03-11 20:38:13 +00001028 return ngx_http_lingering_close_handler(rev);
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001029 }
Igor Sysoevb7387572003-03-11 20:38:13 +00001030
1031#else
1032
Igor Sysoevdc479b42003-03-20 16:09:44 +00001033 if (rev->ready || (ngx_event_flags & NGX_HAVE_AIO_EVENT)) {
Igor Sysoevb7387572003-03-11 20:38:13 +00001034 return ngx_http_lingering_close_handler(rev);
1035 }
1036
Igor Sysoev1e7ec9d2003-02-11 07:14:40 +00001037#endif
1038
Igor Sysoevb7387572003-03-11 20:38:13 +00001039 return NGX_OK;
Igor Sysoev42feecb2002-12-15 06:25:09 +00001040}
1041
1042
Igor Sysoevdc479b42003-03-20 16:09:44 +00001043static int ngx_http_lingering_close_handler(ngx_event_t *rev)
Igor Sysoev42feecb2002-12-15 06:25:09 +00001044{
Igor Sysoevdc479b42003-03-20 16:09:44 +00001045 ssize_t n;
1046 ngx_msec_t timer;
1047 ngx_connection_t *c;
1048 ngx_http_request_t *r;
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001049 ngx_http_core_loc_conf_t *lcf;
Igor Sysoev1af7c822002-09-13 14:47:42 +00001050
Igor Sysoevdc479b42003-03-20 16:09:44 +00001051 c = (ngx_connection_t *) rev->data;
Igor Sysoev86de4cb2003-01-30 07:28:09 +00001052 r = (ngx_http_request_t *) c->data;
1053
Igor Sysoevdc479b42003-03-20 16:09:44 +00001054 ngx_log_debug(c->log, "http lingering close handler");
1055
1056 if (rev->timedout) {
1057 return ngx_http_close_request(r, 0);
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001058 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001059
Igor Sysoev1af7c822002-09-13 14:47:42 +00001060 timer = r->lingering_time - ngx_time();
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001061 if (timer <= 0) {
Igor Sysoevdc479b42003-03-20 16:09:44 +00001062 return ngx_http_close_request(r, 0);
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001063 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001064
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001065 lcf = (ngx_http_core_loc_conf_t *)
Igor Sysoevdc479b42003-03-20 16:09:44 +00001066 ngx_http_get_module_loc_conf(r, ngx_http_core_module);
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001067
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001068 if (r->discarded_buffer == NULL) {
Igor Sysoevb7387572003-03-11 20:38:13 +00001069
1070 /* TODO: r->header_in->start (if large headers are enabled)
1071 or the end of parsed header (otherwise)
1072 instead of r->header_in->last */
1073
1074 if ((size_t)(r->header_in->end - r->header_in->last)
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001075 >= lcf->discarded_buffer_size) {
Igor Sysoevb7387572003-03-11 20:38:13 +00001076 r->discarded_buffer = r->header_in->last;
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001077
1078 } else {
1079 ngx_test_null(r->discarded_buffer,
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001080 ngx_palloc(c->pool, lcf->discarded_buffer_size),
Igor Sysoevdc479b42003-03-20 16:09:44 +00001081 ngx_http_close_request(r, 0));
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001082 }
1083 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001084
Igor Sysoevdc479b42003-03-20 16:09:44 +00001085 do {
1086 n = ngx_event_recv(c, r->discarded_buffer, lcf->discarded_buffer_size);
Igor Sysoev1af7c822002-09-13 14:47:42 +00001087
Igor Sysoevdc479b42003-03-20 16:09:44 +00001088 ngx_log_debug(c->log, "lingering read: %d" _ n);
Igor Sysoev1af7c822002-09-13 14:47:42 +00001089
Igor Sysoevdc479b42003-03-20 16:09:44 +00001090 if (n == NGX_ERROR || n == 0) {
1091 return ngx_http_close_request(r, 0);
1092 }
1093
1094 } while (rev->ready);
Igor Sysoev1af7c822002-09-13 14:47:42 +00001095
Igor Sysoev682bf8e2002-09-16 15:01:44 +00001096 timer *= 1000;
Igor Sysoev4e9393a2003-01-09 05:36:00 +00001097 if (timer > lcf->lingering_timeout) {
1098 timer = lcf->lingering_timeout;
Igor Sysoev0d2bda52002-12-24 07:09:57 +00001099 }
Igor Sysoev1af7c822002-09-13 14:47:42 +00001100
Igor Sysoevdc479b42003-03-20 16:09:44 +00001101 if (rev->timer_set) {
1102 ngx_del_timer(rev);
Igor Sysoev9b25d692003-01-26 21:08:14 +00001103 } else {
Igor Sysoevdc479b42003-03-20 16:09:44 +00001104 rev->timer_set = 1;
Igor Sysoev9b25d692003-01-26 21:08:14 +00001105 }
Igor Sysoevdc479b42003-03-20 16:09:44 +00001106 ngx_add_timer(rev, timer);
Igor Sysoev1af7c822002-09-13 14:47:42 +00001107
1108 return NGX_OK;
1109}
1110
Igor Sysoev2b542382002-08-20 14:48:28 +00001111
Igor Sysoev2ba1ee02002-10-04 17:58:04 +00001112static int ngx_http_close_connection(ngx_event_t *ev)
1113{
Igor Sysoev2ba1ee02002-10-04 17:58:04 +00001114 return ngx_event_close_connection(ev);
1115}
1116
1117
Igor Sysoevdc479b42003-03-20 16:09:44 +00001118static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err)
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001119{
1120 ngx_http_log_ctx_t *ctx;
1121
1122 ctx = r->connection->log->data;
1123 r->connection->log->handler = NULL;
1124
1125 if (ctx->url) {
1126 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1127 header_errors[parse_err - NGX_HTTP_PARSE_INVALID_METHOD],
1128 ctx->client, ctx->url);
1129
1130 } else {
1131 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1132 header_errors[parse_err - NGX_HTTP_PARSE_INVALID_METHOD],
1133 ctx->client);
1134 }
1135
1136 r->connection->log->handler = ngx_http_log_error;
Igor Sysoev3d062ad2003-03-05 06:37:42 +00001137}
1138
1139
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001140static size_t ngx_http_log_error(void *data, char *buf, size_t len)
1141{
1142 ngx_http_log_ctx_t *ctx = (ngx_http_log_ctx_t *) data;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +00001143
Igor Sysoevdc479b42003-03-20 16:09:44 +00001144 if (ctx->url) {
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001145 return ngx_snprintf(buf, len, " while %s, client: %s, URL: %s",
1146 ctx->action, ctx->client, ctx->url);
Igor Sysoevdc479b42003-03-20 16:09:44 +00001147 } else {
Igor Sysoev0ad17c02002-08-26 15:18:19 +00001148 return ngx_snprintf(buf, len, " while %s, client: %s",
1149 ctx->action, ctx->client);
Igor Sysoevdc479b42003-03-20 16:09:44 +00001150 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00001151}