comparison src/http/ngx_http_request.c @ 0:f0b350454894 NGINX_0_1_0

nginx 0.1.0 *) The first public version.
author Igor Sysoev <http://sysoev.ru>
date Mon, 04 Oct 2004 00:00:00 +0400
parents
children cc9f381affaa
comparison
equal deleted inserted replaced
-1:000000000000 0:f0b350454894
1
2 /*
3 * Copyright (C) Igor Sysoev
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_event.h>
10 #include <ngx_http.h>
11
12
13 static void ngx_http_init_request(ngx_event_t *ev);
14 #if (NGX_HTTP_SSL)
15 static void ngx_http_ssl_handshake(ngx_event_t *rev);
16 #endif
17 static void ngx_http_process_request_line(ngx_event_t *rev);
18 static void ngx_http_process_request_headers(ngx_event_t *rev);
19 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
20 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
21 ngx_uint_t request_line);
22 static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
23
24 static void ngx_http_set_write_handler(ngx_http_request_t *r);
25
26 static void ngx_http_block_read(ngx_event_t *ev);
27 static void ngx_http_read_discarded_body_event(ngx_event_t *rev);
28 static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r);
29
30 static void ngx_http_set_keepalive(ngx_http_request_t *r);
31 static void ngx_http_keepalive_handler(ngx_event_t *ev);
32 static void ngx_http_set_lingering_close(ngx_http_request_t *r);
33 static void ngx_http_lingering_close_handler(ngx_event_t *ev);
34
35 static void ngx_http_client_error(ngx_http_request_t *r,
36 int client_error, int error);
37 static size_t ngx_http_log_error(void *data, char *buf, size_t len);
38
39
40 /* NGX_HTTP_PARSE_... errors */
41
42 static char *client_header_errors[] = {
43 "client %s sent invalid method",
44 "client %s sent invalid request",
45 "client %s sent too long URI",
46 "client %s sent invalid 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",
51 "client %s sent invalid \"Content-Length\" header, URL: %s",
52 "client %s sent POST method without \"Content-Length\" header, URL: %s",
53 "client %s sent plain HTTP request to HTTPS port, URL: %s",
54 "client %s sent invalid \"Host\" header \"%s\", URL: %s"
55 };
56
57
58 ngx_http_header_t ngx_http_headers_in[] = {
59 { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host) },
60 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection) },
61 { ngx_string("If-Modified-Since"),
62 offsetof(ngx_http_headers_in_t, if_modified_since) },
63 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) },
64 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer) },
65 { ngx_string("Content-Length"),
66 offsetof(ngx_http_headers_in_t, content_length) },
67
68 { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range) },
69 #if 0
70 { ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range) },
71 #endif
72
73 #if (NGX_HTTP_GZIP)
74 { ngx_string("Accept-Encoding"),
75 offsetof(ngx_http_headers_in_t, accept_encoding) },
76 { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via) },
77 #endif
78
79 { ngx_string("Authorization"),
80 offsetof(ngx_http_headers_in_t, authorization) },
81
82 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive) },
83
84 #if (NGX_HTTP_PROXY)
85 { ngx_string("X-Forwarded-For"),
86 offsetof(ngx_http_headers_in_t, x_forwarded_for) },
87 #endif
88
89 { ngx_null_string, 0 }
90 };
91
92
93 #if 0
94 static void ngx_http_dummy(ngx_event_t *wev)
95 {
96 return;
97 }
98 #endif
99
100
101 void ngx_http_init_connection(ngx_connection_t *c)
102 {
103 ngx_event_t *rev;
104 ngx_http_log_ctx_t *ctx;
105
106 if (!(ctx = ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t)))) {
107 ngx_http_close_connection(c);
108 return;
109 }
110
111 ctx->connection = c->number;
112 ctx->client = c->addr_text.data;
113 ctx->action = "reading client request line";
114 c->log->data = ctx;
115 c->log->handler = ngx_http_log_error;
116 c->log_error = NGX_ERROR_INFO;
117
118 rev = c->read;
119 rev->event_handler = ngx_http_init_request;
120
121 /* STUB: epoll edge */ c->write->event_handler = ngx_http_empty_handler;
122
123 if (rev->ready) {
124 /* the deferred accept(), rtsig, aio, iocp */
125
126 if (ngx_accept_mutex) {
127 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
128 ngx_http_close_connection(c);
129 return;
130 }
131
132 ngx_post_event(rev);
133
134 ngx_mutex_unlock(ngx_posted_events_mutex);
135 return;
136 }
137
138 #if (NGX_STAT_STUB)
139 (*ngx_stat_reading)++;
140 #endif
141
142 ngx_http_init_request(rev);
143 return;
144 }
145
146 ngx_add_timer(rev, c->listening->post_accept_timeout);
147
148 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
149 ngx_http_close_connection(c);
150 return;
151 }
152
153 #if 0
154 /* TODO: learn SO_SNDBUF (to use in zerocopy) via kqueue's EV_CLEAR event */
155
156 c->write->ready = 0;
157 c->write->event_handler = ngx_http_dummy;
158
159 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
160 ngx_http_close_connection(c);
161 return;
162 }
163 #endif
164
165 #if (NGX_STAT_STUB)
166 (*ngx_stat_reading)++;
167 #endif
168
169 }
170
171
172 static void ngx_http_init_request(ngx_event_t *rev)
173 {
174 ngx_uint_t i;
175 socklen_t len;
176 struct sockaddr_in addr_in;
177 ngx_connection_t *c;
178 ngx_http_request_t *r;
179 ngx_http_in_port_t *in_port;
180 ngx_http_in_addr_t *in_addr;
181 ngx_http_connection_t *hc;
182 ngx_http_server_name_t *server_name;
183 ngx_http_core_srv_conf_t *cscf;
184 ngx_http_core_loc_conf_t *clcf;
185 #if (NGX_HTTP_SSL)
186 ngx_http_ssl_srv_conf_t *sscf;
187 #endif
188
189 c = rev->data;
190
191 if (rev->timedout) {
192 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
193
194 #if (NGX_STAT_STUB)
195 (*ngx_stat_reading)--;
196 #endif
197
198 ngx_http_close_connection(c);
199 return;
200 }
201
202 hc = c->data;
203
204 if (hc) {
205
206 #if (NGX_STAT_STUB)
207 (*ngx_stat_reading)++;
208 #endif
209
210 } else {
211 if (!(hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t)))) {
212
213 #if (NGX_STAT_STUB)
214 (*ngx_stat_reading)--;
215 #endif
216
217 ngx_http_close_connection(c);
218 return;
219 }
220 }
221
222 r = hc->request;
223
224 if (r) {
225 ngx_memzero(r, sizeof(ngx_http_request_t));
226
227 r->pipeline = hc->pipeline;
228
229 if (hc->nbusy) {
230 r->header_in = hc->busy[0];
231 }
232
233 } else {
234 if (!(r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)))) {
235
236 #if (NGX_STAT_STUB)
237 (*ngx_stat_reading)--;
238 #endif
239
240 ngx_http_close_connection(c);
241 return;
242 }
243
244 hc->request = r;
245 }
246
247 #if (NGX_STAT_STUB)
248 r->stat_reading = 1;
249 #endif
250
251 c->data = r;
252 r->http_connection = hc;
253
254 c->sent = 0;
255 r->signature = NGX_HTTP_MODULE;
256
257 /* find the server configuration for the address:port */
258
259 /* AF_INET only */
260
261 in_port = c->servers;
262 in_addr = in_port->addrs.elts;
263
264 r->port = in_port->port;
265 r->port_text = &in_port->port_text;
266
267 i = 0;
268
269 if (in_port->addrs.nelts > 1) {
270
271 /*
272 * There are several addresses on this port and one of them
273 * is the "*:port" wildcard so getsockname() is needed to determine
274 * the server address.
275 *
276 * AcceptEx() already gave this address.
277 */
278
279 #if (WIN32)
280 if (c->local_sockaddr) {
281 r->in_addr =
282 ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
283
284 } else {
285 #endif
286 len = sizeof(struct sockaddr_in);
287 if (getsockname(c->fd, (struct sockaddr *) &addr_in, &len) == -1) {
288 ngx_connection_error(c, ngx_socket_errno,
289 "getsockname() failed");
290 ngx_http_close_connection(c);
291 return;
292 }
293
294 r->in_addr = addr_in.sin_addr.s_addr;
295
296 #if (WIN32)
297 }
298 #endif
299
300 /* the last in_port->addrs address is "*" */
301
302 for ( /* void */ ; i < in_port->addrs.nelts - 1; i++) {
303 if (in_addr[i].addr == r->in_addr) {
304 break;
305 }
306 }
307
308 } else {
309 r->in_addr = in_addr[0].addr;
310 }
311
312 r->virtual_names = &in_addr[i].names;
313
314 /* the default server configuration for the address:port */
315 cscf = in_addr[i].core_srv_conf;
316
317 r->main_conf = cscf->ctx->main_conf;
318 r->srv_conf = cscf->ctx->srv_conf;
319 r->loc_conf = cscf->ctx->loc_conf;
320
321 rev->event_handler = ngx_http_process_request_line;
322
323 #if (NGX_HTTP_SSL)
324
325 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
326 if (sscf->enable) {
327
328 if (c->ssl == NULL) {
329 if (ngx_ssl_create_session(sscf->ssl_ctx, c, NGX_SSL_BUFFER)
330 == NGX_ERROR)
331 {
332 ngx_http_close_connection(c);
333 return;
334 }
335
336 /*
337 * The majority of browsers do not send the "close notify" alert.
338 * Among them are MSIE, Mozilla, Netscape 4, Konqueror, and Links.
339 * And what is more MSIE ignores the server's alert.
340 *
341 * Opera always sends the alert.
342 */
343
344 c->ssl->no_rcv_shut = 1;
345 rev->event_handler = ngx_http_ssl_handshake;
346 }
347
348 r->filter_need_in_memory = 1;
349 }
350
351 #endif
352
353 server_name = cscf->server_names.elts;
354 r->server_name = &server_name->name;
355
356 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
357 c->log->file = clcf->err_log->file;
358 if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
359 c->log->log_level = clcf->err_log->log_level;
360 }
361
362 if (c->buffer == NULL) {
363 c->buffer = ngx_create_temp_buf(c->pool,
364 cscf->client_header_buffer_size);
365 if (c->buffer == NULL) {
366 ngx_http_close_connection(c);
367 return;
368 }
369 }
370
371 if (r->header_in == NULL) {
372 r->header_in = c->buffer;
373 }
374
375 if (!(r->pool = ngx_create_pool(cscf->request_pool_size, c->log))) {
376 ngx_http_close_connection(c);
377 return;
378 }
379
380 if (ngx_array_init(&r->cleanup, r->pool, 5, sizeof(ngx_http_cleanup_t))
381 == NGX_ERROR)
382 {
383 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
384 ngx_http_close_connection(c);
385 return;
386 }
387
388
389 if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
390 sizeof(ngx_table_elt_t)) == NGX_ERROR)
391 {
392 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
393 ngx_http_close_connection(c);
394 return;
395 }
396
397
398 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
399 if (r->ctx == NULL) {
400 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
401 ngx_http_close_connection(c);
402 return;
403 }
404
405 c->single_connection = 1;
406 r->connection = c;
407
408 r->file.fd = NGX_INVALID_FILE;
409
410 r->headers_in.content_length_n = -1;
411 r->headers_in.keep_alive_n = -1;
412 r->headers_out.content_length_n = -1;
413 r->headers_out.last_modified_time = -1;
414
415 r->http_state = NGX_HTTP_READING_REQUEST_STATE;
416
417 #if (NGX_STAT_STUB)
418 (*ngx_stat_requests)++;
419 #endif
420
421 rev->event_handler(rev);
422 }
423
424
425 #if (NGX_HTTP_SSL)
426
427 static void ngx_http_ssl_handshake(ngx_event_t *rev)
428 {
429 int n;
430 ngx_int_t rc;
431 u_char buf[1];
432 ngx_connection_t *c;
433 ngx_http_request_t *r;
434
435 c = rev->data;
436 r = c->data;
437
438 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
439 "http check ssl handshake");
440
441 if (rev->timedout) {
442 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
443 return;
444 }
445
446 n = recv(c->fd, buf, 1, MSG_PEEK);
447
448 if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
449 return;
450 }
451
452 if (n == 1) {
453 if (buf[0] == 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
454 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
455 "https ssl handshake: 0x%X", buf[0]);
456
457 c->recv = ngx_ssl_recv;
458 c->send_chain = ngx_ssl_send_chain;
459
460 rc = ngx_ssl_handshake(c);
461
462 if (rc == NGX_ERROR) {
463 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
464 ngx_http_close_connection(r->connection);
465 return;
466 }
467
468 if (rc != NGX_OK) {
469 return;
470 }
471
472 } else {
473 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
474 "plain http");
475
476 r->plain_http = 1;
477 }
478 }
479
480 rev->event_handler = ngx_http_process_request_line;
481 ngx_http_process_request_line(rev);
482 }
483
484 #endif
485
486
487 static void ngx_http_process_request_line(ngx_event_t *rev)
488 {
489 u_char *p;
490 ssize_t n;
491 ngx_int_t rc, rv;
492 ngx_connection_t *c;
493 ngx_http_request_t *r;
494 ngx_http_log_ctx_t *ctx;
495
496 c = rev->data;
497 r = c->data;
498
499 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
500 "http process request line");
501
502 if (rev->timedout) {
503 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
504 return;
505 }
506
507 rc = NGX_AGAIN;
508
509 for ( ;; ) {
510
511 if (rc == NGX_AGAIN) {
512 n = ngx_http_read_request_header(r);
513
514 if (n == NGX_AGAIN || n == NGX_ERROR) {
515 return;
516 }
517 }
518
519 rc = ngx_http_parse_request_line(r, r->header_in);
520
521 if (rc == NGX_OK) {
522
523 /* the request line has been parsed successfully */
524
525 /* copy unparsed URI */
526
527 r->unparsed_uri.len = r->uri_end - r->uri_start;
528 r->unparsed_uri.data = ngx_palloc(r->pool, r->unparsed_uri.len + 1);
529 if (r->unparsed_uri.data == NULL) {
530 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
531 ngx_http_close_connection(c);
532 return;
533 }
534
535 ngx_cpystrn(r->unparsed_uri.data, r->uri_start,
536 r->unparsed_uri.len + 1);
537
538
539 /* copy URI */
540
541 if (r->args_start) {
542 r->uri.len = r->args_start - 1 - r->uri_start;
543 } else {
544 r->uri.len = r->uri_end - r->uri_start;
545 }
546
547 if (!(r->uri.data = ngx_palloc(r->pool, r->uri.len + 1))) {
548 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
549 ngx_http_close_connection(c);
550 return;
551 }
552
553 if (r->complex_uri) {
554 rc = ngx_http_parse_complex_uri(r);
555
556 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
557 ngx_http_close_request(r, rc);
558 ngx_http_close_connection(c);
559 return;
560 }
561
562 if (rc != NGX_OK) {
563 r->request_line.len = r->request_end - r->request_start;
564 r->request_line.data = r->request_start;
565
566 ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST);
567 return;
568 }
569
570 } else {
571 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1);
572 }
573
574
575 r->request_line.len = r->request_end - r->request_start;
576 r->request_line.data = r->request_start;
577 r->request_line.data[r->request_line.len] = '\0';
578
579 if (r->method == 0) {
580 r->method_name.len = r->method_end - r->request_start + 1;
581 r->method_name.data = r->request_line.data;
582 }
583
584 if (r->uri_ext) {
585
586 /* copy URI extention */
587
588 if (r->args_start) {
589 r->exten.len = r->args_start - 1 - r->uri_ext;
590 } else {
591 r->exten.len = r->uri_end - r->uri_ext;
592 }
593
594 if (!(r->exten.data = ngx_palloc(r->pool, r->exten.len + 1))) {
595 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
596 ngx_http_close_connection(c);
597 return;
598 }
599
600 ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1);
601 }
602
603 if (r->args_start && r->uri_end > r->args_start) {
604
605 /* copy URI arguments */
606
607 r->args.len = r->uri_end - r->args_start;
608
609 if (!(r->args.data = ngx_palloc(r->pool, r->args.len + 1))) {
610 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
611 ngx_http_close_connection(c);
612 return;
613 }
614
615 ngx_cpystrn(r->args.data, r->args_start, r->args.len + 1);
616 }
617
618 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
619 "http request line: \"%s\"", r->request_line.data);
620
621 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
622 "http uri: \"%s\"", r->uri.data);
623
624 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
625 "http args: \"%s\"",
626 r->args.data ? r->args.data : (u_char *) "");
627
628 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
629 "http exten: \"%s\"",
630 r->exten.data ? r->exten.data : (u_char *) "");
631
632 if (r->http_version < NGX_HTTP_VERSION_10) {
633 rev->event_handler = ngx_http_block_read;
634 ngx_http_handler(r);
635 return;
636 }
637
638
639 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
640 sizeof(ngx_table_elt_t)) == NGX_ERROR)
641 {
642 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
643 ngx_http_close_connection(c);
644 return;
645 }
646
647
648 if (ngx_array_init(&r->headers_in.cookies, r->pool, 5,
649 sizeof(ngx_table_elt_t *)) == NGX_ERROR)
650 {
651 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
652 ngx_http_close_connection(c);
653 return;
654 }
655
656
657 ctx = c->log->data;
658 ctx->action = "reading client request headers";
659 ctx->url = r->unparsed_uri.data;
660
661 rev->event_handler = ngx_http_process_request_headers;
662 ngx_http_process_request_headers(rev);
663
664 return;
665
666 } else if (rc != NGX_AGAIN) {
667
668 /* there was error while a request line parsing */
669
670 for (p = r->request_start; p < r->header_in->last; p++) {
671 if (*p == CR || *p == LF) {
672 break;
673 }
674 }
675
676 r->request_line.len = p - r->request_start;
677 r->request_line.data = r->request_start;
678
679 if (rc == NGX_HTTP_PARSE_INVALID_METHOD) {
680 r->http_version = NGX_HTTP_VERSION_10;
681 }
682
683 ngx_http_client_error(r, rc,
684 (rc == NGX_HTTP_PARSE_INVALID_METHOD) ?
685 NGX_HTTP_NOT_IMPLEMENTED:
686 NGX_HTTP_BAD_REQUEST);
687 return;
688 }
689
690 /* NGX_AGAIN: a request line parsing is still incomplete */
691
692 if (r->header_in->pos == r->header_in->end) {
693
694 rv = ngx_http_alloc_large_header_buffer(r, 1);
695
696 if (rv == NGX_ERROR) {
697 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
698 ngx_http_close_connection(c);
699 return;
700 }
701
702 if (rv == NGX_DECLINED) {
703 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
704 NGX_HTTP_REQUEST_URI_TOO_LARGE);
705 return;
706 }
707 }
708 }
709 }
710
711
712 static void ngx_http_process_request_headers(ngx_event_t *rev)
713 {
714 ssize_t n;
715 ngx_int_t rc, rv, i;
716 ngx_table_elt_t *h, **cookie;
717 ngx_connection_t *c;
718 ngx_http_request_t *r;
719
720 c = rev->data;
721 r = c->data;
722
723 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
724 "http process request header line");
725
726 if (rev->timedout) {
727 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
728 return;
729 }
730
731 rc = NGX_AGAIN;
732
733 for ( ;; ) {
734
735 if (rc == NGX_AGAIN) {
736
737 if (r->header_in->pos == r->header_in->end) {
738
739 rv = ngx_http_alloc_large_header_buffer(r, 0);
740
741 if (rv == NGX_ERROR) {
742 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
743 ngx_http_close_connection(c);
744 return;
745 }
746
747 if (rv == NGX_DECLINED) {
748 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER,
749 NGX_HTTP_BAD_REQUEST);
750 return;
751 }
752 }
753
754 n = ngx_http_read_request_header(r);
755
756 if (n == NGX_AGAIN || n == NGX_ERROR) {
757 return;
758 }
759 }
760
761 rc = ngx_http_parse_header_line(r, r->header_in);
762
763 if (rc == NGX_OK) {
764
765 /* a header line has been parsed successfully */
766
767 r->headers_n++;
768
769 if (!(h = ngx_list_push(&r->headers_in.headers))) {
770 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
771 ngx_http_close_connection(c);
772 return;
773 }
774
775 h->key.len = r->header_name_end - r->header_name_start;
776 h->key.data = r->header_name_start;
777 h->key.data[h->key.len] = '\0';
778
779 h->value.len = r->header_end - r->header_start;
780 h->value.data = r->header_start;
781 h->value.data[h->value.len] = '\0';
782
783 if (h->key.len == sizeof("Cookie") - 1
784 && ngx_strcasecmp(h->key.data, "Cookie") == 0)
785 {
786 if (!(cookie = ngx_array_push(&r->headers_in.cookies))) {
787 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
788 ngx_http_close_connection(c);
789 return;
790 }
791
792 *cookie = h;
793
794 } else {
795
796 for (i = 0; ngx_http_headers_in[i].name.len != 0; i++) {
797 if (ngx_http_headers_in[i].name.len != h->key.len) {
798 continue;
799 }
800
801 if (ngx_strcasecmp(ngx_http_headers_in[i].name.data,
802 h->key.data) == 0)
803 {
804 *((ngx_table_elt_t **) ((char *) &r->headers_in
805 + ngx_http_headers_in[i].offset)) = h;
806 break;
807 }
808 }
809 }
810
811 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
812 "http header: \"%s: %s\"",
813 h->key.data, h->value.data);
814
815 continue;
816
817 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
818
819 /* a whole header has been parsed successfully */
820
821 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
822 "http header done");
823
824 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
825
826 rc = ngx_http_process_request_header(r);
827
828 if (rc != NGX_OK) {
829 ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST);
830 return;
831 }
832
833 if (rev->timer_set) {
834 ngx_del_timer(rev);
835 }
836
837 #if (NGX_STAT_STUB)
838 (*ngx_stat_reading)--;
839 r->stat_reading = 0;
840 (*ngx_stat_writing)++;
841 r->stat_writing = 1;
842 #endif
843
844 rev->event_handler = ngx_http_block_read;
845 ngx_http_handler(r);
846 return;
847
848 } else if (rc != NGX_AGAIN) {
849
850 /* there was error while a header line parsing */
851
852 #if (NGX_DEBUG)
853 if (rc == NGX_HTTP_PARSE_INVALID_HEADER
854 && (rev->log->log_level & NGX_LOG_DEBUG_HTTP))
855 {
856 u_char *p;
857 for (p = r->header_name_start;
858 p < r->header_in->last - 1;
859 p++)
860 {
861 if (*p == LF) {
862 break;
863 }
864 }
865 *p = '\0';
866 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
867 "http invalid header: \"%s\"",
868 r->header_name_start);
869 }
870 #endif
871
872 ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST);
873 return;
874 }
875
876 /* NGX_AGAIN: a header line parsing is still not complete */
877
878 }
879 }
880
881
882 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
883 {
884 ssize_t n;
885 ngx_event_t *rev;
886 ngx_http_core_srv_conf_t *cscf;
887
888 rev = r->connection->read;
889
890 n = r->header_in->last - r->header_in->pos;
891
892 if (n > 0) {
893 return n;
894 }
895
896 if (!rev->ready) {
897 return NGX_AGAIN;
898 }
899
900 n = r->connection->recv(r->connection, r->header_in->last,
901 r->header_in->end - r->header_in->last);
902
903 if (n == NGX_AGAIN) {
904 if (!r->header_timeout_set) {
905 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
906 ngx_add_timer(rev, cscf->client_header_timeout);
907 r->header_timeout_set = 1;
908 }
909
910 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
911 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
912 ngx_http_close_connection(r->connection);
913 return NGX_ERROR;
914 }
915
916 return NGX_AGAIN;
917 }
918
919 if (n == 0) {
920 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
921 "client closed prematurely connection");
922 }
923
924 if (n == 0 || n == NGX_ERROR) {
925 ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
926 ngx_http_close_connection(r->connection);
927 return NGX_ERROR;
928 }
929
930 r->header_in->last += n;
931
932 return n;
933 }
934
935
936 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
937 ngx_uint_t request_line)
938 {
939 u_char *old, *new;
940 ngx_buf_t *b;
941 ngx_http_connection_t *hc;
942 ngx_http_core_srv_conf_t *cscf;
943
944 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
945 "http alloc large header buffer");
946
947 if (request_line && r->state == 0) {
948
949 /* the client fills up the buffer with "\r\n" */
950
951 r->header_in->pos = r->header_in->start;
952 r->header_in->last = r->header_in->start;
953
954 return NGX_OK;
955 }
956
957 old = request_line ? r->request_start : r->header_name_start;
958
959 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
960
961 if (r->state != 0
962 && (size_t) (r->header_in->pos - old)
963 >= cscf->large_client_header_buffers.size)
964 {
965 return NGX_DECLINED;
966 }
967
968 hc = r->http_connection;
969
970 if (hc->nfree) {
971 b = hc->free[--hc->nfree];
972
973 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
974 "http large header free: " PTR_FMT " " SIZE_T_FMT,
975 b->pos, b->end - b->last);
976
977 } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
978
979 if (hc->busy == NULL) {
980 hc->busy = ngx_palloc(r->connection->pool,
981 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
982 if (hc->busy == NULL) {
983 return NGX_ERROR;
984 }
985 }
986
987 b = ngx_create_temp_buf(r->connection->pool,
988 cscf->large_client_header_buffers.size);
989 if (b == NULL) {
990 return NGX_ERROR;
991 }
992
993 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
994 "http large header alloc: " PTR_FMT " " SIZE_T_FMT,
995 b->pos, b->end - b->last);
996
997 } else {
998 return NGX_DECLINED;
999 }
1000
1001 hc->busy[hc->nbusy++] = b;
1002
1003 if (r->state == 0) {
1004 /*
1005 * r->state == 0 means that a header line was parsed successfully
1006 * and we do not need to copy incomplete header line and
1007 * to relocate the parser header pointers
1008 */
1009
1010 r->header_in = b;
1011
1012 return NGX_OK;
1013 }
1014
1015 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1016 "http large header copy: %d", r->header_in->pos - old);
1017
1018 new = b->start;
1019
1020 ngx_memcpy(new, old, r->header_in->pos - old);
1021
1022 b->pos = new + (r->header_in->pos - old);
1023 b->last = new + (r->header_in->pos - old);
1024
1025 if (request_line) {
1026 r->request_start = new;
1027
1028 if (r->request_end) {
1029 r->request_end = new + (r->request_end - old);
1030 }
1031
1032 r->method_end = new + (r->method_end - old);
1033
1034 r->uri_start = new + (r->uri_start - old);
1035 r->uri_end = new + (r->uri_end - old);
1036
1037 if (r->schema_start) {
1038 r->schema_start = new + (r->schema_start - old);
1039 r->schema_end = new + (r->schema_end - old);
1040 }
1041
1042 if (r->host_start) {
1043 r->host_start = new + (r->host_start - old);
1044 r->host_end = new + (r->host_end - old);
1045 }
1046
1047 if (r->port_start) {
1048 r->port_start = new + (r->port_start - old);
1049 r->port_end = new + (r->port_end - old);
1050 }
1051
1052 if (r->uri_ext) {
1053 r->uri_ext = new + (r->uri_ext - old);
1054 }
1055
1056 if (r->args_start) {
1057 r->args_start = new + (r->args_start - old);
1058 }
1059
1060 } else {
1061 r->header_name_start = new;
1062 r->header_name_end = new + (r->header_name_end - old);
1063 r->header_start = new + (r->header_start - old);
1064 r->header_end = new + (r->header_end - old);
1065 }
1066
1067 r->header_in = b;
1068
1069 return NGX_OK;
1070 }
1071
1072
1073 static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r)
1074 {
1075 u_char *ua, *user_agent;
1076 size_t len;
1077 ngx_uint_t i;
1078 ngx_http_server_name_t *name;
1079 ngx_http_core_srv_conf_t *cscf;
1080 ngx_http_core_loc_conf_t *clcf;
1081
1082 if (r->headers_in.host) {
1083 for (len = 0; len < r->headers_in.host->value.len; len++) {
1084 if (r->headers_in.host->value.data[len] == ':') {
1085 break;
1086 }
1087 }
1088 r->headers_in.host_name_len = len;
1089
1090 /* find the name based server configuration */
1091
1092 name = r->virtual_names->elts;
1093 for (i = 0; i < r->virtual_names->nelts; i++) {
1094 if (r->headers_in.host_name_len != name[i].name.len) {
1095 continue;
1096 }
1097
1098 if (ngx_strncasecmp(r->headers_in.host->value.data,
1099 name[i].name.data,
1100 r->headers_in.host_name_len) == 0)
1101 {
1102 r->srv_conf = name[i].core_srv_conf->ctx->srv_conf;
1103 r->loc_conf = name[i].core_srv_conf->ctx->loc_conf;
1104 r->server_name = &name[i].name;
1105
1106 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1107 r->connection->log->file = clcf->err_log->file;
1108 if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION))
1109 {
1110 r->connection->log->log_level = clcf->err_log->log_level;
1111 }
1112
1113 break;
1114 }
1115 }
1116
1117 if (i == r->virtual_names->nelts) {
1118 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1119
1120 if (cscf->restrict_host_names != NGX_HTTP_RESTRICT_HOST_OFF) {
1121 return NGX_HTTP_PARSE_INVALID_HOST;
1122 }
1123 }
1124
1125 } else {
1126 if (r->http_version > NGX_HTTP_VERSION_10) {
1127 return NGX_HTTP_PARSE_NO_HOST_HEADER;
1128 }
1129 r->headers_in.host_name_len = 0;
1130 }
1131
1132 if (r->headers_in.content_length) {
1133 r->headers_in.content_length_n =
1134 ngx_atoi(r->headers_in.content_length->value.data,
1135 r->headers_in.content_length->value.len);
1136
1137 if (r->headers_in.content_length_n == NGX_ERROR) {
1138 return NGX_HTTP_PARSE_INVALID_CL_HEADER;
1139 }
1140 }
1141
1142 if (r->method == NGX_HTTP_POST && r->headers_in.content_length_n <= 0) {
1143 return NGX_HTTP_PARSE_POST_WO_CL_HEADER;
1144 }
1145
1146 if (r->plain_http) {
1147 return NGX_HTTP_PARSE_HTTP_TO_HTTPS;
1148 }
1149
1150 if (r->headers_in.connection) {
1151 if (r->headers_in.connection->value.len == 5
1152 && ngx_strcasecmp(r->headers_in.connection->value.data, "close")
1153 == 0)
1154 {
1155 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1156
1157 } else if (r->headers_in.connection->value.len == 10
1158 && ngx_strcasecmp(r->headers_in.connection->value.data,
1159 "keep-alive") == 0)
1160 {
1161 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1162
1163 if (r->headers_in.keep_alive) {
1164 r->headers_in.keep_alive_n =
1165 ngx_atoi(r->headers_in.keep_alive->value.data,
1166 r->headers_in.keep_alive->value.len);
1167 }
1168 }
1169 }
1170
1171 if (r->headers_in.user_agent) {
1172
1173 /*
1174 * check some widespread browsers while the headers are still
1175 * in CPU cache
1176 */
1177
1178 user_agent = r->headers_in.user_agent->value.data;
1179
1180 ua = (u_char *) ngx_strstr(user_agent, "MSIE");
1181
1182 if (ua && ua + 8 < user_agent + r->headers_in.user_agent->value.len) {
1183
1184 r->headers_in.msie = 1;
1185
1186 if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') {
1187 r->headers_in.msie4 = 1;
1188 }
1189
1190 #if 0
1191 /* MSIE ignores the SSL "close notify" alert */
1192
1193 ngx_ssl_set_nosendshut(r->connection->ssl);
1194 #endif
1195 }
1196
1197 if (ngx_strstr(user_agent, "Opera")) {
1198 r->headers_in.opera = 1;
1199 r->headers_in.msie = 0;
1200 r->headers_in.msie4 = 0;
1201 }
1202
1203 if (!r->headers_in.msie && !r->headers_in.opera) {
1204
1205 if (ngx_strstr(user_agent, "Gecko/")) {
1206 r->headers_in.gecko = 1;
1207
1208 } else if (ngx_strstr(user_agent, "Konqueror")) {
1209 r->headers_in.konqueror = 1;
1210 }
1211 }
1212 }
1213
1214 return NGX_OK;
1215 }
1216
1217
1218 void ngx_http_finalize_request(ngx_http_request_t *r, int rc)
1219 {
1220 ngx_http_core_loc_conf_t *clcf;
1221
1222 /* r can be already destroyed when rc == NGX_DONE */
1223
1224 if (rc == NGX_DONE || r->main) {
1225 return;
1226 }
1227
1228 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1229 "http finalize request: %d", rc);
1230
1231 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
1232
1233 if (r->connection->read->timer_set) {
1234 ngx_del_timer(r->connection->read);
1235 }
1236
1237 if (r->connection->write->timer_set) {
1238 ngx_del_timer(r->connection->write);
1239 }
1240
1241 if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST || r->closed) {
1242 ngx_http_close_request(r, 0);
1243 ngx_http_close_connection(r->connection);
1244 return;
1245 }
1246
1247 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
1248
1249 return;
1250
1251 } else if (rc == NGX_ERROR) {
1252 ngx_http_close_request(r, 0);
1253 ngx_http_close_connection(r->connection);
1254 return;
1255
1256 } else if (rc == NGX_AGAIN) {
1257 ngx_http_set_write_handler(r);
1258 return;
1259 }
1260
1261 if (r->connection->read->timer_set) {
1262 ngx_del_timer(r->connection->read);
1263 }
1264
1265 if (r->connection->write->timer_set) {
1266 r->connection->write->delayed = 0;
1267 ngx_del_timer(r->connection->write);
1268 }
1269
1270 if (r->connection->read->pending_eof) {
1271 #if (NGX_KQUEUE)
1272 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log,
1273 r->connection->read->kq_errno,
1274 "kevent() reported about an closed connection");
1275 #endif
1276 ngx_http_close_request(r, 0);
1277 ngx_http_close_connection(r->connection);
1278 return;
1279 }
1280
1281 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1282
1283 if (!ngx_terminate
1284 && !ngx_exiting
1285 && r->keepalive != 0
1286 && clcf->keepalive_timeout > 0)
1287 {
1288 ngx_http_set_keepalive(r);
1289 return;
1290
1291 } else if (r->lingering_close && clcf->lingering_timeout > 0) {
1292 ngx_http_set_lingering_close(r);
1293 return;
1294 }
1295
1296 ngx_http_close_request(r, 0);
1297 ngx_http_close_connection(r->connection);
1298 }
1299
1300
1301 static void ngx_http_set_write_handler(ngx_http_request_t *r)
1302 {
1303 ngx_event_t *wev;
1304 ngx_http_core_loc_conf_t *clcf;
1305
1306 wev = r->connection->write;
1307 wev->event_handler = ngx_http_writer;
1308
1309 r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
1310
1311 if (wev->ready && wev->delayed) {
1312 return;
1313 }
1314
1315 clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
1316 ngx_http_core_module);
1317 if (!wev->delayed) {
1318 ngx_add_timer(wev, clcf->send_timeout);
1319 }
1320
1321 wev->available = clcf->send_lowat;
1322 if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
1323 ngx_http_close_request(r, 0);
1324 ngx_http_close_connection(r->connection);
1325 }
1326
1327 return;
1328 }
1329
1330
1331 void ngx_http_writer(ngx_event_t *wev)
1332 {
1333 int rc;
1334 ngx_connection_t *c;
1335 ngx_http_request_t *r;
1336 ngx_http_core_loc_conf_t *clcf;
1337
1338 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http writer handler");
1339
1340 c = wev->data;
1341 r = c->data;
1342
1343 if (wev->timedout) {
1344 if (!wev->delayed) {
1345 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
1346 return;
1347 }
1348
1349 wev->timedout = 0;
1350 wev->delayed = 0;
1351
1352 if (!wev->ready) {
1353 clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
1354 ngx_http_core_module);
1355 ngx_add_timer(wev, clcf->send_timeout);
1356
1357 wev->available = clcf->send_lowat;
1358
1359 if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
1360 ngx_http_close_request(r, 0);
1361 ngx_http_close_connection(r->connection);
1362 }
1363
1364 return;
1365 }
1366
1367 } else {
1368 if (wev->delayed) {
1369 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
1370 "http writer delayed");
1371
1372 clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
1373 ngx_http_core_module);
1374 wev->available = clcf->send_lowat;
1375
1376 if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
1377 ngx_http_close_request(r, 0);
1378 ngx_http_close_connection(r->connection);
1379 }
1380
1381 return;
1382 }
1383 }
1384
1385 rc = ngx_http_output_filter(r, NULL);
1386
1387 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
1388 "http writer output filter: %d", rc);
1389
1390 if (rc == NGX_AGAIN) {
1391 clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
1392 ngx_http_core_module);
1393 if (!wev->ready && !wev->delayed) {
1394 ngx_add_timer(wev, clcf->send_timeout);
1395 }
1396
1397 wev->available = clcf->send_lowat;
1398
1399 if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) {
1400 ngx_http_close_request(r, 0);
1401 ngx_http_close_connection(r->connection);
1402 }
1403
1404 return;
1405 }
1406
1407 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http writer done");
1408
1409 ngx_http_finalize_request(r, rc);
1410 }
1411
1412
1413 static void ngx_http_block_read(ngx_event_t *rev)
1414 {
1415 ngx_connection_t *c;
1416 ngx_http_request_t *r;
1417
1418 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http read blocked");
1419
1420 /* aio does not call this handler */
1421
1422 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
1423 if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
1424 c = rev->data;
1425 r = c->data;
1426 ngx_http_close_request(r, 0);
1427 ngx_http_close_connection(c);
1428 }
1429 }
1430 }
1431
1432
1433 ngx_int_t ngx_http_discard_body(ngx_http_request_t *r)
1434 {
1435 ssize_t size;
1436 ngx_event_t *rev;
1437
1438 rev = r->connection->read;
1439
1440 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body");
1441
1442 if (rev->timer_set) {
1443 ngx_del_timer(rev);
1444 }
1445
1446 if (r->headers_in.content_length_n <= 0) {
1447 return NGX_OK;
1448 }
1449
1450 size = r->header_in->last - r->header_in->pos;
1451
1452 if (size) {
1453 if (r->headers_in.content_length_n > size) {
1454 r->headers_in.content_length_n -= size;
1455
1456 } else {
1457 r->header_in->pos += r->headers_in.content_length_n;
1458 r->headers_in.content_length_n = 0;
1459 return NGX_OK;
1460 }
1461 }
1462
1463 rev->event_handler = ngx_http_read_discarded_body_event;
1464
1465 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1466 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1467 }
1468
1469 return ngx_http_read_discarded_body(r);
1470 }
1471
1472
1473 static void ngx_http_read_discarded_body_event(ngx_event_t *rev)
1474 {
1475 ngx_int_t rc;
1476 ngx_connection_t *c;
1477 ngx_http_request_t *r;
1478
1479 c = rev->data;
1480 r = c->data;
1481
1482 rc = ngx_http_read_discarded_body(r);
1483
1484 if (rc == NGX_AGAIN) {
1485 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1486 ngx_http_close_request(r, rc);
1487 ngx_http_close_connection(c);
1488 return;
1489 }
1490 }
1491
1492 if (rc != NGX_OK) {
1493 ngx_http_close_request(r, rc);
1494 ngx_http_close_connection(c);
1495 }
1496 }
1497
1498
1499 static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r)
1500 {
1501 ssize_t size, n;
1502 u_char buffer[NGX_HTTP_DISCARD_BUFFER_SIZE];
1503
1504 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1505 "http read discarded body");
1506
1507 if (r->headers_in.content_length_n == 0) {
1508 return NGX_OK;
1509 }
1510
1511
1512 size = r->headers_in.content_length_n;
1513
1514 if (size > NGX_HTTP_DISCARD_BUFFER_SIZE) {
1515 size = NGX_HTTP_DISCARD_BUFFER_SIZE;
1516 }
1517
1518 n = r->connection->recv(r->connection, buffer, size);
1519
1520 if (n == NGX_ERROR) {
1521
1522 r->closed = 1;
1523
1524 /*
1525 * if a client request body is discarded then we already set
1526 * some HTTP response code for client and we can ignore the error
1527 */
1528
1529 return NGX_OK;
1530 }
1531
1532 if (n == NGX_AGAIN) {
1533 return NGX_AGAIN;
1534 }
1535
1536 r->headers_in.content_length_n -= n;
1537
1538 return NGX_OK;
1539 }
1540
1541
1542 static void ngx_http_set_keepalive(ngx_http_request_t *r)
1543 {
1544 ngx_int_t i;
1545 ngx_buf_t *b, *f;
1546 ngx_event_t *rev, *wev;
1547 ngx_connection_t *c;
1548 ngx_http_connection_t *hc;
1549 ngx_http_log_ctx_t *ctx;
1550 ngx_http_core_srv_conf_t *cscf;
1551 ngx_http_core_loc_conf_t *clcf;
1552
1553 c = r->connection;
1554 rev = c->read;
1555
1556 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
1557
1558 ctx = (ngx_http_log_ctx_t *) c->log->data;
1559 ctx->action = "closing request";
1560
1561 hc = r->http_connection;
1562 b = r->header_in;
1563
1564 if (b->pos < b->last) {
1565
1566 /* the pipelined request */
1567
1568 if (b != c->buffer) {
1569
1570 /* move the large header buffers to the free list */
1571
1572 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1573
1574 if (hc->free == NULL) {
1575 hc->free = ngx_palloc(c->pool,
1576 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
1577
1578 if (hc->free == NULL) {
1579 ngx_http_close_connection(c);
1580 return;
1581 }
1582 }
1583
1584 for (i = 0; i < hc->nbusy - 1; i++) {
1585 f = hc->busy[i];
1586 hc->free[hc->nfree++] = f;
1587 f->pos = f->start;
1588 f->last = f->start;
1589 }
1590
1591 hc->busy[0] = b;
1592 hc->nbusy = 1;
1593 }
1594 }
1595
1596 ngx_http_close_request(r, 0);
1597 c->data = hc;
1598
1599 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1600 ngx_add_timer(rev, clcf->keepalive_timeout);
1601
1602 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1603 ngx_http_close_connection(c);
1604 return;
1605 }
1606
1607 wev = c->write;
1608 wev->event_handler = ngx_http_empty_handler;
1609
1610 if (b->pos < b->last) {
1611
1612 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
1613
1614 hc->pipeline = 1;
1615 ctx->action = "reading client pipelined request line";
1616 ngx_http_init_request(rev);
1617 return;
1618 }
1619
1620 hc->pipeline = 0;
1621
1622 if (ngx_pfree(c->pool, r) == NGX_OK) {
1623 hc->request = NULL;
1624 }
1625
1626 b = c->buffer;
1627
1628 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
1629 b->pos = NULL;
1630
1631 } else {
1632 b->pos = b->start;
1633 b->last = b->start;
1634 }
1635
1636 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: " PTR_FMT " %d",
1637 hc->free, hc->nfree);
1638
1639 if (hc->free) {
1640 for (i = 0; i < hc->nfree; i++) {
1641 ngx_pfree(c->pool, hc->free[i]);
1642 hc->free[i] = NULL;
1643 }
1644
1645 hc->nfree = 0;
1646 }
1647
1648 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: " PTR_FMT " %d",
1649 hc->busy, hc->nbusy);
1650
1651 if (hc->busy) {
1652 for (i = 0; i < hc->nbusy; i++) {
1653 ngx_pfree(c->pool, hc->busy[i]);
1654 hc->busy[i] = NULL;
1655 }
1656
1657 hc->nbusy = 0;
1658 }
1659
1660 rev->event_handler = ngx_http_keepalive_handler;
1661
1662 if (wev->active) {
1663 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
1664 if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_DISABLE_EVENT)
1665 == NGX_ERROR)
1666 {
1667 ngx_http_close_connection(c);
1668 return;
1669 }
1670
1671 } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
1672 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
1673 ngx_http_close_connection(c);
1674 return;
1675 }
1676 }
1677 }
1678
1679 ctx->action = "keepalive";
1680
1681 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
1682 if (ngx_tcp_push(c->fd) == NGX_ERROR) {
1683 ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
1684 ngx_http_close_connection(c);
1685 return;
1686 }
1687 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
1688 }
1689
1690 #if 0
1691 /* if "keepalive_buffers off" then we need some other place */
1692 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
1693 #endif
1694
1695 if (rev->ready) {
1696 ngx_http_keepalive_handler(rev);
1697 }
1698 }
1699
1700
1701 static void ngx_http_keepalive_handler(ngx_event_t *rev)
1702 {
1703 size_t size;
1704 ssize_t n;
1705 ngx_buf_t *b;
1706 ngx_connection_t *c;
1707 ngx_http_log_ctx_t *ctx;
1708 ngx_http_connection_t *hc;
1709
1710 c = rev->data;
1711
1712 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
1713
1714 if (rev->timedout) {
1715 ngx_http_close_connection(c);
1716 return;
1717 }
1718
1719 ctx = (ngx_http_log_ctx_t *) rev->log->data;
1720
1721 #if (HAVE_KQUEUE)
1722
1723 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
1724 if (rev->pending_eof) {
1725 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
1726 "kevent() reported that client %s closed "
1727 "keepalive connection", ctx->client);
1728 ngx_http_close_connection(c);
1729 return;
1730 }
1731 }
1732
1733 #endif
1734
1735 hc = c->data;
1736 b = c->buffer;
1737 size = b->end - b->start;
1738
1739 if (b->pos == NULL) {
1740 if (!(b->pos = ngx_palloc(c->pool, size))) {
1741 ngx_http_close_connection(c);
1742 return;
1743 }
1744
1745 b->start = b->pos;
1746 b->last = b->pos;
1747 b->end = b->pos + size;
1748 }
1749
1750 /*
1751 * MSIE closes a keepalive connection with RST flag
1752 * so we ignore ECONNRESET here.
1753 */
1754
1755 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
1756 ngx_set_socket_errno(0);
1757
1758 n = c->recv(c, b->last, size);
1759 c->log_error = NGX_ERROR_INFO;
1760
1761 if (n == NGX_AGAIN) {
1762 return;
1763 }
1764
1765 if (n == NGX_ERROR) {
1766 ngx_http_close_connection(c);
1767 return;
1768 }
1769
1770 rev->log->handler = NULL;
1771
1772 if (n == 0) {
1773 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
1774 "client %s closed keepalive connection", ctx->client);
1775 ngx_http_close_connection(c);
1776 return;
1777 }
1778
1779 b->last += n;
1780 rev->log->handler = ngx_http_log_error;
1781 ctx->action = "reading client request line";
1782
1783 ngx_http_init_request(rev);
1784 }
1785
1786
1787 static void ngx_http_set_lingering_close(ngx_http_request_t *r)
1788 {
1789 ngx_event_t *rev, *wev;
1790 ngx_connection_t *c;
1791 ngx_http_core_loc_conf_t *clcf;
1792
1793 c = r->connection;
1794
1795 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1796
1797 rev = c->read;
1798 rev->event_handler = ngx_http_lingering_close_handler;
1799
1800 r->lingering_time = ngx_time() + clcf->lingering_time / 1000;
1801 ngx_add_timer(rev, clcf->lingering_timeout);
1802
1803 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1804 ngx_http_close_request(r, 0);
1805 ngx_http_close_connection(c);
1806 return;
1807 }
1808
1809 wev = c->write;
1810 wev->event_handler = ngx_http_empty_handler;
1811
1812 if (wev->active) {
1813 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
1814 if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_DISABLE_EVENT)
1815 == NGX_ERROR)
1816 {
1817 ngx_http_close_connection(c);
1818 return;
1819 }
1820
1821 } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
1822 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
1823 ngx_http_close_connection(c);
1824 return;
1825 }
1826 }
1827 }
1828
1829 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
1830 ngx_connection_error(c, ngx_socket_errno,
1831 ngx_shutdown_socket_n " failed");
1832 ngx_http_close_request(r, 0);
1833 ngx_http_close_connection(c);
1834 return;
1835 }
1836
1837 if (rev->ready) {
1838 ngx_http_lingering_close_handler(rev);
1839 }
1840 }
1841
1842
1843 static void ngx_http_lingering_close_handler(ngx_event_t *rev)
1844 {
1845 ssize_t n;
1846 ngx_msec_t timer;
1847 ngx_connection_t *c;
1848 ngx_http_request_t *r;
1849 ngx_http_core_loc_conf_t *clcf;
1850 u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
1851
1852 c = rev->data;
1853 r = c->data;
1854
1855 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1856 "http lingering close handler");
1857
1858 if (rev->timedout) {
1859 ngx_http_close_request(r, 0);
1860 ngx_http_close_connection(c);
1861 return;
1862 }
1863
1864 timer = r->lingering_time - ngx_time();
1865 if (timer <= 0) {
1866 ngx_http_close_request(r, 0);
1867 ngx_http_close_connection(c);
1868 return;
1869 }
1870
1871 do {
1872 n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
1873
1874 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
1875
1876 if (n == NGX_ERROR || n == 0) {
1877 ngx_http_close_request(r, 0);
1878 ngx_http_close_connection(c);
1879 return;
1880 }
1881
1882 } while (rev->ready);
1883
1884 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1885
1886 timer *= 1000;
1887
1888 if (timer > clcf->lingering_timeout) {
1889 timer = clcf->lingering_timeout;
1890 }
1891
1892 ngx_add_timer(rev, timer);
1893
1894 return;
1895 }
1896
1897
1898 void ngx_http_empty_handler(ngx_event_t *wev)
1899 {
1900 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
1901
1902 return;
1903 }
1904
1905
1906 ngx_int_t ngx_http_send_last(ngx_http_request_t *r)
1907 {
1908 ngx_buf_t *b;
1909 ngx_chain_t out;
1910
1911 if (!(b = ngx_calloc_buf(r->pool))) {
1912 return NGX_ERROR;
1913 }
1914
1915 b->last_buf = 1;
1916 out.buf = b;
1917 out.next = NULL;
1918
1919 return ngx_http_output_filter(r, &out);
1920 }
1921
1922
1923 void ngx_http_close_request(ngx_http_request_t *r, int error)
1924 {
1925 ngx_uint_t i;
1926 ngx_log_t *log;
1927 ngx_http_log_ctx_t *ctx;
1928 ngx_http_cleanup_t *cleanup;
1929 ngx_http_core_loc_conf_t *clcf;
1930 struct linger l;
1931
1932 log = r->connection->log;
1933
1934 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
1935
1936 if (r->pool == NULL) {
1937 ngx_log_error(NGX_LOG_ALERT, log, 0,
1938 "http request already closed");
1939 return;
1940 }
1941
1942 #if (NGX_STAT_STUB)
1943 if (r->stat_reading) {
1944 (*ngx_stat_reading)--;
1945 }
1946
1947 if (r->stat_writing) {
1948 (*ngx_stat_writing)--;
1949 }
1950 #endif
1951
1952 if (error && r->headers_out.status == 0) {
1953 r->headers_out.status = error;
1954 }
1955
1956 ngx_http_log_handler(r);
1957
1958 cleanup = r->cleanup.elts;
1959 for (i = 0; i < r->cleanup.nelts; i++) {
1960 if (!cleanup[i].valid) {
1961 continue;
1962 }
1963
1964 #if (NGX_HTTP_CACHE)
1965
1966 if (cleanup[i].cache) {
1967 ngx_http_cache_unlock(cleanup[i].data.cache.hash,
1968 cleanup[i].data.cache.cache, log);
1969 continue;
1970 }
1971
1972 #endif
1973
1974 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http cleanup fd: %d",
1975 cleanup[i].data.file.fd);
1976
1977 if (ngx_close_file(cleanup[i].data.file.fd) == NGX_FILE_ERROR) {
1978 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
1979 ngx_close_file_n " \"%s\" failed",
1980 cleanup[i].data.file.name);
1981 }
1982 }
1983
1984 /* STUB */
1985 if (r->file.fd != NGX_INVALID_FILE) {
1986 if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
1987 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
1988 ngx_close_file_n " \"%s\" failed", r->file.name.data);
1989 }
1990 }
1991
1992 if (r->request_body
1993 && r->request_body->temp_file
1994 && r->request_body->temp_file->file.fd != NGX_INVALID_FILE)
1995 {
1996 if (ngx_close_file(r->request_body->temp_file->file.fd)
1997 == NGX_FILE_ERROR)
1998 {
1999 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
2000 ngx_close_file_n " deleted file \"%s\" failed",
2001 r->request_body->temp_file->file.name.data);
2002 }
2003 }
2004
2005 if (r->connection->timedout) {
2006 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2007
2008 if (clcf->reset_timedout_connection) {
2009 l.l_onoff = 1;
2010 l.l_linger = 0;
2011
2012 if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
2013 (const void *) &l, sizeof(struct linger)) == -1)
2014 {
2015 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
2016 "setsockopt(SO_LINGER) failed");
2017 }
2018 }
2019 }
2020
2021 /* ctx->url was allocated from r->pool */
2022 ctx = log->data;
2023 ctx->url = NULL;
2024
2025 r->request_line.len = 0;
2026
2027 ngx_destroy_pool(r->pool);
2028
2029 return;
2030 }
2031
2032
2033 #if (NGX_HTTP_SSL)
2034
2035 void ngx_ssl_close_handler(ngx_event_t *ev)
2036 {
2037 ngx_connection_t *c;
2038
2039 c = ev->data;
2040
2041 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, "http ssl close handler");
2042
2043 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
2044 return;
2045 }
2046
2047 ngx_http_close_connection(c);
2048 }
2049
2050 #endif
2051
2052
2053 void ngx_http_close_connection(ngx_connection_t *c)
2054 {
2055 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
2056 "close http connection: %d", c->fd);
2057
2058 #if (NGX_STAT_STUB)
2059 (*ngx_stat_active)--;
2060 #endif
2061
2062 ngx_close_connection(c);
2063 }
2064
2065
2066 static void ngx_http_client_error(ngx_http_request_t *r,
2067 int client_error, int error)
2068 {
2069 ngx_http_log_ctx_t *ctx;
2070 ngx_http_core_srv_conf_t *cscf;
2071
2072 ctx = r->connection->log->data;
2073
2074 if (error == NGX_HTTP_REQUEST_TIME_OUT) {
2075 ngx_log_error(NGX_LOG_INFO, r->connection->log, NGX_ETIMEDOUT,
2076 "client timed out");
2077 r->connection->timedout = 1;
2078 ngx_http_close_request(r, error);
2079 ngx_http_close_connection(r->connection);
2080 return;
2081 }
2082
2083 r->connection->log->handler = NULL;
2084
2085 if (ctx->url) {
2086 switch (client_error) {
2087
2088 case NGX_HTTP_PARSE_INVALID_HOST:
2089 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2090 client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR],
2091 ctx->client, r->headers_in.host->value.data, ctx->url);
2092
2093 error = NGX_HTTP_INVALID_HOST;
2094
2095 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2096
2097 if (cscf->restrict_host_names == NGX_HTTP_RESTRICT_HOST_CLOSE) {
2098 ngx_http_close_request(r, error);
2099 ngx_http_close_connection(r->connection);
2100 return;
2101 }
2102
2103 break;
2104
2105 case NGX_HTTP_PARSE_HTTP_TO_HTTPS:
2106 error = NGX_HTTP_TO_HTTPS;
2107
2108 /* fall through */
2109
2110 default:
2111 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2112 client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR],
2113 ctx->client, ctx->url);
2114 }
2115
2116 } else {
2117 if (error == NGX_HTTP_REQUEST_URI_TOO_LARGE) {
2118 r->request_line.len = r->header_in->end - r->request_start;
2119 r->request_line.data = r->request_start;
2120 }
2121
2122 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2123 client_header_errors[client_error - NGX_HTTP_CLIENT_ERROR],
2124 ctx->client);
2125 }
2126
2127 r->connection->log->handler = ngx_http_log_error;
2128
2129 ngx_http_finalize_request(r, error);
2130 }
2131
2132
2133 static size_t ngx_http_log_error(void *data, char *buf, size_t len)
2134 {
2135 ngx_http_log_ctx_t *ctx = data;
2136
2137 if (ctx->action && ctx->url) {
2138 return ngx_snprintf(buf, len, " while %s, client: %s, URL: %s",
2139 ctx->action, ctx->client, ctx->url);
2140
2141 } else if (ctx->action == NULL && ctx->url) {
2142 return ngx_snprintf(buf, len, ", client: %s, URL: %s",
2143 ctx->client, ctx->url);
2144
2145 } else {
2146 return ngx_snprintf(buf, len, " while %s, client: %s",
2147 ctx->action, ctx->client);
2148 }
2149 }