Mercurial > hg > nginx-mail
comparison src/http/ngx_http_core_module.c @ 230:38e7b94d63ac NGINX_0_4_0
nginx 0.4.0
*) Change in internal API: the HTTP modules initialization was moved
from the init module phase to the HTTP postconfiguration phase.
*) Change: now the request body is not read beforehand for the
ngx_http_perl_module: it's required to start the reading using the
$r->has_request_body method.
*) Feature: the ngx_http_perl_module supports the DECLINED return code.
*) Feature: the ngx_http_dav_module supports the incoming "Date" header
line for the PUT method.
*) Feature: the "ssi" directive is available inside the "if" block.
*) Bugfix: a segmentation fault occurred if there was an "index"
directive with variables and the first index name was without
variables; bug appeared in 0.1.29.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Wed, 30 Aug 2006 00:00:00 +0400 |
parents | 9eebc1b2cdbb |
children | c982febb7588 |
comparison
equal
deleted
inserted
replaced
229:1965c8e23be7 | 230:38e7b94d63ac |
---|---|
21 #define NGX_HTTP_LOCATION_AUTO_REDIRECT 2 | 21 #define NGX_HTTP_LOCATION_AUTO_REDIRECT 2 |
22 #define NGX_HTTP_LOCATION_NOREGEX 3 | 22 #define NGX_HTTP_LOCATION_NOREGEX 3 |
23 #define NGX_HTTP_LOCATION_REGEX 4 | 23 #define NGX_HTTP_LOCATION_REGEX 4 |
24 | 24 |
25 | 25 |
26 static void ngx_http_core_run_phases(ngx_http_request_t *r); | |
27 static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r, | 26 static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r, |
28 ngx_array_t *locations, size_t len); | 27 ngx_array_t *locations, size_t len); |
29 | 28 |
30 static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf); | 29 static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf); |
31 static void *ngx_http_core_create_main_conf(ngx_conf_t *cf); | 30 static void *ngx_http_core_create_main_conf(ngx_conf_t *cf); |
472 | 471 |
473 | 472 |
474 void | 473 void |
475 ngx_http_handler(ngx_http_request_t *r) | 474 ngx_http_handler(ngx_http_request_t *r) |
476 { | 475 { |
476 ngx_http_core_main_conf_t *cmcf; | |
477 | |
477 r->connection->log->action = NULL; | 478 r->connection->log->action = NULL; |
478 | 479 |
479 r->connection->unexpected_eof = 0; | 480 r->connection->unexpected_eof = 0; |
480 | 481 |
481 if (!r->internal) { | 482 if (!r->internal) { |
498 } | 499 } |
499 | 500 |
500 if (r->keepalive && r->headers_in.msie && r->method == NGX_HTTP_POST) { | 501 if (r->keepalive && r->headers_in.msie && r->method == NGX_HTTP_POST) { |
501 | 502 |
502 /* | 503 /* |
503 * MSIE may wait for some time if the response for | 504 * MSIE may wait for some time if an response for |
504 * the POST request is sent over the keepalive connection | 505 * a POST request was sent over a keepalive connection |
505 */ | 506 */ |
506 | 507 |
507 r->keepalive = 0; | 508 r->keepalive = 0; |
508 } | 509 } |
509 | 510 |
513 } else { | 514 } else { |
514 r->lingering_close = 0; | 515 r->lingering_close = 0; |
515 } | 516 } |
516 } | 517 } |
517 | 518 |
518 r->write_event_handler = ngx_http_core_run_phases; | |
519 | |
520 r->valid_unparsed_uri = 1; | 519 r->valid_unparsed_uri = 1; |
521 r->valid_location = 1; | 520 r->valid_location = 1; |
522 r->uri_changed = 1; | 521 |
523 | 522 if (!r->internal) { |
524 r->phase = (!r->internal) ? NGX_HTTP_POST_READ_PHASE: | 523 r->phase_handler = 0; |
525 NGX_HTTP_SERVER_REWRITE_PHASE; | 524 |
526 r->phase_handler = 0; | 525 } else { |
527 | 526 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); |
527 r->phase_handler = cmcf->phase_engine.server_rewrite_index; | |
528 } | |
529 | |
530 r->write_event_handler = ngx_http_core_run_phases; | |
528 ngx_http_core_run_phases(r); | 531 ngx_http_core_run_phases(r); |
529 } | 532 } |
530 | 533 |
531 | 534 |
532 static void | 535 void |
533 ngx_http_core_run_phases(ngx_http_request_t *r) | 536 ngx_http_core_run_phases(ngx_http_request_t *r) |
534 { | 537 { |
535 ngx_int_t rc; | 538 ngx_int_t rc; |
536 ngx_str_t path; | 539 ngx_http_phase_handler_t *ph; |
537 ngx_http_handler_pt *h; | |
538 ngx_http_core_loc_conf_t *clcf; | |
539 ngx_http_core_main_conf_t *cmcf; | 540 ngx_http_core_main_conf_t *cmcf; |
540 | 541 |
541 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
542 "http phase handler"); | |
543 | |
544 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | 542 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); |
545 | 543 |
546 for (/* void */; r->phase < NGX_HTTP_LOG_PHASE; r->phase++) { | 544 ph = cmcf->phase_engine.handlers; |
547 | 545 |
548 if (r->phase == NGX_HTTP_REWRITE_PHASE + 1 && r->uri_changed) { | 546 while (ph[r->phase_handler].checker) { |
549 | 547 |
550 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 548 rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]); |
551 "uri changes: %d", r->uri_changes); | 549 |
552 | 550 if (rc == NGX_OK) { |
553 /* | |
554 * gcc before 3.3 compiles the broken code for | |
555 * if (r->uri_changes-- == 0) | |
556 * if the r->uri_changes is defined as | |
557 * unsigned uri_changes:4 | |
558 */ | |
559 | |
560 r->uri_changes--; | |
561 | |
562 if (r->uri_changes == 0) { | |
563 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
564 "rewrite or internal redirection cycle " | |
565 "while processing \"%V\"", &r->uri); | |
566 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
567 return; | |
568 } | |
569 | |
570 r->phase = NGX_HTTP_FIND_CONFIG_PHASE; | |
571 } | |
572 | |
573 if (r->phase == NGX_HTTP_ACCESS_PHASE && r != r->main) { | |
574 continue; | |
575 } | |
576 | |
577 if (r->phase == NGX_HTTP_CONTENT_PHASE && r->content_handler) { | |
578 r->write_event_handler = ngx_http_request_empty_handler; | |
579 ngx_http_finalize_request(r, r->content_handler(r)); | |
580 return; | 551 return; |
581 } | 552 } |
582 | 553 } |
583 h = cmcf->phases[r->phase].handlers.elts; | |
584 for (r->phase_handler = cmcf->phases[r->phase].handlers.nelts - 1; | |
585 r->phase_handler >= 0; | |
586 r->phase_handler--) | |
587 { | |
588 rc = h[r->phase_handler](r); | |
589 | |
590 if (rc == NGX_DONE) { | |
591 | |
592 /* | |
593 * we should never use r here because | |
594 * it may point to already freed data | |
595 */ | |
596 | |
597 return; | |
598 } | |
599 | |
600 if (rc == NGX_DECLINED) { | |
601 continue; | |
602 } | |
603 | |
604 if (r->phase == NGX_HTTP_ACCESS_PHASE) { | |
605 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
606 | |
607 if (clcf->satisfy_any) { | |
608 | |
609 if (rc == NGX_OK) { | |
610 r->access_code = 0; | |
611 | |
612 if (r->headers_out.www_authenticate) { | |
613 r->headers_out.www_authenticate->hash = 0; | |
614 } | |
615 | |
616 break; | |
617 } | |
618 | |
619 if (rc == NGX_HTTP_FORBIDDEN || rc == NGX_HTTP_UNAUTHORIZED) | |
620 { | |
621 r->access_code = rc; | |
622 | |
623 continue; | |
624 } | |
625 } | |
626 } | |
627 | |
628 if (rc >= NGX_HTTP_SPECIAL_RESPONSE | |
629 || rc == NGX_HTTP_NO_CONTENT | |
630 || rc == NGX_ERROR) | |
631 { | |
632 ngx_http_finalize_request(r, rc); | |
633 return; | |
634 } | |
635 | |
636 if (r->phase == NGX_HTTP_CONTENT_PHASE) { | |
637 ngx_http_finalize_request(r, rc); | |
638 return; | |
639 } | |
640 | |
641 if (rc == NGX_AGAIN) { | |
642 return; | |
643 } | |
644 | |
645 if (rc == NGX_OK && cmcf->phases[r->phase].type == NGX_OK) { | |
646 break; | |
647 } | |
648 | |
649 } | |
650 | |
651 if (r->phase == NGX_HTTP_ACCESS_PHASE && r->access_code) { | |
652 | |
653 if (r->access_code == NGX_HTTP_FORBIDDEN) { | |
654 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
655 "access forbidden by rule"); | |
656 } | |
657 | |
658 ngx_http_finalize_request(r, r->access_code); | |
659 return; | |
660 } | |
661 } | |
662 | |
663 /* no content handler was found */ | |
664 | |
665 if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) { | |
666 | |
667 if (ngx_http_map_uri_to_path(r, &path, 0) != NULL) { | |
668 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
669 "directory index of \"%V\" is forbidden", &path); | |
670 } | |
671 | |
672 ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN); | |
673 return; | |
674 } | |
675 | |
676 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found"); | |
677 | |
678 ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); | |
679 } | 554 } |
680 | 555 |
681 | 556 |
682 ngx_int_t | 557 ngx_int_t |
683 ngx_http_find_location_config(ngx_http_request_t *r) | 558 ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) |
559 { | |
560 ngx_int_t rc; | |
561 | |
562 /* | |
563 * generic phase checker, | |
564 * used by the post read, server rewrite, rewrite, and pre-access phases | |
565 */ | |
566 | |
567 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
568 "generic phase: %ui", r->phase_handler); | |
569 | |
570 rc = ph->handler(r); | |
571 | |
572 if (rc == NGX_OK) { | |
573 r->phase_handler = ph->next; | |
574 return NGX_AGAIN; | |
575 } | |
576 | |
577 if (rc == NGX_DECLINED) { | |
578 r->phase_handler++; | |
579 return NGX_AGAIN; | |
580 } | |
581 | |
582 if (rc == NGX_AGAIN || rc == NGX_DONE) { | |
583 return NGX_OK; | |
584 } | |
585 | |
586 /* rc == NGX_ERROR || rc == NGX_HTTP_... */ | |
587 | |
588 ngx_http_finalize_request(r, rc); | |
589 | |
590 return NGX_OK; | |
591 } | |
592 | |
593 | |
594 ngx_int_t | |
595 ngx_http_core_find_config_phase(ngx_http_request_t *r, | |
596 ngx_http_phase_handler_t *ph) | |
684 { | 597 { |
685 ngx_int_t rc; | 598 ngx_int_t rc; |
686 ngx_http_core_loc_conf_t *clcf; | 599 ngx_http_core_loc_conf_t *clcf; |
687 ngx_http_core_srv_conf_t *cscf; | 600 ngx_http_core_srv_conf_t *cscf; |
688 | 601 |
692 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); | 605 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); |
693 | 606 |
694 rc = ngx_http_core_find_location(r, &cscf->locations, 0); | 607 rc = ngx_http_core_find_location(r, &cscf->locations, 0); |
695 | 608 |
696 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { | 609 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { |
697 return rc; | 610 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
611 return NGX_OK; | |
698 } | 612 } |
699 | 613 |
700 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 614 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
701 | 615 |
702 if (!r->internal && clcf->internal) { | 616 if (!r->internal && clcf->internal) { |
703 return NGX_HTTP_NOT_FOUND; | 617 ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); |
618 return NGX_OK; | |
704 } | 619 } |
705 | 620 |
706 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 621 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
707 "using configuration \"%s%V\"", | 622 "using configuration \"%s%V\"", |
708 (clcf->noname ? "*" : (clcf->exact_match ? "=" : "")), | 623 (clcf->noname ? "*" : (clcf->exact_match ? "=" : "")), |
721 { | 636 { |
722 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 637 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
723 "client intented to send too large body: %O bytes", | 638 "client intented to send too large body: %O bytes", |
724 r->headers_in.content_length_n); | 639 r->headers_in.content_length_n); |
725 | 640 |
726 return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; | 641 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE); |
642 return NGX_OK; | |
727 } | 643 } |
728 | 644 |
729 | 645 |
730 if (rc == NGX_HTTP_LOCATION_AUTO_REDIRECT) { | 646 if (rc == NGX_HTTP_LOCATION_AUTO_REDIRECT) { |
731 r->headers_out.location = ngx_list_push(&r->headers_out.headers); | 647 r->headers_out.location = ngx_list_push(&r->headers_out.headers); |
732 if (r->headers_out.location == NULL) { | 648 if (r->headers_out.location == NULL) { |
733 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 649 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
650 return NGX_OK; | |
734 } | 651 } |
735 | 652 |
736 /* | 653 /* |
737 * we do not need to set the r->headers_out.location->hash and | 654 * we do not need to set the r->headers_out.location->hash and |
738 * r->headers_out.location->key fields | 655 * r->headers_out.location->key fields |
739 */ | 656 */ |
740 | 657 |
741 r->headers_out.location->value = clcf->name; | 658 r->headers_out.location->value = clcf->name; |
742 | 659 |
743 return NGX_HTTP_MOVED_PERMANENTLY; | 660 ngx_http_finalize_request(r, NGX_HTTP_MOVED_PERMANENTLY); |
744 } | 661 return NGX_OK; |
745 | 662 } |
663 | |
664 r->phase_handler++; | |
665 return NGX_AGAIN; | |
666 } | |
667 | |
668 | |
669 ngx_int_t | |
670 ngx_http_core_post_rewrite_phase(ngx_http_request_t *r, | |
671 ngx_http_phase_handler_t *ph) | |
672 { | |
673 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
674 "post rewrite phase: %ui", r->phase_handler); | |
675 | |
676 if (!r->uri_changed) { | |
677 r->phase_handler++; | |
678 return NGX_AGAIN; | |
679 } | |
680 | |
681 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
682 "uri changes: %d", r->uri_changes); | |
683 | |
684 /* | |
685 * gcc before 3.3 compiles the broken code for | |
686 * if (r->uri_changes-- == 0) | |
687 * if the r->uri_changes is defined as | |
688 * unsigned uri_changes:4 | |
689 */ | |
690 | |
691 r->uri_changes--; | |
692 | |
693 if (r->uri_changes == 0) { | |
694 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
695 "rewrite or internal redirection cycle " | |
696 "while processing \"%V\"", &r->uri); | |
697 | |
698 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
699 return NGX_OK; | |
700 } | |
701 | |
702 r->phase_handler = ph->next; | |
703 | |
704 return NGX_AGAIN; | |
705 } | |
706 | |
707 | |
708 ngx_int_t | |
709 ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) | |
710 { | |
711 ngx_int_t rc; | |
712 ngx_http_core_loc_conf_t *clcf; | |
713 | |
714 if (r != r->main) { | |
715 r->phase_handler = ph->next; | |
716 return NGX_AGAIN; | |
717 } | |
718 | |
719 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
720 "access phase: %ui", r->phase_handler); | |
721 | |
722 rc = ph->handler(r); | |
723 | |
724 if (rc == NGX_DECLINED) { | |
725 r->phase_handler++; | |
726 return NGX_AGAIN; | |
727 } | |
728 | |
729 if (rc == NGX_AGAIN || rc == NGX_DONE) { | |
730 return NGX_OK; | |
731 } | |
732 | |
733 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
734 | |
735 if (clcf->satisfy_any == 0) { | |
736 | |
737 if (rc == NGX_OK) { | |
738 r->phase_handler++; | |
739 return NGX_AGAIN; | |
740 } | |
741 | |
742 } else { | |
743 if (rc == NGX_OK) { | |
744 r->access_code = 0; | |
745 | |
746 if (r->headers_out.www_authenticate) { | |
747 r->headers_out.www_authenticate->hash = 0; | |
748 } | |
749 | |
750 r->phase_handler = ph->next; | |
751 return NGX_AGAIN; | |
752 } | |
753 | |
754 if (rc == NGX_HTTP_FORBIDDEN || rc == NGX_HTTP_UNAUTHORIZED) { | |
755 r->access_code = rc; | |
756 | |
757 r->phase_handler++; | |
758 return NGX_AGAIN; | |
759 } | |
760 } | |
761 | |
762 /* rc == NGX_ERROR || rc == NGX_HTTP_... */ | |
763 | |
764 ngx_http_finalize_request(r, rc); | |
765 return NGX_OK; | |
766 } | |
767 | |
768 | |
769 ngx_int_t | |
770 ngx_http_core_post_access_phase(ngx_http_request_t *r, | |
771 ngx_http_phase_handler_t *ph) | |
772 { | |
773 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
774 "post access phase: %ui", r->phase_handler); | |
775 | |
776 if (r->access_code) { | |
777 | |
778 if (r->access_code == NGX_HTTP_FORBIDDEN) { | |
779 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
780 "access forbidden by rule"); | |
781 } | |
782 | |
783 ngx_http_finalize_request(r, r->access_code); | |
784 return NGX_OK; | |
785 } | |
786 | |
787 r->phase_handler++; | |
788 return NGX_AGAIN; | |
789 } | |
790 | |
791 | |
792 ngx_int_t | |
793 ngx_http_core_content_phase(ngx_http_request_t *r, | |
794 ngx_http_phase_handler_t *ph) | |
795 { | |
796 ngx_int_t rc; | |
797 ngx_str_t path; | |
798 | |
799 if (r->content_handler) { | |
800 r->write_event_handler = ngx_http_request_empty_handler; | |
801 ngx_http_finalize_request(r, r->content_handler(r)); | |
802 return NGX_OK; | |
803 } | |
804 | |
805 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
806 "content phase: %ui", r->phase_handler); | |
807 | |
808 rc = ph->handler(r); | |
809 | |
810 if (rc == NGX_DONE) { | |
811 return NGX_OK; | |
812 } | |
813 | |
814 if (rc != NGX_DECLINED) { | |
815 ngx_http_finalize_request(r, rc); | |
816 return NGX_OK; | |
817 } | |
818 | |
819 /* rc == NGX_DECLINED */ | |
820 | |
821 ph++; | |
822 | |
823 if (ph->checker) { | |
824 r->phase_handler++; | |
825 return NGX_AGAIN; | |
826 } | |
827 | |
828 /* no content handler was found */ | |
829 | |
830 if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) { | |
831 | |
832 if (ngx_http_map_uri_to_path(r, &path, 0) != NULL) { | |
833 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
834 "directory index of \"%V\" is forbidden", &path); | |
835 } | |
836 | |
837 ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN); | |
838 return NGX_OK; | |
839 } | |
840 | |
841 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found"); | |
842 | |
843 ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); | |
746 return NGX_OK; | 844 return NGX_OK; |
747 } | 845 } |
748 | 846 |
749 | 847 |
750 void | 848 void |
1914 == NGX_ERROR) | 2012 == NGX_ERROR) |
1915 { | 2013 { |
1916 return NGX_CONF_ERROR; | 2014 return NGX_CONF_ERROR; |
1917 } | 2015 } |
1918 | 2016 |
1919 if (ngx_array_init(&cscf->server_names, cf->pool, 4, | 2017 if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4, |
1920 sizeof(ngx_http_server_name_t)) | 2018 sizeof(ngx_http_server_name_t)) |
1921 == NGX_ERROR) | 2019 == NGX_ERROR) |
1922 { | 2020 { |
1923 return NGX_CONF_ERROR; | 2021 return NGX_CONF_ERROR; |
1924 } | 2022 } |