Mercurial > hg > nginx-quic
comparison src/http/modules/proxy/ngx_http_event_proxy_handler.c @ 72:66de3f065886
nginx-0.0.1-2003-04-09-19:42:08 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Wed, 09 Apr 2003 15:42:08 +0000 |
parents | 59229033ae93 |
children | 4534060fde92 |
comparison
equal
deleted
inserted
replaced
71:59229033ae93 | 72:66de3f065886 |
---|---|
23 static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p); | 23 static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p); |
24 static int ngx_http_proxy_process_upstream_event(ngx_event_t *ev); | 24 static int ngx_http_proxy_process_upstream_event(ngx_event_t *ev); |
25 static int ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p); | 25 static int ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p); |
26 static int ngx_http_proxy_init_upstream(ngx_http_proxy_ctx_t *p); | 26 static int ngx_http_proxy_init_upstream(ngx_http_proxy_ctx_t *p); |
27 static int ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p); | 27 static int ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p); |
28 | |
28 static int ngx_http_proxy_process_upstream_status_line(ngx_http_proxy_ctx_t *p); | 29 static int ngx_http_proxy_process_upstream_status_line(ngx_http_proxy_ctx_t *p); |
30 static int ngx_http_proxy_process_upstream_headers(ngx_http_proxy_ctx_t *p); | |
31 static int ngx_http_proxy_process_upstream_header_line(ngx_http_proxy_ctx_t *p); | |
29 | 32 |
30 | 33 |
31 static int ngx_http_proxy_read_response_body(ngx_event_t *ev); | 34 static int ngx_http_proxy_read_response_body(ngx_event_t *ev); |
32 static int ngx_http_proxy_write_to_client(ngx_event_t *ev); | 35 static int ngx_http_proxy_write_to_client(ngx_event_t *ev); |
33 | 36 |
88 ngx_string("HEAD "), | 91 ngx_string("HEAD "), |
89 ngx_string("POST ") | 92 ngx_string("POST ") |
90 }; | 93 }; |
91 | 94 |
92 | 95 |
96 static char *header_errors[] = { | |
97 "upstream sent too long status line", | |
98 "upstream sent invalid header", | |
99 "upstream sent too long header line" | |
100 }; | |
101 | |
102 | |
103 static ngx_http_header_t headers_in[] = { | |
104 { ngx_string("Date"), offsetof(ngx_http_proxy_headers_in_t, date) }, | |
105 { ngx_string("Server"), offsetof(ngx_http_proxy_headers_in_t, server) }, | |
106 { ngx_string("Connection"), | |
107 offsetof(ngx_http_proxy_headers_in_t, connection) }, | |
108 { ngx_string("Content-Type"), | |
109 offsetof(ngx_http_proxy_headers_in_t, content_type) }, | |
110 { ngx_string("Content-Length"), | |
111 offsetof(ngx_http_proxy_headers_in_t, content_length) }, | |
112 { ngx_string("Last-Modified"), | |
113 offsetof(ngx_http_proxy_headers_in_t, last_modified) }, | |
114 | |
115 { ngx_null_string, 0 } | |
116 }; | |
117 | |
118 | |
93 static char http_version[] = " HTTP/1.0" CRLF; | 119 static char http_version[] = " HTTP/1.0" CRLF; |
94 static char host_header[] = "Host: "; | 120 static char host_header[] = "Host: "; |
95 static char conn_close_header[] = "Connection: close" CRLF; | 121 static char conn_close_header[] = "Connection: close" CRLF; |
96 | 122 |
97 | 123 |
137 p->log->data = lcx; | 163 p->log->data = lcx; |
138 hcx = r->connection->log->data; | 164 hcx = r->connection->log->data; |
139 lcx->client = hcx->client; | 165 lcx->client = hcx->client; |
140 lcx->url = hcx->url; | 166 lcx->url = hcx->url; |
141 | 167 |
168 r->proxy = 1; | |
169 p->accel = 1; | |
170 | |
142 p->method = r->method; | 171 p->method = r->method; |
172 p->headers_in.headers = ngx_create_table(r->pool, 10); | |
143 | 173 |
144 /* TODO: read a client's body */ | 174 /* TODO: read a client's body */ |
145 | 175 |
146 chain = ngx_http_proxy_create_request(p); | 176 chain = ngx_http_proxy_create_request(p); |
147 if (chain == NULL) { | 177 if (chain == NULL) { |
360 | 390 |
361 if (p->tries == 0) { | 391 if (p->tries == 0) { |
362 ngx_http_proxy_finalize_request(p, p->last_error); | 392 ngx_http_proxy_finalize_request(p, p->last_error); |
363 return NGX_ERROR; | 393 return NGX_ERROR; |
364 } | 394 } |
395 | |
396 p->headers_in.server->key.len = 0; | |
397 p->headers_in.connection->key.len = 0; | |
398 p->headers_in.content_type->key.len = 0; | |
399 p->headers_in.content_length->key.len = 0; | |
400 p->headers_in.last_modified->key.len = 0; | |
401 | |
402 p->headers_in.headers->nelts = 0; | |
365 } | 403 } |
366 | 404 |
367 if (rc == NGX_OK) { | 405 if (rc == NGX_OK) { |
368 ngx_http_proxy_finalize_request(p, p->status); | 406 ngx_http_proxy_finalize_request(p, p->status); |
369 return NGX_DONE; | 407 return NGX_DONE; |
676 ngx_create_temp_hunk(r->pool, p->lcf->header_size, 0, 0), | 714 ngx_create_temp_hunk(r->pool, p->lcf->header_size, 0, 0), |
677 NGX_ERROR); | 715 NGX_ERROR); |
678 | 716 |
679 p->header_in->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY; | 717 p->header_in->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY; |
680 | 718 |
719 #if 0 | |
681 ngx_test_null(p->headers_in, | 720 ngx_test_null(p->headers_in, |
682 ngx_palloc(r->pool, sizeof(ngx_http_proxy_headers_in_t)), | 721 ngx_palloc(r->pool, sizeof(ngx_http_proxy_headers_in_t)), |
683 NGX_ERROR); | 722 NGX_ERROR); |
684 | 723 #endif |
685 p->hunks_number = p->lcf->max_block_size / p->lcf->block_size; | 724 |
686 if (p->hunks_number * p->lcf->block_size < p->lcf->max_block_size) { | 725 p->nhunks = p->lcf->max_block_size / p->lcf->block_size; |
687 p->hunks_number++; | 726 if (p->nhunks * p->lcf->block_size < p->lcf->max_block_size) { |
688 } | 727 p->nhunks++; |
689 | 728 } |
690 ngx_init_array(p->hunks, r->pool, p->hunks_number, sizeof(ngx_hunk_t *), | 729 |
730 ngx_init_array(p->hunks, r->pool, p->nhunks, sizeof(ngx_hunk_t *), | |
691 NGX_ERROR); | 731 NGX_ERROR); |
692 | 732 |
693 ngx_test_null(ph, ngx_push_array(&p->hunks), NGX_ERROR); | 733 ngx_test_null(ph, ngx_push_array(&p->hunks), NGX_ERROR); |
694 *ph = p->header_in; | 734 *ph = p->header_in; |
695 | 735 |
699 } | 739 } |
700 | 740 |
701 | 741 |
702 static int ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p) | 742 static int ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p) |
703 { | 743 { |
704 int n, rc; | 744 int i, n, rc; |
705 ngx_event_t *rev; | 745 ngx_event_t *rev; |
746 ngx_table_elt_t *ch, *ph; | |
747 ngx_http_request_t *r; | |
706 | 748 |
707 rev = p->connection->read; | 749 rev = p->connection->read; |
708 | 750 |
709 do { | 751 do { |
710 n = ngx_event_recv(p->connection, p->header_in->last, | 752 n = ngx_event_recv(p->connection, p->header_in->last, |
734 } | 776 } |
735 | 777 |
736 p->header_in->last += n; | 778 p->header_in->last += n; |
737 | 779 |
738 /* the state handlers are called in the following order: | 780 /* the state handlers are called in the following order: |
739 ngx_http_proxy_process_upstream_status_line(r) | 781 ngx_http_proxy_process_upstream_status_line(p) |
740 ngx_http_proxy_process_upstream_headers(r) */ | 782 ngx_http_proxy_process_upstream_headers(p) */ |
741 | 783 |
742 do { | 784 do { |
743 rc = p->state_handler(p); | 785 rc = p->state_handler(p); |
744 } while (rc == NGX_AGAIN && p->header_in->end < p->header_in->last); | 786 } while (rc == NGX_AGAIN && p->header_in->pos < p->header_in->last); |
745 | 787 |
746 } while (rc == NGX_AGAIN | 788 } while (rc == NGX_AGAIN |
747 && (rev->ready || ngx_event_flags & NGX_HAVE_AIO_EVENT)); | 789 && (rev->ready || ngx_event_flags & NGX_HAVE_AIO_EVENT)); |
748 | 790 |
791 if (rc == NGX_OK) { | |
792 | |
793 r = p->request; | |
794 | |
795 /* copy an upstream header to r->headers_out */ | |
796 | |
797 ph = (ngx_table_elt_t *) p->headers_in.headers->elts; | |
798 for (i = 0; i < p->headers_in.headers->nelts; i++) { | |
799 | |
800 if (&ph[i] == p->headers_in.connection) { | |
801 continue; | |
802 } | |
803 | |
804 if (p->accel && &ph[i] == p->headers_in.date) { | |
805 continue; | |
806 } | |
807 | |
808 ngx_test_null(ch, ngx_push_table(r->headers_out.headers), | |
809 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
810 | |
811 ch->key.len = ph[i].key.len; | |
812 ch->key.data = ph[i].key.data; | |
813 ch->value.len = ph[i].value.len; | |
814 ch->value.data = ph[i].value.data; | |
815 } | |
816 | |
817 if (p->headers_in.server) { | |
818 r->headers_out.server = p->headers_in.server; | |
819 } | |
820 | |
821 if (!p->accel && p->headers_in.date) { | |
822 r->headers_out.date = p->headers_in.date; | |
823 } | |
824 | |
825 r->headers_out.status = p->status; | |
826 | |
827 /* STUB */ r->header_only = 1; | |
828 | |
829 rc = ngx_http_send_header(r); | |
830 | |
831 /* STUB */ return NGX_DONE; | |
832 } | |
833 | |
749 if (rc > NGX_OK) { | 834 if (rc > NGX_OK) { |
750 return rc; | 835 return rc; |
751 } | 836 } |
752 | 837 |
753 if (rc == NGX_OK) { | 838 /* STUB */ return NGX_DONE; |
754 /* STUB */ return NGX_ERROR; | |
755 } | |
756 | |
757 /* STUB */ return NGX_ERROR; | |
758 } | 839 } |
759 | 840 |
760 | 841 |
761 static int ngx_http_proxy_process_upstream_status_line(ngx_http_proxy_ctx_t *p) | 842 static int ngx_http_proxy_process_upstream_status_line(ngx_http_proxy_ctx_t *p) |
762 { | 843 { |
763 int rc; | 844 int rc; |
764 | |
765 #if 0 | |
766 *p->header_in->last = '\0'; | |
767 ngx_log_debug(p->log, "PROXY:\n'%s'" _ p->header_in->pos); | |
768 #endif | |
769 | 845 |
770 rc = ngx_read_http_proxy_status_line(p); | 846 rc = ngx_read_http_proxy_status_line(p); |
771 | 847 |
772 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { | 848 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) { |
773 p->status = 200; | 849 p->status = 200; |
774 p->status_line.len = 0; | 850 p->status_line.len = 0; |
775 p->full_status_line.len = 0; | 851 p->full_status_line.len = 0; |
776 } | 852 p->state_handler = ngx_http_proxy_process_upstream_headers; |
777 | 853 |
778 if (rc == NGX_OK) { | 854 } else if (rc == NGX_OK) { |
779 p->status_line.len = p->status_end - p->status_start; | 855 p->status_line.len = p->status_end - p->status_start; |
780 p->full_status_line.len = p->status_end - p->header_in->start; | 856 p->full_status_line.len = p->status_end - p->header_in->start; |
781 | 857 |
782 if (p->lcf->large_header) { | 858 if (p->lcf->large_header) { |
783 ngx_test_null(p->full_status_line.data, | 859 ngx_test_null(p->full_status_line.data, |
794 | 870 |
795 } else { | 871 } else { |
796 p->status_line.data = p->status_start; | 872 p->status_line.data = p->status_start; |
797 p->full_status_line.data = p->header_in->start; | 873 p->full_status_line.data = p->header_in->start; |
798 *p->status_end = '\0'; | 874 *p->status_end = '\0'; |
875 | |
876 if (p->header_in->pos == p->header_in->end) { | |
877 ngx_log_error(NGX_LOG_ERR, p->log, 0, | |
878 "upstream sent too long status line"); | |
879 return NGX_HTTP_BAD_GATEWAY; | |
880 } | |
799 } | 881 } |
800 | 882 |
801 ngx_log_debug(p->log, "upstream status: %d, '%s'" _ | 883 ngx_log_debug(p->log, "upstream status: %d, '%s'" _ |
802 p->status _ p->full_status_line.data); | 884 p->status _ p->full_status_line.data); |
803 | 885 |
804 p->state_handler = NULL; | 886 p->state_handler = ngx_http_proxy_process_upstream_headers; |
805 } | 887 } |
806 | 888 |
807 if (p->header_in->last == p->header_in->end) { | 889 /* rc == NGX_AGAIN */ |
808 rc = NGX_HTTP_PARSE_TOO_LONG_STATUS_LINE; | 890 |
809 | 891 return NGX_AGAIN; |
810 } else if (rc == NGX_AGAIN) { | 892 } |
893 | |
894 | |
895 static int ngx_http_proxy_process_upstream_headers(ngx_http_proxy_ctx_t *p) | |
896 { | |
897 int rc, offset; | |
898 ngx_http_request_t *r; | |
899 | |
900 r = p->request; | |
901 | |
902 for ( ;; ) { | |
903 rc = ngx_read_http_header_line(r, p->header_in); | |
904 | |
905 /* a header line has been parsed successfully */ | |
906 | |
907 if (rc == NGX_OK) { | |
908 if (ngx_http_proxy_process_upstream_header_line(p) == NGX_ERROR) { | |
909 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
910 } | |
911 | |
912 if (p->lcf->large_header | |
913 && p->header_in->pos == p->header_in->last) | |
914 { | |
915 p->header_in->pos = p->header_in->last = p->header_in->start; | |
916 } | |
917 | |
918 return NGX_AGAIN; | |
919 | |
920 /* a whole header has been parsed successfully */ | |
921 | |
922 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { | |
923 ngx_log_debug(p->log, "proxy HTTP header done"); | |
924 | |
925 p->state_handler = NULL; | |
926 return NGX_OK; | |
927 | |
928 /* there was error while a header line parsing */ | |
929 | |
930 } else if (rc != NGX_AGAIN) { | |
931 ngx_log_error(NGX_LOG_ERR, p->log, 0, | |
932 "upstream sent ERROR %d", rc); | |
933 return NGX_HTTP_BAD_GATEWAY; | |
934 } | |
935 | |
936 /* NGX_AGAIN: a header line parsing is still not complete */ | |
937 | |
938 if (p->header_in->pos == p->header_in->last) { | |
939 /* if the large upstream headers are enabled then | |
940 we need to compact p->header_in hunk */ | |
941 | |
942 if (p->lcf->large_header) { | |
943 offset = r->header_name_start - p->header_in->start; | |
944 | |
945 if (offset == 0) { | |
946 ngx_log_error(NGX_LOG_ERR, p->log, 0, | |
947 "upstream sent too long header line"); | |
948 return NGX_HTTP_BAD_GATEWAY; | |
949 } | |
950 | |
951 ngx_memcpy(p->header_in->start, r->header_name_start, | |
952 p->header_in->last - r->header_name_start); | |
953 | |
954 p->header_in->last -= offset; | |
955 p->header_in->pos -= offset; | |
956 r->header_name_start = p->header_in->start; | |
957 r->header_name_end -= offset; | |
958 r->header_start -= offset; | |
959 r->header_end -= offset; | |
960 | |
961 } else { | |
962 ngx_log_error(NGX_LOG_ERR, p->log, 0, | |
963 "upstream sent too long header line"); | |
964 /* NGX_HTTP_PARSE_TOO_LONG_HEADER */ | |
965 return NGX_HTTP_BAD_GATEWAY; | |
966 } | |
967 } | |
968 | |
811 return NGX_AGAIN; | 969 return NGX_AGAIN; |
812 } | 970 } |
813 | 971 } |
814 /* STUB */ return NGX_ERROR; | 972 |
815 } | 973 |
816 | 974 static int ngx_http_proxy_process_upstream_header_line(ngx_http_proxy_ctx_t *p) |
817 | 975 { |
818 | 976 int i; |
819 | 977 ngx_table_elt_t *h; |
820 | 978 ngx_http_request_t *r; |
821 | 979 |
822 | 980 r = p->request; |
823 | 981 |
982 ngx_test_null(h, ngx_push_table(p->headers_in.headers), NGX_ERROR); | |
983 | |
984 h->key.len = r->header_name_end - r->header_name_start; | |
985 h->value.len = r->header_end - r->header_start; | |
986 | |
987 /* if the large upstream headers are enabled then | |
988 we need to copy the header name and value */ | |
989 | |
990 if (p->lcf->large_header) { | |
991 ngx_test_null(h->key.data, ngx_palloc(r->pool, h->key.len + 1), | |
992 NGX_ERROR); | |
993 ngx_test_null(h->value.data, ngx_palloc(r->pool, h->value.len + 1), | |
994 NGX_ERROR); | |
995 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); | |
996 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); | |
997 | |
998 } else { | |
999 h->key.data = r->header_name_start; | |
1000 h->key.data[h->key.len] = '\0'; | |
1001 h->value.data = r->header_start; | |
1002 h->value.data[h->value.len] = '\0'; | |
1003 } | |
1004 | |
1005 for (i = 0; headers_in[i].name.len != 0; i++) { | |
1006 if (headers_in[i].name.len != h->key.len) { | |
1007 continue; | |
1008 } | |
1009 | |
1010 if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) { | |
1011 *((ngx_table_elt_t **) | |
1012 ((char *) &p->headers_in + headers_in[i].offset)) = h; | |
1013 } | |
1014 } | |
1015 | |
1016 ngx_log_debug(p->log, "proxy HTTP header: '%s: %s'" _ | |
1017 h->key.data _ h->value.data); | |
1018 | |
1019 return NGX_OK; | |
1020 } | |
824 | 1021 |
825 | 1022 |
826 #if 0 | 1023 #if 0 |
827 static int ngx_http_proxy_process_response_header(ngx_http_request_t *r, | 1024 |
828 ngx_http_proxy_ctx_t *p) | 1025 static int ngx_http_proxy_read_upstream_body(ngx_event_t *rev) |
829 { | 1026 { |
830 return NGX_OK; | 1027 do { |
831 } | 1028 if (free) { |
1029 buf = get | |
1030 else if (kqueue and eof) { | |
1031 buf = &buf; | |
1032 size = 0; | |
1033 else if (p->cur_hunks < p->nhunks) | |
1034 palloc | |
1035 p->cur_hunks++; | |
1036 else | |
1037 write first | |
1038 add file hunk to out | |
1039 } | |
1040 | |
1041 n = ngx_event_recv(c, buf, size); | |
1042 | |
1043 } while (n > 0 && left == 0); | |
1044 | |
1045 if (out && p->request->connection->write->ready) { | |
1046 ngx_http_proxy_write_upstream_body(p->request->connection->write); | |
1047 } | |
1048 } | |
1049 | |
1050 | |
1051 static int ngx_http_proxy_write_upstream_body(ngx_event_t *wev) | |
1052 { | |
1053 while (out) { | |
1054 output_filter(r, hunk); | |
1055 if (again) | |
1056 return | |
1057 | |
1058 if (hunk done) | |
1059 remove from out | |
1060 if (hunk is memory) | |
1061 add it to free | |
1062 } | |
1063 } | |
1064 | |
1065 | |
1066 | |
832 #endif | 1067 #endif |
1068 | |
1069 | |
1070 | |
833 | 1071 |
834 | 1072 |
835 static int ngx_http_proxy_read_response_body(ngx_event_t *ev) | 1073 static int ngx_http_proxy_read_response_body(ngx_event_t *ev) |
836 { | 1074 { |
837 int n; | 1075 int n; |