Mercurial > hg > nginx
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); |