blob: 5856ebff61e664aeb56a67c4f722ecd42191bde1 [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 Sysoev6de5c2c2002-08-06 16:39:45 +000018
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000019/* STUB */
20#include <ngx_http_output_filter.h>
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000021int ngx_http_static_handler(ngx_http_request_t *r);
Igor Sysoeve0268b92002-09-11 15:18:33 +000022int ngx_http_index_handler(ngx_http_request_t *r);
Igor Sysoeva0bb31f2002-12-02 16:09:40 +000023int ngx_http_proxy_handler(ngx_http_request_t *r);
Igor Sysoevb0869052002-12-10 18:05:12 +000024/**/
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000025
Igor Sysoev0ad17c02002-08-26 15:18:19 +000026int ngx_http_init_connection(ngx_connection_t *c);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000027
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000028static int ngx_http_init_request(ngx_event_t *ev);
Igor Sysoevb0869052002-12-10 18:05:12 +000029static int ngx_http_process_request_header(ngx_event_t *ev);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000030
Igor Sysoev016b8522002-08-29 16:59:54 +000031static int ngx_http_process_request_line(ngx_http_request_t *r);
Igor Sysoevb0869052002-12-10 18:05:12 +000032static int ngx_http_process_request_headers(ngx_http_request_t *r);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000033static int ngx_http_process_request_header_line(ngx_http_request_t *r);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000034
Igor Sysoev42feecb2002-12-15 06:25:09 +000035static int ngx_http_event_request_handler(ngx_http_request_t *r);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000036
37static int ngx_http_writer(ngx_event_t *ev);
Igor Sysoev42feecb2002-12-15 06:25:09 +000038static int ngx_http_block_read(ngx_event_t *ev);
39static int ngx_http_read_discarded_body(ngx_event_t *ev);
Igor Sysoev1af7c822002-09-13 14:47:42 +000040static int ngx_http_keepalive_handler(ngx_event_t *ev);
Igor Sysoev42feecb2002-12-15 06:25:09 +000041static int ngx_http_set_lingering_close(ngx_http_request_t *r);
42static int ngx_http_lingering_close_handler(ngx_event_t *ev);
Igor Sysoev3a40d482002-09-12 14:42:29 +000043
Igor Sysoevb0869052002-12-10 18:05:12 +000044#if 0
45int ngx_http_special_response(ngx_http_request_t *r, int error);
46int ngx_http_redirect(ngx_http_request_t *r, int redirect);
47int ngx_http_error(ngx_http_request_t *r, int error);
48int ngx_http_close_request(ngx_http_request_t *r);
49#endif
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000050
Igor Sysoev2ba1ee02002-10-04 17:58:04 +000051static int ngx_http_close_connection(ngx_event_t *ev);
Igor Sysoev0ad17c02002-08-26 15:18:19 +000052static size_t ngx_http_log_error(void *data, char *buf, size_t len);
53
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000054
Igor Sysoev0ad17c02002-08-26 15:18:19 +000055
Igor Sysoev016b8522002-08-29 16:59:54 +000056static char *header_errors[] = {
57 "client %s sent invalid method",
58 "client %s sent invalid request",
Igor Sysoev1af7c822002-09-13 14:47:42 +000059 "client %s sent too long URI",
Igor Sysoev016b8522002-08-29 16:59:54 +000060 "client %s sent HEAD method in HTTP/0.9 request"
61};
62
63
Igor Sysoeva0bb31f2002-12-02 16:09:40 +000064static ngx_http_header_t headers_in[] = {
65 { 4, "Host", offsetof(ngx_http_headers_in_t, host) },
66 { 10, "Connection", offsetof(ngx_http_headers_in_t, connection) },
Igor Sysoev42feecb2002-12-15 06:25:09 +000067 { 17, "If-Modified-Since",
68 offsetof(ngx_http_headers_in_t,if_modified_since) },
Igor Sysoeva0bb31f2002-12-02 16:09:40 +000069
70 { 10, "User-Agent", offsetof(ngx_http_headers_in_t, user_agent) },
71
72 { 0, NULL, 0 }
73};
74
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000075
76int ngx_http_init_connection(ngx_connection_t *c)
77{
Igor Sysoev0ad17c02002-08-26 15:18:19 +000078 ngx_event_t *ev;
79 struct sockaddr *addr;
80 ngx_http_log_ctx_t *ctx;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000081
82 ev = c->read;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000083 ev->event_handler = ngx_http_init_request;
Igor Sysoev2ba1ee02002-10-04 17:58:04 +000084
Igor Sysoev1af7c822002-09-13 14:47:42 +000085 ngx_test_null(c->pool,
Igor Sysoev4e9393a2003-01-09 05:36:00 +000086 ngx_create_pool(ngx_http_connection_pool_size, ev->log),
Igor Sysoev1af7c822002-09-13 14:47:42 +000087 NGX_ERROR);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000088
Igor Sysoev2ba1ee02002-10-04 17:58:04 +000089 ngx_test_null(c->requests, ngx_create_array(c->pool, 10, sizeof(char *)),
90 NGX_ERROR);
91
92 ev->close_handler = ngx_http_close_connection;
93 c->write->close_handler = ngx_http_close_connection;
94
Igor Sysoev0ad17c02002-08-26 15:18:19 +000095 ngx_test_null(addr, ngx_palloc(c->pool, c->socklen), NGX_ERROR);
96 ngx_memcpy(addr, c->sockaddr, c->socklen);
97 c->sockaddr = addr;
98
Igor Sysoev4e9393a2003-01-09 05:36:00 +000099 ngx_test_null(c->addr_text.data, ngx_palloc(c->pool, c->addr_text_max_len),
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000100 NGX_ERROR);
Igor Sysoevb0869052002-12-10 18:05:12 +0000101
Igor Sysoev5518aba2002-12-17 15:48:27 +0000102 c->addr_text.len = ngx_inet_ntop(c->family,
103 (char *)c->sockaddr + c->addr,
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000104 c->addr_text.data, c->addr_text_max_len);
Igor Sysoev88092572002-12-19 07:08:55 +0000105 if (c->addr_text.len == 0)
Igor Sysoev5518aba2002-12-17 15:48:27 +0000106 return NGX_ERROR;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000107
108 ngx_test_null(ctx, ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t)),
109 NGX_ERROR);
Igor Sysoevb0869052002-12-10 18:05:12 +0000110 ctx->client = c->addr_text.data;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000111 ctx->action = "reading client request line";
112 c->log->data = ctx;
113 c->log->handler = ngx_http_log_error;
114
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000115#if (HAVE_DEFERRED_ACCEPT)
Igor Sysoev016b8522002-08-29 16:59:54 +0000116 if (ev->ready) {
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000117 return ngx_http_init_request(ev);
Igor Sysoev016b8522002-08-29 16:59:54 +0000118 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000119#endif
Igor Sysoev9b25d692003-01-26 21:08:14 +0000120
121 ngx_add_timer(ev, c->post_accept_timeout);
122 ev->timer_set = 1;
123
124#if (USE_KQUEUE)
125
126 return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
127
128#else
129
130#if (HAVE_CLEAR_EVENT)
131 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
132 return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
133 }
134#endif
135
136#if (HAVE_AIO_EVENT)
137 if (ngx_event_flags & NGX_HAVE_AIO_EVENT) {
138 return ngx_http_init_request(ev);
139 }
140#endif
141
142 return ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT);
143
144#endif /* USE_KQUEUE */
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000145}
146
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000147
Igor Sysoev1af7c822002-09-13 14:47:42 +0000148static int ngx_http_init_request(ngx_event_t *ev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000149{
Igor Sysoev9b25d692003-01-26 21:08:14 +0000150 ngx_connection_t *c;
151 ngx_http_request_t *r;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000152
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000153 c = (ngx_connection_t *) ev->data;
Igor Sysoevad22e012003-01-15 07:02:27 +0000154 c->sent = 0;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000155
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000156 ngx_test_null(r, ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)),
157 NGX_ERROR);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000158
159 c->data = r;
160 r->connection = c;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000161 r->file.fd = NGX_INVALID_FILE;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000162
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000163 if (c->buffer == NULL) {
164 ngx_test_null(c->buffer,
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000165 ngx_create_temp_hunk(c->pool,
166 ngx_http_client_header_buffer_size,
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000167 0, 0),
168 NGX_ERROR);
169 } else {
170 r->header_read = 1;
171 }
172
173 r->header_in = c->buffer;
174
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000175 ngx_test_null(r->pool, ngx_create_pool(ngx_http_request_pool_size, ev->log),
Igor Sysoev016b8522002-08-29 16:59:54 +0000176 ngx_http_close_request(r));
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000177
Igor Sysoev207ed5a2002-12-26 16:26:23 +0000178 ngx_test_null(r->ctx,
179 ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module),
Igor Sysoeve0268b92002-09-11 15:18:33 +0000180 ngx_http_close_request(r));
181
Igor Sysoev42feecb2002-12-15 06:25:09 +0000182 r->headers_out.headers = ngx_create_table(r->pool, 10);
183 r->headers_out.content_length = -1;
184 r->headers_out.last_modified_time = -1;
185
Igor Sysoevb0869052002-12-10 18:05:12 +0000186 ev->event_handler = ngx_http_process_request_header;
Igor Sysoev016b8522002-08-29 16:59:54 +0000187 r->state_handler = ngx_http_process_request_line;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000188
Igor Sysoevb0869052002-12-10 18:05:12 +0000189 return ngx_http_process_request_header(ev);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000190}
191
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000192
Igor Sysoevb0869052002-12-10 18:05:12 +0000193static int ngx_http_process_request_header(ngx_event_t *ev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000194{
Igor Sysoev9b25d692003-01-26 21:08:14 +0000195 int n, rc;
196 ngx_connection_t *c;
197 ngx_http_request_t *r;
Igor Sysoev1af7c822002-09-13 14:47:42 +0000198 ngx_http_log_ctx_t *ctx;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000199
200 c = (ngx_connection_t *) ev->data;
201 r = (ngx_http_request_t *) c->data;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000202
203 ngx_log_debug(ev->log, "http process request");
204
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000205 if (r->header_read) {
206 r->header_read = 0;
207 ngx_log_debug(ev->log, "http preread %d" _
208 r->header_in->last.mem - r->header_in->pos.mem);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000209
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000210 } else {
211 n = ngx_event_recv(c, r->header_in->last.mem,
212 r->header_in->end - r->header_in->last.mem);
213
214 if (n == NGX_AGAIN) {
Igor Sysoev9b25d692003-01-26 21:08:14 +0000215 if (!r->header_timeout_set) {
216
217 if (ev->timer_set) {
218 ngx_del_timer(ev);
219 } else {
220 ev->timer_set = 1;
221 }
222
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000223 ngx_add_timer(ev, ngx_http_client_header_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000224 r->header_timeout_set = 1;
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000225 }
226 return NGX_AGAIN;
Igor Sysoev016b8522002-08-29 16:59:54 +0000227 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000228
229 if (n == NGX_ERROR)
230 return ngx_http_close_request(r);
231
232 ngx_log_debug(ev->log, "http read %d" _ n);
233
234 if (n == 0) {
Igor Sysoevb0869052002-12-10 18:05:12 +0000235 ngx_log_error(NGX_LOG_INFO, c->log, 0,
236 "client has prematurely closed connection");
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000237 return ngx_http_close_request(r);
238 }
239
240 r->header_in->last.mem += n;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000241 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000242
Igor Sysoev016b8522002-08-29 16:59:54 +0000243 /* state_handlers are called in following order:
244 ngx_http_process_request_line(r)
Igor Sysoevb0869052002-12-10 18:05:12 +0000245 ngx_http_process_request_headers(r) */
Igor Sysoev016b8522002-08-29 16:59:54 +0000246
247 do {
248 rc = (r->state_handler)(r);
249
250 if (rc == NGX_ERROR)
251 return rc;
252
Igor Sysoevb0869052002-12-10 18:05:12 +0000253 } while (rc == NGX_AGAIN && r->header_in->pos.mem < r->header_in->last.mem);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000254
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000255 if (rc == NGX_OK) {
256 /* HTTP header done */
Igor Sysoev016b8522002-08-29 16:59:54 +0000257
Igor Sysoev9b25d692003-01-26 21:08:14 +0000258 if (ev->timer_set) {
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000259 ngx_del_timer(ev);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000260 ev->timer_set = 0;
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000261 }
262
Igor Sysoev42feecb2002-12-15 06:25:09 +0000263 return ngx_http_event_request_handler(r);
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000264
Igor Sysoev9b25d692003-01-26 21:08:14 +0000265 } else { /* NGX_AGAIN */
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000266
Igor Sysoev9b25d692003-01-26 21:08:14 +0000267 if (!r->header_timeout_set) {
268
269 if (ev->timer_set) {
270 ngx_del_timer(ev);
271 } else {
272 ev->timer_set = 1;
273 }
274
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000275 ngx_add_timer(ev, ngx_http_client_header_timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000276 r->header_timeout_set = 1;
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000277 }
278
Igor Sysoevb0869052002-12-10 18:05:12 +0000279 return rc;
Igor Sysoev830c4ce2003-01-24 16:09:40 +0000280 }
Igor Sysoev016b8522002-08-29 16:59:54 +0000281}
282
Igor Sysoev1af7c822002-09-13 14:47:42 +0000283
Igor Sysoev016b8522002-08-29 16:59:54 +0000284static int ngx_http_process_request_line(ngx_http_request_t *r)
285{
Igor Sysoev2ba1ee02002-10-04 17:58:04 +0000286 int rc, len;
287 char **request;
288 ngx_connection_t *c;
Igor Sysoev016b8522002-08-29 16:59:54 +0000289 ngx_http_log_ctx_t *ctx;
290
291 rc = ngx_read_http_request_line(r);
292
Igor Sysoev2ba1ee02002-10-04 17:58:04 +0000293 c = r->connection;
294
Igor Sysoev016b8522002-08-29 16:59:54 +0000295 if (rc == NGX_OK) {
Igor Sysoev42feecb2002-12-15 06:25:09 +0000296 r->uri.len = (r->args_start ? r->args_start - 1 : r->uri_end)
297 - r->uri_start;
Igor Sysoevb0869052002-12-10 18:05:12 +0000298 ngx_test_null(r->uri.data, ngx_palloc(r->pool, r->uri.len + 1),
Igor Sysoev016b8522002-08-29 16:59:54 +0000299 ngx_http_close_request(r));
Igor Sysoevb0869052002-12-10 18:05:12 +0000300 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1);
Igor Sysoev016b8522002-08-29 16:59:54 +0000301
Igor Sysoev2d0d9092002-12-03 15:45:38 +0000302 r->request_line.len = r->request_end - r->header_in->start;
303 ngx_test_null(r->request_line.data,
304 ngx_palloc(r->pool, r->request_line.len + 1),
305 ngx_http_close_request(r));
306 ngx_cpystrn(r->request_line.data, r->header_in->start,
307 r->request_line.len + 1);
308
309 /* TEMP */
Igor Sysoev2ba1ee02002-10-04 17:58:04 +0000310 ngx_test_null(request, ngx_push_array(c->requests),
311 ngx_http_close_request(r));
312
313 if (r->request_end)
314 len = r->request_end - r->header_in->start + 1;
315 else
316 len = 1;
317 c->requests_len += len;
318 ngx_test_null(*request, ngx_palloc(c->pool, len),
319 ngx_http_close_request(r));
320 ngx_cpystrn(*request, r->header_in->start, len);
321
322 ngx_log_debug(c->log, "REQ: '%s'" _ *request);
Igor Sysoev2d0d9092002-12-03 15:45:38 +0000323 /* */
Igor Sysoev2ba1ee02002-10-04 17:58:04 +0000324
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000325 if (r->uri_ext) {
Igor Sysoev42feecb2002-12-15 06:25:09 +0000326 r->exten.len = (r->args_start ? r->args_start - 1 : r->uri_end)
327 - r->uri_ext;
Igor Sysoevb0869052002-12-10 18:05:12 +0000328 ngx_test_null(r->exten.data,
329 ngx_palloc(r->pool, r->exten.len + 1),
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000330 ngx_http_close_request(r));
Igor Sysoevb0869052002-12-10 18:05:12 +0000331 ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000332 }
333
Igor Sysoev295bb632002-12-23 18:22:18 +0000334#if 0
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000335 ngx_log_debug(r->connection->log, "HTTP: %d, %d, %s %s" _
Igor Sysoevb0869052002-12-10 18:05:12 +0000336 r->method _ r->http_version _
337 r->uri.data _ r->exten.data);
Igor Sysoev295bb632002-12-23 18:22:18 +0000338#endif
Igor Sysoev016b8522002-08-29 16:59:54 +0000339
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000340 if (r->http_version == 9)
Igor Sysoevb0869052002-12-10 18:05:12 +0000341 return NGX_OK;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000342
Igor Sysoev1af7c822002-09-13 14:47:42 +0000343 /* TODO: check too long URI - no space for header, compact buffer */
344
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000345 r->headers_in.headers = ngx_create_table(r->pool, 10);
346
Igor Sysoevb0869052002-12-10 18:05:12 +0000347 r->state_handler = ngx_http_process_request_headers;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000348 ctx = r->connection->log->data;
349 ctx->action = "reading client request headers";
Igor Sysoev016b8522002-08-29 16:59:54 +0000350
Igor Sysoevb0869052002-12-10 18:05:12 +0000351 return NGX_AGAIN;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000352 }
353
Igor Sysoev1af7c822002-09-13 14:47:42 +0000354 if (r->header_in->last.mem >= r->header_in->end) {
Igor Sysoevef259d12002-12-06 16:32:33 +0000355 rc = NGX_HTTP_PARSE_TOO_LONG_URI;
Igor Sysoev1af7c822002-09-13 14:47:42 +0000356
357 } else if (rc == NGX_AGAIN) {
358 return NGX_AGAIN;
359 }
360
Igor Sysoev016b8522002-08-29 16:59:54 +0000361 ctx = r->connection->log->data;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000362 r->connection->log->handler = NULL;
Igor Sysoev1af7c822002-09-13 14:47:42 +0000363 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
364 header_errors[rc - NGX_HTTP_PARSE_INVALID_METHOD],
365 ctx->client);
Igor Sysoev016b8522002-08-29 16:59:54 +0000366 r->connection->log->handler = ngx_http_log_error;
367
Igor Sysoev1af7c822002-09-13 14:47:42 +0000368 return ngx_http_error(r, (rc == NGX_HTTP_PARSE_TOO_LONG_URI) ?
369 NGX_HTTP_REQUEST_URI_TOO_LARGE:
370 NGX_HTTP_BAD_REQUEST);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000371}
372
Igor Sysoev1af7c822002-09-13 14:47:42 +0000373
Igor Sysoevb0869052002-12-10 18:05:12 +0000374static int ngx_http_process_request_headers(ngx_http_request_t *r)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000375{
Igor Sysoev016b8522002-08-29 16:59:54 +0000376 int rc;
377 ngx_http_log_ctx_t *ctx;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000378
Igor Sysoev016b8522002-08-29 16:59:54 +0000379 for ( ;; ) {
Igor Sysoevb0869052002-12-10 18:05:12 +0000380 rc = ngx_read_http_header_line(r, r->header_in);
Igor Sysoev016b8522002-08-29 16:59:54 +0000381
Igor Sysoev1af7c822002-09-13 14:47:42 +0000382 /* TODO: check too long header, compact buffer */
383
Igor Sysoev016b8522002-08-29 16:59:54 +0000384 if (rc == NGX_OK) {
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000385 if (ngx_http_process_request_header_line(r) == NGX_ERROR)
386 return ngx_http_error(r, NGX_HTTP_BAD_REQUEST);
387
Igor Sysoev1af7c822002-09-13 14:47:42 +0000388 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000389 ngx_log_debug(r->connection->log, "HTTP header done");
Igor Sysoev42feecb2002-12-15 06:25:09 +0000390
391 if (r->http_version > NGX_HTTP_VERSION_10
392 && r->headers_in.host == NULL)
393 {
394 return ngx_http_error(r, NGX_HTTP_BAD_REQUEST);
395 } else {
396 return NGX_OK;
397 }
Igor Sysoev016b8522002-08-29 16:59:54 +0000398
399 } else if (rc == NGX_AGAIN) {
400 return NGX_AGAIN;
401
Igor Sysoev1af7c822002-09-13 14:47:42 +0000402 } else if (rc == NGX_HTTP_PARSE_INVALID_HEADER) {
Igor Sysoev016b8522002-08-29 16:59:54 +0000403 ctx = r->connection->log->data;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000404 r->connection->log->handler = NULL;
Igor Sysoev1af7c822002-09-13 14:47:42 +0000405 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
Igor Sysoev016b8522002-08-29 16:59:54 +0000406 "client %s sent invalid header", ctx->client);
407 r->connection->log->handler = ngx_http_log_error;
408
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000409 return ngx_http_error(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev016b8522002-08-29 16:59:54 +0000410 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000411 }
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000412}
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000413
Igor Sysoev1af7c822002-09-13 14:47:42 +0000414
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000415static int ngx_http_process_request_header_line(ngx_http_request_t *r)
416{
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000417 int i;
418 ngx_table_elt_t *h;
419
Igor Sysoev2d0d9092002-12-03 15:45:38 +0000420 ngx_test_null(h, ngx_push_table(r->headers_in.headers), NGX_ERROR);
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000421
422 h->key.len = r->header_name_end - r->header_name_start;
423 ngx_test_null(h->key.data, ngx_palloc(r->pool, h->key.len + 1), NGX_ERROR);
424 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
425
426 h->value.len = r->header_end - r->header_start;
427 ngx_test_null(h->value.data, ngx_palloc(r->pool, h->value.len + 1),
428 NGX_ERROR);
429 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
430
431 for (i = 0; headers_in[i].len != 0; i++) {
432 if (headers_in[i].len == h->key.len) {
Igor Sysoevb2620632003-01-10 06:09:20 +0000433 if (ngx_strcasecmp(headers_in[i].data, h->key.data) == 0) {
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000434 *((ngx_table_elt_t **)
435 ((char *) &r->headers_in + headers_in[i].offset)) = h;
436 }
437 }
438 }
439
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000440 ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000441 h->key.data _ h->value.data);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000442
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000443 return NGX_OK;
444}
445
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000446
Igor Sysoev42feecb2002-12-15 06:25:09 +0000447static int ngx_http_event_request_handler(ngx_http_request_t *r)
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000448{
Igor Sysoev9b25d692003-01-26 21:08:14 +0000449 int rc;
450 ngx_msec_t timeout;
451 ngx_event_t *rev, *wev;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000452
Igor Sysoev9b25d692003-01-26 21:08:14 +0000453 rev = r->connection->read;
454 wev = r->connection->write;
455
456 if (rev->timer_set) {
457 ngx_del_timer(rev);
458 rev->timer_set = 0;
459 }
Igor Sysoevb0869052002-12-10 18:05:12 +0000460
461 r->state_handler = NULL;
Igor Sysoev9b25d692003-01-26 21:08:14 +0000462 rev->event_handler = ngx_http_block_read;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000463
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000464 rc = ngx_http_handler(r);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000465
Igor Sysoevef259d12002-12-06 16:32:33 +0000466 /* handler is still busy */
Igor Sysoev6ed07e42002-12-05 16:21:24 +0000467 if (rc == NGX_WAITING)
468 return rc;
469
Igor Sysoevef259d12002-12-06 16:32:33 +0000470 /* handler has done its work but transfer is not completed */
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000471 if (rc == NGX_AGAIN) {
472#if (HAVE_CLEAR_EVENT)
Igor Sysoev9b25d692003-01-26 21:08:14 +0000473 if (ngx_add_event(wev, NGX_WRITE_EVENT,
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000474 NGX_CLEAR_EVENT) == NGX_ERROR) {
475#else
Igor Sysoev9b25d692003-01-26 21:08:14 +0000476 if (ngx_add_event(wev, NGX_WRITE_EVENT,
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000477 NGX_ONESHOT_EVENT) == NGX_ERROR) {
478#endif
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000479 return ngx_http_close_request(r);
480 }
481
Igor Sysoev96f83772002-09-07 10:14:25 +0000482 if (r->connection->sent > 0) {
483 ngx_log_debug(r->connection->log, "sent: " QD_FMT _
484 r->connection->sent);
485 timeout = (ngx_msec_t) (r->connection->sent * 10);
486 ngx_log_debug(r->connection->log, "timeout: %d" _ timeout);
Igor Sysoev9b25d692003-01-26 21:08:14 +0000487 ngx_add_timer(wev, timeout);
Igor Sysoev96f83772002-09-07 10:14:25 +0000488
489 } else {
Igor Sysoev9b25d692003-01-26 21:08:14 +0000490 ngx_add_timer(wev, 10000);
Igor Sysoev96f83772002-09-07 10:14:25 +0000491 }
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000492
Igor Sysoev9b25d692003-01-26 21:08:14 +0000493 wev->event_handler = ngx_http_writer;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000494 return rc;
495 }
496
497 if (rc == NGX_ERROR) {
498 /* log http request */
499 return ngx_http_close_request(r);
500 }
501
502 if (rc >= NGX_HTTP_SPECIAL_RESPONSE)
503 return ngx_http_special_response(r, rc);
504
505 /* rc == NGX_OK */
506
Igor Sysoev3a40d482002-09-12 14:42:29 +0000507 if (!r->keepalive) {
508 if (r->lingering_close) {
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000509 return ngx_http_set_lingering_close(r);
510
Igor Sysoev3a40d482002-09-12 14:42:29 +0000511 } else {
512 return ngx_http_close_request(r);
513 }
514 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000515
516 /* keepalive */
517
518 ngx_http_close_request(r);
519 r->connection->buffer->pos.mem = r->connection->buffer->last.mem
520 = r->connection->buffer->start;
Igor Sysoev9b25d692003-01-26 21:08:14 +0000521 rev->event_handler = ngx_http_keepalive_handler;
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000522}
523
Igor Sysoevb0869052002-12-10 18:05:12 +0000524
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000525static int ngx_http_writer(ngx_event_t *ev)
526{
527 int rc;
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000528 ngx_msec_t timeout;
529 ngx_connection_t *c;
530 ngx_http_request_t *r;
531 ngx_http_core_loc_conf_t *conf;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000532
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000533 c = (ngx_connection_t *) ev->data;
534 r = (ngx_http_request_t *) c->data;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000535
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000536 rc = ngx_http_output_filter(r, NULL);
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000537
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000538 ngx_log_debug(ev->log, "output filter in writer: %d" _ rc);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000539
540 if (rc == NGX_AGAIN) {
541
542 if (c->sent > 0) {
Igor Sysoeva0bb31f2002-12-02 16:09:40 +0000543 conf = (ngx_http_core_loc_conf_t *)
Igor Sysoev207ed5a2002-12-26 16:26:23 +0000544 ngx_http_get_module_loc_conf(r->main ? r->main : r,
545 ngx_http_core_module_ctx);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000546
547 timeout = (ngx_msec_t) (c->sent * conf->send_timeout);
548
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000549 ngx_log_debug(ev->log, "sent: " QD_FMT _ c->sent);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000550 ngx_log_debug(ev->log, "timeout: %d" _ timeout);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000551
Igor Sysoev9b25d692003-01-26 21:08:14 +0000552 if (ev->timer_set) {
553 ngx_del_timer(ev);
554 } else {
555 ev->timer_set = 1;
556 }
557
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000558 ngx_add_timer(ev, timeout);
559 }
560
561 if (ev->oneshot)
Igor Sysoev9b25d692003-01-26 21:08:14 +0000562 if (ngx_add_event(ev, NGX_WRITE_EVENT,
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000563 NGX_ONESHOT_EVENT) == NGX_ERROR) {
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000564 return ngx_http_close_request(r);
565 }
566
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000567 return rc;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000568 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000569
570 if (rc == NGX_ERROR)
571 return rc;
572
573 /* rc == NGX_OK */
574
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000575 ngx_log_debug(ev->log, "http writer done");
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000576
Igor Sysoev3a40d482002-09-12 14:42:29 +0000577 if (!r->keepalive) {
578 if (r->lingering_close) {
Igor Sysoev3a17f242002-12-24 17:30:59 +0000579 return ngx_http_set_lingering_close(r);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000580
Igor Sysoev3a40d482002-09-12 14:42:29 +0000581 } else {
582 return ngx_http_close_request(r);
583 }
584 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000585
Igor Sysoev3a40d482002-09-12 14:42:29 +0000586 /* keepalive */
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000587
Igor Sysoev3a40d482002-09-12 14:42:29 +0000588 ngx_http_close_request(r);
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000589 c->buffer->pos.mem = c->buffer->last.mem = c->buffer->start;
590 c->read->event_handler = ngx_http_keepalive_handler;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000591}
592
Igor Sysoevb0869052002-12-10 18:05:12 +0000593
Igor Sysoev42feecb2002-12-15 06:25:09 +0000594static int ngx_http_block_read(ngx_event_t *ev)
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000595{
Igor Sysoev42feecb2002-12-15 06:25:09 +0000596 ngx_log_debug(ev->log, "http read blocked");
597
598 ev->blocked = 1;
599 return ngx_del_event(ev, NGX_READ_EVENT, 0);
600}
601
602
603int ngx_http_discard_body(ngx_http_request_t *r)
604{
Igor Sysoev9b25d692003-01-26 21:08:14 +0000605 ngx_event_t *ev;
606
607 ev = r->connection->read;
608
Igor Sysoev42feecb2002-12-15 06:25:09 +0000609 ngx_log_debug(r->connection->log, "set discard body");
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000610
Igor Sysoev9b25d692003-01-26 21:08:14 +0000611 if (ev->timer_set) {
612 ngx_del_timer(ev);
613 ev->timer_set = 0;
614 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000615
Igor Sysoev42feecb2002-12-15 06:25:09 +0000616 if (r->client_content_length)
Igor Sysoev9b25d692003-01-26 21:08:14 +0000617 ev->event_handler = ngx_http_read_discarded_body;
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000618
619 return NGX_OK;
620}
621
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000622
Igor Sysoev42feecb2002-12-15 06:25:09 +0000623static int ngx_http_read_discarded_body(ngx_event_t *ev)
624{
625 size_t size;
626 ssize_t n;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000627 ngx_connection_t *c;
628 ngx_http_request_t *r;
629 ngx_http_core_loc_conf_t *lcf;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000630
631 ngx_log_debug(ev->log, "http read discarded body");
632
633 if (ev->timedout)
634 return NGX_ERROR;
635
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000636 c = (ngx_connection_t *) ev->data;
637 r = (ngx_http_request_t *) c->data;
638
639 lcf = (ngx_http_core_loc_conf_t *)
640 ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
641
Igor Sysoev42feecb2002-12-15 06:25:09 +0000642 if (r->discarded_buffer == NULL)
643 ngx_test_null(r->discarded_buffer,
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000644 ngx_palloc(r->pool, lcf->discarded_buffer_size),
Igor Sysoev42feecb2002-12-15 06:25:09 +0000645 NGX_ERROR);
646
647 size = r->client_content_length;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000648 if (size > lcf->discarded_buffer_size)
649 size = lcf->discarded_buffer_size;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000650
651 n = ngx_event_recv(c, r->discarded_buffer, size);
652 if (n == NGX_ERROR)
653 return NGX_ERROR;
654
655 if (n == NGX_AGAIN)
656 return NGX_OK;
657
658 r->client_content_length -= n;
659 /* XXX: what if r->client_content_length == 0 ? */
660 return NGX_OK;
661}
662
663
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000664static int ngx_http_keepalive_handler(ngx_event_t *ev)
665{
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000666 ssize_t n;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000667 ngx_connection_t *c;
668 ngx_http_log_ctx_t *ctx;
669
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000670 c = (ngx_connection_t *) ev->data;
671
Igor Sysoev42feecb2002-12-15 06:25:09 +0000672 ngx_log_debug(ev->log, "http keepalive handler");
Igor Sysoev1af7c822002-09-13 14:47:42 +0000673
674 if (ev->timedout)
675 return NGX_DONE;
676
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000677 n = ngx_event_recv(c, c->buffer->last.mem,
678 c->buffer->end - c->buffer->last.mem);
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000679
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000680 if (n == NGX_AGAIN || n == NGX_ERROR)
681 return n;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000682
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000683 ctx = (ngx_http_log_ctx_t *) ev->log->data;
684 ev->log->handler = NULL;
685
686 if (n == 0) {
687 ngx_log_error(NGX_LOG_INFO, ev->log, 0,
688 "client %s closed keepalive connection", ctx->client);
689 return NGX_DONE;
690 }
691
692 c->buffer->last.mem += n;
693 ev->log->handler = ngx_http_log_error;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000694 ctx->action = "reading client request line";
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000695
696 return ngx_http_init_request(ev);
697}
698
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000699
Igor Sysoev42feecb2002-12-15 06:25:09 +0000700static int ngx_http_set_lingering_close(ngx_http_request_t *r)
Igor Sysoev1af7c822002-09-13 14:47:42 +0000701{
Igor Sysoev9b25d692003-01-26 21:08:14 +0000702 ngx_event_t *ev;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000703 ngx_http_core_loc_conf_t *lcf;
704
Igor Sysoev9b25d692003-01-26 21:08:14 +0000705 ev = r->connection->read;
706
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000707 lcf = (ngx_http_core_loc_conf_t *)
708 ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
709
710 r->lingering_time = ngx_time() + lcf->lingering_time;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000711 r->connection->read->event_handler = ngx_http_lingering_close_handler;
712
Igor Sysoev9b25d692003-01-26 21:08:14 +0000713 if (ev->timer_set) {
714 ngx_del_timer(ev);
715 } else {
716 ev->timer_set = 1;
717 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000718
Igor Sysoev9b25d692003-01-26 21:08:14 +0000719 ngx_add_timer(ev, lcf->lingering_timeout);
720
721 if (ev->blocked) {
722 if (ngx_add_event(ev, NGX_READ_EVENT,
Igor Sysoev42feecb2002-12-15 06:25:09 +0000723#if (HAVE_CLEAR_EVENT)
Igor Sysoev0d2bda52002-12-24 07:09:57 +0000724 NGX_CLEAR_EVENT) == NGX_ERROR)
Igor Sysoev42feecb2002-12-15 06:25:09 +0000725#else
Igor Sysoev0d2bda52002-12-24 07:09:57 +0000726 NGX_ONESHOT_EVENT) == NGX_ERROR)
Igor Sysoev42feecb2002-12-15 06:25:09 +0000727#endif
Igor Sysoev0d2bda52002-12-24 07:09:57 +0000728 {
729 return ngx_http_close_request(r);
730 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000731 }
732
Igor Sysoev9b25d692003-01-26 21:08:14 +0000733 if (ngx_shutdown_socket(r->connection->fd, NGX_WRITE_SHUTDOWN) == -1) {
Igor Sysoev42feecb2002-12-15 06:25:09 +0000734 ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_socket_errno,
735 ngx_shutdown_socket_n " failed");
736 return ngx_http_close_request(r);
737 }
738
739 return NGX_OK;
740}
741
742
743static int ngx_http_lingering_close_handler(ngx_event_t *ev)
744{
745 ssize_t n;
746 ngx_msec_t timer;
Igor Sysoev1af7c822002-09-13 14:47:42 +0000747 ngx_connection_t *c;
748 ngx_http_request_t *r;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000749 ngx_http_core_loc_conf_t *lcf;
Igor Sysoev1af7c822002-09-13 14:47:42 +0000750
Igor Sysoev42feecb2002-12-15 06:25:09 +0000751 ngx_log_debug(ev->log, "http lingering close handler");
Igor Sysoev1af7c822002-09-13 14:47:42 +0000752
Igor Sysoev0d2bda52002-12-24 07:09:57 +0000753 if (ev->timedout) {
754 return ngx_http_close_request(r);
755 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000756
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000757 c = (ngx_connection_t *) ev->data;
758 r = (ngx_http_request_t *) c->data;
759
Igor Sysoev1af7c822002-09-13 14:47:42 +0000760 timer = r->lingering_time - ngx_time();
Igor Sysoev0d2bda52002-12-24 07:09:57 +0000761 if (timer <= 0) {
762 return ngx_http_close_request(r);
763 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000764
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000765 lcf = (ngx_http_core_loc_conf_t *)
766 ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
767
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000768 if (r->discarded_buffer == NULL) {
769 if (r->header_in->end - r->header_in->last.mem
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000770 >= lcf->discarded_buffer_size) {
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000771 r->discarded_buffer = r->header_in->last.mem;
772
773 } else {
774 ngx_test_null(r->discarded_buffer,
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000775 ngx_palloc(c->pool, lcf->discarded_buffer_size),
Igor Sysoev0d2bda52002-12-24 07:09:57 +0000776 ngx_http_close_request(r));
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000777 }
778 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000779
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000780 n = ngx_event_recv(c, r->discarded_buffer, lcf->discarded_buffer_size);
Igor Sysoev1af7c822002-09-13 14:47:42 +0000781
Igor Sysoev0d2bda52002-12-24 07:09:57 +0000782 ngx_log_debug(ev->log, "lingering read: %d" _ n);
Igor Sysoev1af7c822002-09-13 14:47:42 +0000783
Igor Sysoev0d2bda52002-12-24 07:09:57 +0000784 if (n == NGX_ERROR || n == 0) {
785 return ngx_http_close_request(r);
786 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000787
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000788 timer *= 1000;
Igor Sysoev4e9393a2003-01-09 05:36:00 +0000789 if (timer > lcf->lingering_timeout) {
790 timer = lcf->lingering_timeout;
Igor Sysoev0d2bda52002-12-24 07:09:57 +0000791 }
Igor Sysoev1af7c822002-09-13 14:47:42 +0000792
Igor Sysoev9b25d692003-01-26 21:08:14 +0000793 if (ev->timer_set) {
794 ngx_del_timer(ev);
795 } else {
796 ev->timer_set = 1;
797 }
Igor Sysoev682bf8e2002-09-16 15:01:44 +0000798 ngx_add_timer(ev, timer);
Igor Sysoev1af7c822002-09-13 14:47:42 +0000799
800 return NGX_OK;
801}
802
Igor Sysoev2b542382002-08-20 14:48:28 +0000803
Igor Sysoev2ba1ee02002-10-04 17:58:04 +0000804static int ngx_http_close_connection(ngx_event_t *ev)
805{
806 int i, len;
807 char **requests, *requests_line, *prev, *new;
808 ngx_connection_t *c = (ngx_connection_t *) ev->data;
809
810 if (c->requests->nelts > 1) {
811 len = c->requests_len + c->requests->nelts * 2 - 1;
812
813 ngx_test_null(requests_line, ngx_palloc(c->pool, len),
814 ngx_event_close_connection(ev));
815
816 requests = (char **) c->requests->elts;
817 prev = requests_line;
818 new = ngx_cpystrn(prev, requests[0], len);
819 len -= new - prev;
820 prev = new;
821
822 for (i = 1; i < c->requests->nelts; i++) {
823 new = ngx_cpystrn(prev, ", ", len);
824 new = ngx_cpystrn(new, requests[i], len);
825 len -= new - prev;
826 prev = new;
827 }
828
829 } else {
830 requests_line = * (char **) c->requests->elts;
831 }
832
833 ngx_log_error(NGX_LOG_INFO, c->log, 0,
834 "REQUESTS: %d, '%s'", c->requests->nelts, requests_line);
835
836 return ngx_event_close_connection(ev);
837}
838
839
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000840static size_t ngx_http_log_error(void *data, char *buf, size_t len)
841{
842 ngx_http_log_ctx_t *ctx = (ngx_http_log_ctx_t *) data;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000843
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000844 if (ctx->url)
845 return ngx_snprintf(buf, len, " while %s, client: %s, URL: %s",
846 ctx->action, ctx->client, ctx->url);
847 else
848 return ngx_snprintf(buf, len, " while %s, client: %s",
849 ctx->action, ctx->client);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000850}