comparison src/http/ngx_http_request.c @ 436:9549fc9508e5

nginx-0.0.11-2004-09-23-10:32:00 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 23 Sep 2004 06:32:00 +0000
parents 5cdc4838d4e8
children 470270fa84d2
comparison
equal deleted inserted replaced
435:5cdc4838d4e8 436:9549fc9508e5
10 static void ngx_http_ssl_handshake(ngx_event_t *rev); 10 static void ngx_http_ssl_handshake(ngx_event_t *rev);
11 #endif 11 #endif
12 static void ngx_http_process_request_line(ngx_event_t *rev); 12 static void ngx_http_process_request_line(ngx_event_t *rev);
13 static void ngx_http_process_request_headers(ngx_event_t *rev); 13 static void ngx_http_process_request_headers(ngx_event_t *rev);
14 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r); 14 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
15 static ngx_int_t ngx_http_alloc_header_buf(ngx_http_request_t *r, 15 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
16 ngx_uint_t request_line); 16 ngx_uint_t request_line);
17 static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r); 17 static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
18 18
19 static void ngx_http_set_write_handler(ngx_http_request_t *r); 19 static void ngx_http_set_write_handler(ngx_http_request_t *r);
20 20
21 static void ngx_http_block_read(ngx_event_t *ev); 21 static void ngx_http_block_read(ngx_event_t *ev);
193 193
194 ngx_http_close_connection(c); 194 ngx_http_close_connection(c);
195 return; 195 return;
196 } 196 }
197 197
198 if (c->data) { 198 hc = c->data;
199 hc = c->data; 199
200 r = hc->request; 200 if (hc == NULL) {
201 201 if (!(hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t)))) {
202
203 #if (NGX_STAT_STUB)
204 (*ngx_stat_reading)--;
205 #endif
206
207 ngx_http_close_connection(c);
208 return;
209 }
210 }
211
212 r = hc->request;
213
214 if (r) {
202 ngx_memzero(r, sizeof(ngx_http_request_t)); 215 ngx_memzero(r, sizeof(ngx_http_request_t));
203 216
204 r->pipeline = hc->pipeline; 217 r->pipeline = hc->pipeline;
218
219 if (hc->nbusy) {
220 r->header_in = hc->busy[0];
221 }
205 222
206 #if (NGX_STAT_STUB) 223 #if (NGX_STAT_STUB)
207 (*ngx_stat_reading)++; 224 (*ngx_stat_reading)++;
208 #endif 225 #endif
209 226
210 } else { 227 } 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 if (!(r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)))) { 228 if (!(r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)))) {
222 229
223 #if (NGX_STAT_STUB) 230 #if (NGX_STAT_STUB)
224 (*ngx_stat_reading)--; 231 (*ngx_stat_reading)--;
225 #endif 232 #endif
353 ngx_http_close_connection(c); 360 ngx_http_close_connection(c);
354 return; 361 return;
355 } 362 }
356 } 363 }
357 364
365 if (r->header_in == NULL) {
366 r->header_in = c->buffer;
367 }
368
358 if (!(r->pool = ngx_create_pool(cscf->request_pool_size, c->log))) { 369 if (!(r->pool = ngx_create_pool(cscf->request_pool_size, c->log))) {
359 ngx_http_close_connection(c); 370 ngx_http_close_connection(c);
360 return; 371 return;
361 } 372 }
362 373
385 return; 396 return;
386 } 397 }
387 398
388 c->single_connection = 1; 399 c->single_connection = 1;
389 r->connection = c; 400 r->connection = c;
390 r->header_in = c->buffer;
391 401
392 r->file.fd = NGX_INVALID_FILE; 402 r->file.fd = NGX_INVALID_FILE;
393 403
394 r->headers_in.content_length_n = -1; 404 r->headers_in.content_length_n = -1;
395 r->headers_in.keep_alive_n = -1; 405 r->headers_in.keep_alive_n = -1;
468 #endif 478 #endif
469 479
470 480
471 static void ngx_http_process_request_line(ngx_event_t *rev) 481 static void ngx_http_process_request_line(ngx_event_t *rev)
472 { 482 {
473 u_char *p; 483 u_char *p;
474 ssize_t n; 484 ssize_t n;
475 ngx_int_t rc, offset; 485 ngx_int_t rc, rv, offset;
476 ngx_connection_t *c; 486 ngx_connection_t *c;
477 ngx_http_request_t *r; 487 ngx_http_request_t *r;
478 ngx_http_log_ctx_t *ctx; 488 ngx_http_log_ctx_t *ctx;
479 ngx_http_core_srv_conf_t *cscf;
480 489
481 c = rev->data; 490 c = rev->data;
482 r = c->data; 491 r = c->data;
483 492
484 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, 493 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
487 if (rev->timedout) { 496 if (rev->timedout) {
488 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT); 497 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
489 return; 498 return;
490 } 499 }
491 500
492 n = ngx_http_read_request_header(r); 501 rc = NGX_AGAIN;
493 502
494 if (n == NGX_AGAIN || n == NGX_ERROR) { 503 for ( ;; ) {
495 return; 504
496 } 505 if (rc == NGX_AGAIN) {
497 506 n = ngx_http_read_request_header(r);
498 rc = ngx_http_parse_request_line(r, r->header_in); 507
499 508 if (n == NGX_AGAIN || n == NGX_ERROR) {
500 if (rc == NGX_OK) {
501
502 /* the request line has been parsed successfully */
503
504 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
505
506 if (r->http_version >= NGX_HTTP_VERSION_10
507 && cscf->large_client_header == 0
508 && r->header_in->pos == r->header_in->end)
509 {
510 /* no space for "\r\n" at the end of the header */
511
512 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
513 NGX_HTTP_REQUEST_URI_TOO_LARGE);
514 return;
515 }
516
517
518 /* copy unparsed URI */
519
520 r->unparsed_uri.len = r->uri_end - r->uri_start;
521 r->unparsed_uri.data = ngx_palloc(r->pool, r->unparsed_uri.len + 1);
522 if (r->unparsed_uri.data == NULL) {
523 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
524 ngx_http_close_connection(c);
525 return;
526 }
527
528 ngx_cpystrn(r->unparsed_uri.data, r->uri_start,
529 r->unparsed_uri.len + 1);
530
531
532 /* copy URI */
533
534 if (r->args_start) {
535 r->uri.len = r->args_start - 1 - r->uri_start;
536 } else {
537 r->uri.len = r->uri_end - r->uri_start;
538 }
539
540 if (!(r->uri.data = ngx_palloc(r->pool, r->uri.len + 1))) {
541 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
542 ngx_http_close_connection(c);
543 return;
544 }
545
546 if (r->complex_uri) {
547 rc = ngx_http_parse_complex_uri(r);
548
549 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
550 ngx_http_close_request(r, rc);
551 ngx_http_close_connection(c);
552 return; 509 return;
553 } 510 }
554 511 }
555 if (rc != NGX_OK) { 512
556 r->request_line.len = r->request_end - r->request_start; 513 rc = ngx_http_parse_request_line(r, r->header_in);
557 r->request_line.data = r->request_start; 514
558 515 if (rc == NGX_OK) {
559 ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST); 516
560 return; 517 /* the request line has been parsed successfully */
561 } 518
562 519 /* copy unparsed URI */
563 } else { 520
564 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); 521 r->unparsed_uri.len = r->uri_end - r->uri_start;
565 } 522 r->unparsed_uri.data = ngx_palloc(r->pool, r->unparsed_uri.len + 1);
566 523 if (r->unparsed_uri.data == NULL) {
567
568 r->request_line.len = r->request_end - r->request_start;
569
570 if (cscf->large_client_header) {
571
572 /*
573 * if the large client headers are enabled then
574 * we need to copy the request line
575 */
576
577 r->request_line.data = ngx_palloc(r->pool, r->request_line.len + 1);
578 if (r->request_line.data == NULL) {
579 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 524 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
580 ngx_http_close_connection(c); 525 ngx_http_close_connection(c);
581 return; 526 return;
582 } 527 }
583 528
584 ngx_cpystrn(r->request_line.data, r->request_start, 529 ngx_cpystrn(r->unparsed_uri.data, r->uri_start,
585 r->request_line.len + 1); 530 r->unparsed_uri.len + 1);
586 531
587 } else { 532
588 r->request_line.data = r->request_start; 533 /* copy URI */
589 r->request_line.data[r->request_line.len] = '\0';
590 }
591
592 if (r->method == 0) {
593 r->method_name.len = r->method_end - r->request_start + 1;
594 r->method_name.data = r->request_line.data;
595 }
596
597 if (r->uri_ext) {
598
599 /* copy URI extention */
600 534
601 if (r->args_start) { 535 if (r->args_start) {
602 r->exten.len = r->args_start - 1 - r->uri_ext; 536 r->uri.len = r->args_start - 1 - r->uri_start;
603 } else { 537 } else {
604 r->exten.len = r->uri_end - r->uri_ext; 538 r->uri.len = r->uri_end - r->uri_start;
605 } 539 }
606 540
607 if (!(r->exten.data = ngx_palloc(r->pool, r->exten.len + 1))) { 541 if (!(r->uri.data = ngx_palloc(r->pool, r->uri.len + 1))) {
608 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 542 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
609 ngx_http_close_connection(c); 543 ngx_http_close_connection(c);
610 return; 544 return;
611 } 545 }
612 546
613 ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1); 547 if (r->complex_uri) {
614 } 548 rc = ngx_http_parse_complex_uri(r);
615 549
616 if (r->args_start && r->uri_end > r->args_start) { 550 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
617 551 ngx_http_close_request(r, rc);
618 /* copy URI arguments */ 552 ngx_http_close_connection(c);
619 553 return;
620 r->args.len = r->uri_end - r->args_start; 554 }
621 555
622 if (!(r->args.data = ngx_palloc(r->pool, r->args.len + 1))) { 556 if (rc != NGX_OK) {
557 r->request_line.len = r->request_end - r->request_start;
558 r->request_line.data = r->request_start;
559
560 ngx_http_client_error(r, rc, NGX_HTTP_BAD_REQUEST);
561 return;
562 }
563
564 } else {
565 ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1);
566 }
567
568
569 r->request_line.len = r->request_end - r->request_start;
570 r->request_line.data = r->request_start;
571 r->request_line.data[r->request_line.len] = '\0';
572
573 if (r->method == 0) {
574 r->method_name.len = r->method_end - r->request_start + 1;
575 r->method_name.data = r->request_line.data;
576 }
577
578 if (r->uri_ext) {
579
580 /* copy URI extention */
581
582 if (r->args_start) {
583 r->exten.len = r->args_start - 1 - r->uri_ext;
584 } else {
585 r->exten.len = r->uri_end - r->uri_ext;
586 }
587
588 if (!(r->exten.data = ngx_palloc(r->pool, r->exten.len + 1))) {
589 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
590 ngx_http_close_connection(c);
591 return;
592 }
593
594 ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1);
595 }
596
597 if (r->args_start && r->uri_end > r->args_start) {
598
599 /* copy URI arguments */
600
601 r->args.len = r->uri_end - r->args_start;
602
603 if (!(r->args.data = ngx_palloc(r->pool, r->args.len + 1))) {
604 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
605 ngx_http_close_connection(c);
606 return;
607 }
608
609 ngx_cpystrn(r->args.data, r->args_start, r->args.len + 1);
610 }
611
612 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
613 "http request line: \"%s\"", r->request_line.data);
614
615 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
616 "http uri: \"%s\"", r->uri.data);
617
618 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
619 "http args: \"%s\"",
620 r->args.data ? r->args.data : (u_char *) "");
621
622 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
623 "http exten: \"%s\"",
624 r->exten.data ? r->exten.data : (u_char *) "");
625
626 if (r->http_version < NGX_HTTP_VERSION_10) {
627 rev->event_handler = ngx_http_block_read;
628 ngx_http_handler(r);
629 return;
630 }
631
632
633 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
634 sizeof(ngx_table_elt_t)) == NGX_ERROR)
635 {
623 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 636 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
624 ngx_http_close_connection(c); 637 ngx_http_close_connection(c);
625 return; 638 return;
626 } 639 }
627 640
628 ngx_cpystrn(r->args.data, r->args_start, r->args.len + 1); 641
629 } 642 if (ngx_array_init(&r->headers_in.cookies, r->pool, 5,
630 643 sizeof(ngx_table_elt_t *)) == NGX_ERROR)
631 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 644 {
632 "http request line: \"%s\"", r->request_line.data); 645 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
633 646 ngx_http_close_connection(c);
634 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 647 return;
635 "http uri: \"%s\"", r->uri.data); 648 }
636 649
637 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 650
638 "http args: \"%s\"", 651 ctx = c->log->data;
639 r->args.data ? r->args.data : (u_char *) ""); 652 ctx->action = "reading client request headers";
640 653 ctx->url = r->unparsed_uri.data;
641 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 654
642 "http exten: \"%s\"", 655 rev->event_handler = ngx_http_process_request_headers;
643 r->exten.data ? r->exten.data : (u_char *) ""); 656 ngx_http_process_request_headers(rev);
644 657
645 if (r->http_version < NGX_HTTP_VERSION_10) {
646 rev->event_handler = ngx_http_block_read;
647 ngx_http_handler(r);
648 return; 658 return;
649 } 659
650 660 } else if (rc != NGX_AGAIN) {
651 661
652 if (ngx_list_init(&r->headers_in.headers, r->pool, 20, 662 /* there was error while a request line parsing */
653 sizeof(ngx_table_elt_t)) == NGX_ERROR) 663
654 { 664 for (p = r->request_start; p < r->header_in->last; p++) {
655 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 665 if (*p == CR || *p == LF) {
656 ngx_http_close_connection(c); 666 break;
667 }
668 }
669
670 r->request_line.len = p - r->request_start;
671 r->request_line.data = r->request_start;
672
673 if (rc == NGX_HTTP_PARSE_INVALID_METHOD) {
674 r->http_version = NGX_HTTP_VERSION_10;
675 }
676
677 ngx_http_client_error(r, rc,
678 (rc == NGX_HTTP_PARSE_INVALID_METHOD) ?
679 NGX_HTTP_NOT_IMPLEMENTED:
680 NGX_HTTP_BAD_REQUEST);
657 return; 681 return;
658 } 682 }
659 683
660 684 /* NGX_AGAIN: a request line parsing is still incomplete */
661 if (ngx_array_init(&r->headers_in.cookies, r->pool, 5, 685
662 sizeof(ngx_table_elt_t *)) == NGX_ERROR) 686 if (r->header_in->last == r->header_in->end) {
663 { 687
664 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 688 rv = ngx_http_alloc_large_header_buffer(r, 1);
665 ngx_http_close_connection(c); 689
666 return; 690 if (rv == NGX_ERROR) {
667 } 691 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
668 692 ngx_http_close_connection(c);
669 693 return;
670 ctx = c->log->data; 694 }
671 ctx->action = "reading client request headers"; 695
672 ctx->url = r->unparsed_uri.data; 696 if (rv == NGX_DECLINED) {
673
674 if (cscf->large_client_header
675 && r->header_in->pos == r->header_in->last)
676 {
677 r->header_in->pos = r->header_in->last = r->header_in->start;
678 }
679
680 rev->event_handler = ngx_http_process_request_headers;
681 ngx_http_process_request_headers(rev);
682
683 return;
684
685 } else if (rc != NGX_AGAIN) {
686
687 /* there was error while a request line parsing */
688
689 for (p = r->request_start; p < r->header_in->last; p++) {
690 if (*p == CR || *p == LF) {
691 break;
692 }
693 }
694
695 r->request_line.len = p - r->request_start;
696 r->request_line.data = r->request_start;
697
698 if (rc == NGX_HTTP_PARSE_INVALID_METHOD) {
699 r->http_version = NGX_HTTP_VERSION_10;
700 }
701
702 ngx_http_client_error(r, rc,
703 (rc == NGX_HTTP_PARSE_INVALID_METHOD) ?
704 NGX_HTTP_NOT_IMPLEMENTED:
705 NGX_HTTP_BAD_REQUEST);
706 return;
707 }
708
709 /* NGX_AGAIN: a request line parsing is still not complete */
710
711 if (r->header_in->last == r->header_in->end) {
712
713 /*
714 * If it's a pipelined request and a request line is not complete
715 * then we have to copy it to the start of the r->header_in buf.
716 * We have to copy it here only if the large client headers
717 * are enabled otherwise a request line had been already copied
718 * to the start of the r->header_in buf in ngx_http_set_keepalive().
719 */
720
721 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
722
723 if (cscf->large_client_header) {
724 offset = r->request_start - r->header_in->start;
725
726 if (offset == 0) {
727 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI, 697 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
728 NGX_HTTP_REQUEST_URI_TOO_LARGE); 698 NGX_HTTP_REQUEST_URI_TOO_LARGE);
729 return; 699 return;
730 } 700 }
731 701 }
732 ngx_memcpy(r->header_in->start, r->request_start, 702 }
733 r->header_in->last - r->request_start);
734
735 r->header_in->pos -= offset;
736 r->header_in->last -= offset;
737 r->request_start = r->header_in->start;
738 r->request_end -= offset;
739 r->uri_start -= offset;
740 r->uri_end -= offset;
741 if (r->uri_ext) {
742 r->uri_ext -= offset;
743 }
744 if (r->args_start) {
745 r->args_start -= offset;
746 }
747
748 } else {
749 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_URI,
750 NGX_HTTP_REQUEST_URI_TOO_LARGE);
751 }
752 }
753
754 return;
755 } 703 }
756 704
757 705
758 static void ngx_http_process_request_headers(ngx_event_t *rev) 706 static void ngx_http_process_request_headers(ngx_event_t *rev)
759 { 707 {
760 ssize_t n; 708 ssize_t n;
761 ngx_int_t rc, i, offset; 709 ngx_int_t rc, rv, i, offset;
762 ngx_table_elt_t *h, **cookie; 710 ngx_table_elt_t *h, **cookie;
763 ngx_connection_t *c; 711 ngx_connection_t *c;
764 ngx_http_request_t *r; 712 ngx_http_request_t *r;
765 ngx_http_core_srv_conf_t *cscf;
766 713
767 c = rev->data; 714 c = rev->data;
768 r = c->data; 715 r = c->data;
769 716
770 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, 717 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
773 if (rev->timedout) { 720 if (rev->timedout) {
774 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT); 721 ngx_http_client_error(r, 0, NGX_HTTP_REQUEST_TIME_OUT);
775 return; 722 return;
776 } 723 }
777 724
778 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
779
780 rc = NGX_AGAIN; 725 rc = NGX_AGAIN;
781 726
782 for ( ;; ) { 727 for ( ;; ) {
728
783 if (rc == NGX_AGAIN) { 729 if (rc == NGX_AGAIN) {
730
731 if (r->header_in->last == r->header_in->end) {
732
733 rv = ngx_http_alloc_large_header_buffer(r, 0);
734
735 if (rv == NGX_ERROR) {
736 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
737 ngx_http_close_connection(c);
738 return;
739 }
740
741 if (rv == NGX_DECLINED) {
742 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER,
743 NGX_HTTP_BAD_REQUEST);
744 return;
745 }
746 }
747
784 n = ngx_http_read_request_header(r); 748 n = ngx_http_read_request_header(r);
785 749
786 if (n == NGX_AGAIN || n == NGX_ERROR) { 750 if (n == NGX_AGAIN || n == NGX_ERROR) {
787 return; 751 return;
788 } 752 }
807 ngx_http_close_connection(c); 771 ngx_http_close_connection(c);
808 return; 772 return;
809 } 773 }
810 774
811 h->key.len = r->header_name_end - r->header_name_start; 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
812 h->value.len = r->header_end - r->header_start; 779 h->value.len = r->header_end - r->header_start;
813 780 h->value.data = r->header_start;
814 /* if the large client headers are enabled then 781 h->value.data[h->value.len] = '\0';
815 we need to copy the header name and value */
816
817 if (cscf->large_client_header) {
818 h->key.data = ngx_palloc(r->pool,
819 h->key.len + 1 + h->value.len + 1);
820 if (h->key.data == NULL) {
821 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
822 ngx_http_close_connection(c);
823 return;
824 }
825
826 h->value.data = h->key.data + h->key.len + 1;
827 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
828 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
829
830 } else {
831 h->key.data = r->header_name_start;
832 h->key.data[h->key.len] = '\0';
833 h->value.data = r->header_start;
834 h->value.data[h->value.len] = '\0';
835 }
836 782
837 if (h->key.len == sizeof("Cookie") - 1 783 if (h->key.len == sizeof("Cookie") - 1
838 && ngx_strcasecmp(h->key.data, "Cookie") == 0) 784 && ngx_strcasecmp(h->key.data, "Cookie") == 0)
839 { 785 {
840 if (!(cookie = ngx_push_array(&r->headers_in.cookies))) { 786 if (!(cookie = ngx_array_push(&r->headers_in.cookies))) {
841 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 787 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
842 ngx_http_close_connection(c); 788 ngx_http_close_connection(c);
843 return; 789 return;
844 } 790 }
845 791
863 } 809 }
864 810
865 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 811 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
866 "http header: \"%s: %s\"", 812 "http header: \"%s: %s\"",
867 h->key.data, h->value.data); 813 h->key.data, h->value.data);
868
869 if (cscf->large_client_header
870 && r->header_in->pos == r->header_in->last)
871 {
872 r->header_in->pos = r->header_in->last = r->header_in->start;
873 }
874 814
875 continue; 815 continue;
876 816
877 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { 817 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
878 818
933 return; 873 return;
934 } 874 }
935 875
936 /* NGX_AGAIN: a header line parsing is still not complete */ 876 /* NGX_AGAIN: a header line parsing is still not complete */
937 877
938 if (r->header_in->last == r->header_in->end) {
939
940 #if 1
941 /* ngx_http_alloc_large_header_buffer() */
942
943 rc = ngx_http_alloc_header_buf(r, 0);
944
945 if (rc == NGX_ERROR) {
946 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
947 ngx_http_close_connection(c);
948 return;
949 }
950
951 if (rc == NGX_DECLINED) {
952 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER,
953 NGX_HTTP_BAD_REQUEST);
954 return;
955 }
956 #endif
957
958 #if 0
959 /*
960 * if the large client headers are enabled then
961 * we need to compact r->header_in buf
962 */
963
964 if (cscf->large_client_header) {
965 offset = r->header_name_start - r->header_in->start;
966
967 if (offset == 0) {
968 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER,
969 NGX_HTTP_BAD_REQUEST);
970 return;
971 }
972
973 ngx_memcpy(r->header_in->start, r->header_name_start,
974 r->header_in->last - r->header_name_start);
975
976 r->header_in->last -= offset;
977 r->header_in->pos -= offset;
978 r->header_name_start = r->header_in->start;
979 r->header_name_end -= offset;
980 r->header_start -= offset;
981 r->header_end -= offset;
982
983 } else {
984 ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER,
985 NGX_HTTP_BAD_REQUEST);
986 return;
987 }
988 #endif
989 }
990 } 878 }
991 } 879 }
992 880
993 881
994 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r) 882 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
1043 931
1044 return n; 932 return n;
1045 } 933 }
1046 934
1047 935
1048 #if 1 936 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
1049 937 ngx_uint_t request_line)
1050 static ngx_int_t ngx_http_alloc_header_buf(ngx_http_request_t *r,
1051 ngx_uint_t request_line)
1052 { 938 {
1053 u_char *old, *new; 939 u_char *old, *new;
1054 ngx_int_t offset; 940 ngx_int_t offset;
1055 ngx_buf_t *b; 941 ngx_buf_t *b;
1056 ngx_http_connection_t *hc; 942 ngx_http_connection_t *hc;
1057 ngx_http_core_srv_conf_t *cscf; 943 ngx_http_core_srv_conf_t *cscf;
1058 944
1059 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 945 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1060 "http alloc large header buffer"); 946 "http alloc large header buffer");
1061 947
948 if (request_line && r->state == 0) {
949
950 /* the client fills up the buffer with "\r\n" */
951
952 r->header_in->pos = r->header_in->start;
953 r->header_in->last = r->header_in->start;
954
955 return NGX_OK;
956 }
957
1062 old = request_line ? r->request_start : r->header_name_start; 958 old = request_line ? r->request_start : r->header_name_start;
1063 959
1064 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); 960 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1065 961
1066 if ((size_t) (r->header_in->pos - old) >= cscf->client_large_buffers.size) { 962 if (r->state != 0
963 && (size_t) (r->header_in->pos - old)
964 >= cscf->large_client_header_buffers.size)
965 {
1067 return NGX_DECLINED; 966 return NGX_DECLINED;
1068 } 967 }
1069 968
1070 hc = r->http_connection; 969 hc = r->http_connection;
1071 970
1072 if (hc->nfree) { 971 if (hc->nfree) {
1073 b = hc->free[--hc->nfree]; 972 b = hc->free[--hc->nfree];
1074 973
1075 } else if (hc->nbusy < cscf->client_large_buffers.num) { 974 } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
1076 975
1077 if (hc->busy == NULL) { 976 if (hc->busy == NULL) {
1078 hc->busy = ngx_palloc(r->connection->pool, 977 hc->busy = ngx_palloc(r->connection->pool,
1079 cscf->client_large_buffers.num * sizeof(ngx_buf_t *)); 978 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
1080 if (hc->busy == NULL) { 979 if (hc->busy == NULL) {
1081 return NGX_ERROR; 980 return NGX_ERROR;
1082 } 981 }
1083 } 982 }
1084 983
1085 b = ngx_create_temp_buf(r->connection->pool, 984 b = ngx_create_temp_buf(r->connection->pool,
1086 cscf->client_large_buffers.size); 985 cscf->large_client_header_buffers.size);
1087 if (b == NULL) { 986 if (b == NULL) {
1088 return NGX_ERROR; 987 return NGX_ERROR;
1089 } 988 }
1090 989
1091 } else { 990 } else {
1092 return NGX_DECLINED; 991 return NGX_DECLINED;
1093 } 992 }
1094 993
1095 hc->busy[hc->nbusy++] = b; 994 hc->busy[hc->nbusy++] = b;
1096 995
996 if (r->state == 0) {
997 /*
998 * r->state == 0 means that a header line was parsed successfully
999 * and we do not need to copy incomplete header line and
1000 * to relocate the parser header pointers
1001 */
1002
1003 r->header_in = b;
1004
1005 return NGX_OK;
1006 }
1007
1097 new = b->start; 1008 new = b->start;
1098 1009
1099 ngx_memcpy(new, old, r->header_in->last - old); 1010 ngx_memcpy(new, old, r->header_in->last - old);
1100 1011
1101 b->pos = new + (r->header_in->pos - old); 1012 b->pos = new + (r->header_in->pos - old);
1102 b->last = new + (r->header_in->last - old); 1013 b->last = new + (r->header_in->last - old);
1103 1014
1104 if (request_line) { 1015 if (request_line) {
1105 r->request_start = new; 1016 r->request_start = new;
1106 r->request_end = new + (r->request_end - old); 1017
1018 if (r->request_end) {
1019 r->request_end = new + (r->request_end - old);
1020 }
1021
1022 r->method_end = new + (r->method_end - old);
1107 1023
1108 r->uri_start = new + (r->uri_start - old); 1024 r->uri_start = new + (r->uri_start - old);
1109 r->uri_end = new + (r->uri_end - old); 1025 r->uri_end = new + (r->uri_end - old);
1026
1027 if (r->schema_start) {
1028 r->schema_start = new + (r->schema_start - old);
1029 r->schema_end = new + (r->schema_end - old);
1030 }
1031
1032 if (r->host_start) {
1033 r->host_start = new + (r->host_start - old);
1034 r->host_end = new + (r->host_end - old);
1035 }
1036
1037 if (r->port_start) {
1038 r->port_start = new + (r->port_start - old);
1039 r->port_end = new + (r->port_end - old);
1040 }
1110 1041
1111 if (r->uri_ext) { 1042 if (r->uri_ext) {
1112 r->uri_ext = new + (r->uri_ext - old); 1043 r->uri_ext = new + (r->uri_ext - old);
1113 } 1044 }
1114 1045
1125 1056
1126 r->header_in = b; 1057 r->header_in = b;
1127 1058
1128 return NGX_OK; 1059 return NGX_OK;
1129 } 1060 }
1130
1131 #endif
1132 1061
1133 1062
1134 static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r) 1063 static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r)
1135 { 1064 {
1136 u_char *ua, *user_agent; 1065 u_char *ua, *user_agent;
1557 } 1486 }
1558 1487
1559 1488
1560 static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r) 1489 static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r)
1561 { 1490 {
1562 ssize_t size, n; 1491 ssize_t size, n;
1563 ngx_http_core_loc_conf_t *clcf; 1492 u_char buffer[NGX_HTTP_DISCARD_BUFFER_SIZE];
1564 1493
1565 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 1494 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1566 "http read discarded body"); 1495 "http read discarded body");
1567 1496
1568 if (r->headers_in.content_length_n == 0) { 1497 if (r->headers_in.content_length_n == 0) {
1569 return NGX_OK; 1498 return NGX_OK;
1570 } 1499 }
1571 1500
1572 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1573
1574 if (r->discarded_buffer == NULL) {
1575 r->discarded_buffer = ngx_palloc(r->pool, clcf->discarded_buffer_size);
1576 if (r->discarded_buffer == NULL) {
1577 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1578 }
1579 }
1580 1501
1581 size = r->headers_in.content_length_n; 1502 size = r->headers_in.content_length_n;
1582 1503
1583 if (size > (ssize_t) clcf->discarded_buffer_size) { 1504 if (size > NGX_HTTP_DISCARD_BUFFER_SIZE) {
1584 size = (ssize_t) clcf->discarded_buffer_size; 1505 size = NGX_HTTP_DISCARD_BUFFER_SIZE;
1585 } 1506 }
1586 1507
1587 n = r->connection->recv(r->connection, r->discarded_buffer, size); 1508 n = r->connection->recv(r->connection, buffer, size);
1588 1509
1589 if (n == NGX_ERROR) { 1510 if (n == NGX_ERROR) {
1590 1511
1591 r->closed = 1; 1512 r->closed = 1;
1592 1513
1593 /* 1514 /*
1594 * when a client request body is discarded then we already set 1515 * if a client request body is discarded then we already set
1595 * some HTTP response code for client and we can ignore the error 1516 * some HTTP response code for client and we can ignore the error
1596 */ 1517 */
1597 1518
1598 return NGX_OK; 1519 return NGX_OK;
1599 } 1520 }
1608 } 1529 }
1609 1530
1610 1531
1611 static void ngx_http_set_keepalive(ngx_http_request_t *r) 1532 static void ngx_http_set_keepalive(ngx_http_request_t *r)
1612 { 1533 {
1534 ngx_int_t i;
1613 size_t len; 1535 size_t len;
1614 ngx_buf_t *b; 1536 ngx_buf_t *b, *f;
1615 ngx_event_t *rev, *wev; 1537 ngx_event_t *rev, *wev;
1616 ngx_connection_t *c; 1538 ngx_connection_t *c;
1617 ngx_http_connection_t *hc; 1539 ngx_http_connection_t *hc;
1618 ngx_http_log_ctx_t *ctx; 1540 ngx_http_log_ctx_t *ctx;
1619 ngx_http_core_srv_conf_t *cscf; 1541 ngx_http_core_srv_conf_t *cscf;
1626 1548
1627 ctx = (ngx_http_log_ctx_t *) c->log->data; 1549 ctx = (ngx_http_log_ctx_t *) c->log->data;
1628 ctx->action = "closing request"; 1550 ctx->action = "closing request";
1629 1551
1630 hc = r->http_connection; 1552 hc = r->http_connection;
1553 b = r->header_in;
1554
1555 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1556
1557 if (b->pos < b->last || clcf->keepalive_buffers) {
1558
1559 /*
1560 * the pipelined request or we like to keep the allocated
1561 * ngx_http_request_t and the client header buffers while keepalive
1562 */
1563
1564 if (b != c->buffer) {
1565
1566 /* move the large header buffers to the free list */
1567
1568 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1569
1570 if (hc->free == NULL) {
1571 hc->free = ngx_palloc(c->pool,
1572 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
1573 if (hc->free == NULL) {
1574 ngx_http_close_connection(c);
1575 return;
1576 }
1577 }
1578
1579 for (i = 0; i < hc->nbusy - 1; i++) {
1580 f = hc->busy[i];
1581 hc->free[hc->nfree++] = f;
1582 f->pos = f->start;
1583 f->last = f->start;
1584 }
1585
1586 hc->busy[0] = b;
1587 hc->nbusy = 1;
1588 }
1589 }
1590
1631 ngx_http_close_request(r, 0); 1591 ngx_http_close_request(r, 0);
1632 c->data = hc; 1592 c->data = hc;
1633 1593
1634 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1635 ngx_add_timer(rev, clcf->keepalive_timeout); 1594 ngx_add_timer(rev, clcf->keepalive_timeout);
1636 1595
1637 if (ngx_handle_level_read_event(rev) == NGX_ERROR) { 1596 if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
1638 ngx_http_close_connection(c); 1597 ngx_http_close_connection(c);
1639 return; 1598 return;
1640 } 1599 }
1641 1600
1642 b = c->buffer;
1643 wev = c->write; 1601 wev = c->write;
1644 wev->event_handler = ngx_http_empty_handler; 1602 wev->event_handler = ngx_http_empty_handler;
1645 1603
1646
1647 if (b->pos < b->last) { 1604 if (b->pos < b->last) {
1648 1605
1649 /* 1606 /* the pipelined request */
1650 * The pipelined request.
1651 *
1652 * We do not know here whether the pipelined request is complete
1653 * so if the large client headers are not enabled
1654 * we need to copy the data to the start of c->buffer.
1655 * This copy should be rare because clients that support
1656 * pipelined requests (Mozilla 1.x, Opera 6.x+) are still rare.
1657 */
1658
1659 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1660
1661 if (!cscf->large_client_header) {
1662 len = b->last - b->pos;
1663 ngx_memcpy(b->start, b->pos, len);
1664 b->pos = b->start;
1665 b->last = b->start + len;
1666 }
1667 1607
1668 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request"); 1608 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
1669 1609
1670 hc->pipeline = 1; 1610 hc->pipeline = 1;
1671 ctx->action = "reading client pipelined request line"; 1611 ctx->action = "reading client pipelined request line";
1674 } 1614 }
1675 1615
1676 hc->pipeline = 0; 1616 hc->pipeline = 0;
1677 1617
1678 b->pos = b->last = b->start; 1618 b->pos = b->last = b->start;
1619
1620 if (!clcf->keepalive_buffers) {
1621
1622 if (ngx_pfree(c->pool, r) == NGX_OK) {
1623 hc->request = NULL;
1624 }
1625
1626 if (ngx_pfree(c->pool, c->buffer->start) == NGX_OK) {
1627 c->buffer = NULL;
1628 }
1629
1630 if (hc->free) {
1631 for (i = 0; i < hc->nfree; i++) {
1632 ngx_pfree(c->pool, hc->free[i]);
1633 hc->free[i] = NULL;
1634 }
1635
1636 hc->nfree = 0;
1637 }
1638
1639 if (hc->busy) {
1640 for (i = 0; i < hc->nbusy; i++) {
1641 ngx_pfree(c->pool, hc->busy[i]);
1642 hc->busy[i] = NULL;
1643 }
1644
1645 hc->nbusy = 0;
1646 }
1647 }
1648
1679 rev->event_handler = ngx_http_keepalive_handler; 1649 rev->event_handler = ngx_http_keepalive_handler;
1680 1650
1681 if (wev->active) { 1651 if (wev->active) {
1682 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { 1652 if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
1683 if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_DISABLE_EVENT) 1653 if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_DISABLE_EVENT)
1704 return; 1674 return;
1705 } 1675 }
1706 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; 1676 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
1707 } 1677 }
1708 1678
1679 #if 0
1680 /* if "keepalive_buffers off" then we need some other place */
1709 r->http_state = NGX_HTTP_KEEPALIVE_STATE; 1681 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
1682 #endif
1710 1683
1711 if (rev->ready) { 1684 if (rev->ready) {
1712 ngx_http_keepalive_handler(rev); 1685 ngx_http_keepalive_handler(rev);
1713 } 1686 }
1714 } 1687 }
1715 1688
1716 1689
1717 static void ngx_http_keepalive_handler(ngx_event_t *rev) 1690 static void ngx_http_keepalive_handler(ngx_event_t *rev)
1718 { 1691 {
1719 ssize_t n; 1692 ssize_t n;
1720 ngx_connection_t *c; 1693 ngx_buf_t *b;
1721 ngx_http_log_ctx_t *ctx; 1694 ngx_connection_t *c;
1695 ngx_http_log_ctx_t *ctx;
1696 ngx_http_connection_t *hc;
1722 1697
1723 c = rev->data; 1698 c = rev->data;
1724 1699
1725 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler"); 1700 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
1726 1701
1727 if (rev->timedout) { 1702 if (rev->timedout) {
1728 ngx_http_close_connection(c); 1703 ngx_http_close_connection(c);
1729 return; 1704 return;
1730 } 1705 }
1706
1707 hc = c->data;
1708 b = hc->nbusy ? hc->busy[0] : c->buffer;
1731 1709
1732 /* 1710 /*
1733 * MSIE closes a keepalive connection with RST flag 1711 * MSIE closes a keepalive connection with RST flag
1734 * so we ignore ECONNRESET here. 1712 * so we ignore ECONNRESET here.
1735 */ 1713 */
1736 1714
1737 c->log_error = NGX_ERROR_IGNORE_ECONNRESET; 1715 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
1738 ngx_set_socket_errno(0); 1716 ngx_set_socket_errno(0);
1739 1717
1740 n = c->recv(c, c->buffer->last, c->buffer->end - c->buffer->last); 1718 n = c->recv(c, b->last, b->end - b->last);
1741 c->log_error = NGX_ERROR_INFO; 1719 c->log_error = NGX_ERROR_INFO;
1742 1720
1743 if (n == NGX_AGAIN) { 1721 if (n == NGX_AGAIN) {
1744 return; 1722 return;
1745 } 1723 }
1757 "client %s closed keepalive connection", ctx->client); 1735 "client %s closed keepalive connection", ctx->client);
1758 ngx_http_close_connection(c); 1736 ngx_http_close_connection(c);
1759 return; 1737 return;
1760 } 1738 }
1761 1739
1762 c->buffer->last += n; 1740 b->last += n;
1763 rev->log->handler = ngx_http_log_error; 1741 rev->log->handler = ngx_http_log_error;
1764 ctx->action = "reading client request line"; 1742 ctx->action = "reading client request line";
1765
1766 #if 0
1767 if (!(hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t)) {
1768 ngx_http_close_connection(c);
1769 return;
1770 }
1771
1772 hc->request = r;
1773 c->data = r;
1774 #endif
1775 1743
1776 ngx_http_init_request(rev); 1744 ngx_http_init_request(rev);
1777 } 1745 }
1778 1746
1779 1747
1838 ssize_t n; 1806 ssize_t n;
1839 ngx_msec_t timer; 1807 ngx_msec_t timer;
1840 ngx_connection_t *c; 1808 ngx_connection_t *c;
1841 ngx_http_request_t *r; 1809 ngx_http_request_t *r;
1842 ngx_http_core_loc_conf_t *clcf; 1810 ngx_http_core_loc_conf_t *clcf;
1811 u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
1843 1812
1844 c = rev->data; 1813 c = rev->data;
1845 r = c->data; 1814 r = c->data;
1846 1815
1847 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, 1816 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1858 ngx_http_close_request(r, 0); 1827 ngx_http_close_request(r, 0);
1859 ngx_http_close_connection(c); 1828 ngx_http_close_connection(c);
1860 return; 1829 return;
1861 } 1830 }
1862 1831
1863 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1864
1865 if (r->discarded_buffer == NULL) {
1866
1867 /* TODO: r->header_in->start (if large headers are enabled)
1868 or the end of parsed header (otherwise)
1869 instead of r->header_in->last */
1870
1871 if (r->header_in->end - r->header_in->last
1872 >= (ssize_t) clcf->discarded_buffer_size)
1873 {
1874 r->discarded_buffer = r->header_in->last;
1875
1876 } else {
1877 r->discarded_buffer = ngx_palloc(c->pool,
1878 clcf->discarded_buffer_size);
1879 if (r->discarded_buffer) {
1880 ngx_http_close_request(r, 0);
1881 ngx_http_close_connection(c);
1882 return;
1883 }
1884 }
1885 }
1886
1887 do { 1832 do {
1888 n = c->recv(c, r->discarded_buffer, clcf->discarded_buffer_size); 1833 n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
1889 1834
1890 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n); 1835 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
1891 1836
1892 if (n == NGX_ERROR || n == 0) { 1837 if (n == NGX_ERROR || n == 0) {
1893 ngx_http_close_request(r, 0); 1838 ngx_http_close_request(r, 0);
1895 return; 1840 return;
1896 } 1841 }
1897 1842
1898 } while (rev->ready); 1843 } while (rev->ready);
1899 1844
1845 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1846
1900 timer *= 1000; 1847 timer *= 1000;
1848
1901 if (timer > clcf->lingering_timeout) { 1849 if (timer > clcf->lingering_timeout) {
1902 timer = clcf->lingering_timeout; 1850 timer = clcf->lingering_timeout;
1903 } 1851 }
1904 1852
1905 ngx_add_timer(rev, timer); 1853 ngx_add_timer(rev, timer);