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;