Mercurial > hg > nginx
comparison src/http/ngx_http_upstream.c @ 649:1e720b0be7ec release-0.3.46
nginx-0.3.46-RELEASE import
*) Feature: the "proxy_hide_header", "proxy_pass_header",
"fastcgi_hide_header", and "fastcgi_pass_header" directives.
*) Change: the "proxy_pass_x_powered_by", "fastcgi_x_powered_by", and
"proxy_pass_server" directives were canceled.
*) Feature: the "X-Accel-Buffering" response header line is supported
in proxy mode.
*) Bugfix: the reconfiguration bug and memory leaks in the
ngx_http_perl_module.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 11 May 2006 14:43:47 +0000 |
parents | 5e8fb59c18c1 |
children | 39b7d7b33c91 |
comparison
equal
deleted
inserted
replaced
648:e60de1d1cdb2 | 649:1e720b0be7ec |
---|---|
45 ngx_table_elt_t *h, ngx_uint_t offset); | 45 ngx_table_elt_t *h, ngx_uint_t offset); |
46 static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, | 46 static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, |
47 ngx_table_elt_t *h, ngx_uint_t offset); | 47 ngx_table_elt_t *h, ngx_uint_t offset); |
48 static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, | 48 static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, |
49 ngx_table_elt_t *h, ngx_uint_t offset); | 49 ngx_table_elt_t *h, ngx_uint_t offset); |
50 static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r, | |
51 ngx_table_elt_t *h, ngx_uint_t offset); | |
50 static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r, | 52 static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r, |
51 ngx_table_elt_t *h, ngx_uint_t offset); | |
52 static ngx_int_t | |
53 ngx_http_upstream_conditional_copy_header_line(ngx_http_request_t *r, | |
54 ngx_table_elt_t *h, ngx_uint_t offset); | 53 ngx_table_elt_t *h, ngx_uint_t offset); |
55 static ngx_int_t | 54 static ngx_int_t |
56 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r, | 55 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r, |
57 ngx_table_elt_t *h, ngx_uint_t offset); | 56 ngx_table_elt_t *h, ngx_uint_t offset); |
58 static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r, | 57 static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r, |
101 ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { | 100 ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { |
102 | 101 |
103 { ngx_string("Status"), | 102 { ngx_string("Status"), |
104 ngx_http_upstream_process_header_line, | 103 ngx_http_upstream_process_header_line, |
105 offsetof(ngx_http_upstream_headers_in_t, status), | 104 offsetof(ngx_http_upstream_headers_in_t, status), |
106 /* STUB */ ngx_http_upstream_ignore_header_line, 0, 0 }, | 105 ngx_http_upstream_copy_header_line, 0, 0 }, |
107 | 106 |
108 { ngx_string("Content-Type"), | 107 { ngx_string("Content-Type"), |
109 ngx_http_upstream_process_header_line, | 108 ngx_http_upstream_process_header_line, |
110 offsetof(ngx_http_upstream_headers_in_t, content_type), | 109 offsetof(ngx_http_upstream_headers_in_t, content_type), |
111 ngx_http_upstream_copy_content_type, 0, 0 }, | 110 ngx_http_upstream_copy_content_type, 0, 0 }, |
116 ngx_http_upstream_copy_content_length, 0, 0 }, | 115 ngx_http_upstream_copy_content_length, 0, 0 }, |
117 | 116 |
118 { ngx_string("Date"), | 117 { ngx_string("Date"), |
119 ngx_http_upstream_process_header_line, | 118 ngx_http_upstream_process_header_line, |
120 offsetof(ngx_http_upstream_headers_in_t, date), | 119 offsetof(ngx_http_upstream_headers_in_t, date), |
121 ngx_http_upstream_conditional_copy_header_line, | 120 ngx_http_upstream_copy_header_line, |
122 offsetof(ngx_http_upstream_conf_t, pass_date), 0 }, | 121 offsetof(ngx_http_headers_out_t, date), 0 }, |
123 | 122 |
124 { ngx_string("Server"), | 123 { ngx_string("Server"), |
125 ngx_http_upstream_process_header_line, | 124 ngx_http_upstream_process_header_line, |
126 offsetof(ngx_http_upstream_headers_in_t, server), | 125 offsetof(ngx_http_upstream_headers_in_t, server), |
127 ngx_http_upstream_conditional_copy_header_line, | 126 ngx_http_upstream_copy_header_line, |
128 offsetof(ngx_http_upstream_conf_t, pass_server), 0 }, | 127 offsetof(ngx_http_headers_out_t, server), 0 }, |
129 | 128 |
130 { ngx_string("WWW-Authenticate"), | 129 { ngx_string("WWW-Authenticate"), |
131 ngx_http_upstream_process_header_line, | 130 ngx_http_upstream_process_header_line, |
132 offsetof(ngx_http_upstream_headers_in_t, www_authenticate), | 131 offsetof(ngx_http_upstream_headers_in_t, www_authenticate), |
133 ngx_http_upstream_copy_header_line, 0, 0 }, | 132 ngx_http_upstream_copy_header_line, 0, 0 }, |
172 | 171 |
173 { ngx_string("Keep-Alive"), | 172 { ngx_string("Keep-Alive"), |
174 ngx_http_upstream_ignore_header_line, 0, | 173 ngx_http_upstream_ignore_header_line, 0, |
175 ngx_http_upstream_ignore_header_line, 0, 0 }, | 174 ngx_http_upstream_ignore_header_line, 0, 0 }, |
176 | 175 |
177 { ngx_string("X-Pad"), | |
178 ngx_http_upstream_ignore_header_line, 0, | |
179 ngx_http_upstream_ignore_header_line, 0, 0 }, | |
180 | |
181 { ngx_string("X-Powered-By"), | 176 { ngx_string("X-Powered-By"), |
182 ngx_http_upstream_ignore_header_line, 0, | 177 ngx_http_upstream_ignore_header_line, 0, |
183 ngx_http_upstream_conditional_copy_header_line, | 178 ngx_http_upstream_copy_header_line, 0, 0 }, |
184 offsetof(ngx_http_upstream_conf_t, pass_x_powered_by), 0 }, | |
185 | 179 |
186 { ngx_string("X-Accel-Expires"), | 180 { ngx_string("X-Accel-Expires"), |
187 ngx_http_upstream_process_header_line, | 181 ngx_http_upstream_process_header_line, |
188 offsetof(ngx_http_upstream_headers_in_t, x_accel_expires), | 182 offsetof(ngx_http_upstream_headers_in_t, x_accel_expires), |
189 ngx_http_upstream_conditional_copy_header_line, | 183 ngx_http_upstream_copy_header_line, 0, 0 }, |
190 offsetof(ngx_http_upstream_conf_t, pass_x_accel_expires), 0 }, | |
191 | 184 |
192 { ngx_string("X-Accel-Redirect"), | 185 { ngx_string("X-Accel-Redirect"), |
193 ngx_http_upstream_process_header_line, | 186 ngx_http_upstream_process_header_line, |
194 offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect), | 187 offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect), |
195 ngx_http_upstream_ignore_header_line, 0, 0 }, | 188 ngx_http_upstream_ignore_header_line, 0, 0 }, |
196 | 189 |
197 { ngx_string("X-Accel-Limit-Rate"), | 190 { ngx_string("X-Accel-Limit-Rate"), |
198 ngx_http_upstream_process_limit_rate, 0, | 191 ngx_http_upstream_process_limit_rate, 0, |
192 ngx_http_upstream_ignore_header_line, 0, 0 }, | |
193 | |
194 { ngx_string("X-Accel-Buffering"), | |
195 ngx_http_upstream_process_buffering, 0, | |
199 ngx_http_upstream_ignore_header_line, 0, 0 }, | 196 ngx_http_upstream_ignore_header_line, 0, 0 }, |
200 | 197 |
201 #if (NGX_HTTP_GZIP) | 198 #if (NGX_HTTP_GZIP) |
202 { ngx_string("Content-Encoding"), | 199 { ngx_string("Content-Encoding"), |
203 ngx_http_upstream_process_header_line, | 200 ngx_http_upstream_process_header_line, |
879 ngx_http_upstream_process_header(ngx_event_t *rev) | 876 ngx_http_upstream_process_header(ngx_event_t *rev) |
880 { | 877 { |
881 ssize_t n; | 878 ssize_t n; |
882 ngx_int_t rc; | 879 ngx_int_t rc; |
883 ngx_str_t *uri, args; | 880 ngx_str_t *uri, args; |
884 ngx_uint_t i, key, flags; | 881 ngx_uint_t i, flags; |
885 ngx_list_part_t *part; | 882 ngx_list_part_t *part; |
886 ngx_table_elt_t *h; | 883 ngx_table_elt_t *h; |
887 ngx_connection_t *c; | 884 ngx_connection_t *c; |
888 ngx_http_request_t *r; | 885 ngx_http_request_t *r; |
889 ngx_http_upstream_t *u; | 886 ngx_http_upstream_t *u; |
1087 | 1084 |
1088 if (r->upstream->headers_in.x_accel_redirect) { | 1085 if (r->upstream->headers_in.x_accel_redirect) { |
1089 ngx_http_upstream_finalize_request(r, u, NGX_DECLINED); | 1086 ngx_http_upstream_finalize_request(r, u, NGX_DECLINED); |
1090 | 1087 |
1091 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); | 1088 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); |
1092 hh = (ngx_http_upstream_header_t *) umcf->headers_in_hash.buckets; | |
1093 | 1089 |
1094 part = &r->upstream->headers_in.headers.part; | 1090 part = &r->upstream->headers_in.headers.part; |
1095 h = part->elts; | 1091 h = part->elts; |
1096 | 1092 |
1097 for (i = 0; /* void */; i++) { | 1093 for (i = 0; /* void */; i++) { |
1104 part = part->next; | 1100 part = part->next; |
1105 h = part->elts; | 1101 h = part->elts; |
1106 i = 0; | 1102 i = 0; |
1107 } | 1103 } |
1108 | 1104 |
1109 key = h[i].hash % umcf->headers_in_hash.hash_size; | 1105 hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash, |
1110 | 1106 h[i].lowcase_key, h[i].key.len); |
1111 if (hh[key].redirect | 1107 |
1112 && hh[key].name.len == h[i].key.len | 1108 if (hh && hh->redirect) { |
1113 && ngx_strcasecmp(hh[key].name.data, h[i].key.data) == 0) | 1109 if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) { |
1114 { | |
1115 if (hh[key].copy_handler(r, &h[i], hh[key].conf) != NGX_OK) { | |
1116 ngx_http_upstream_finalize_request(r, u, | 1110 ngx_http_upstream_finalize_request(r, u, |
1117 NGX_HTTP_INTERNAL_SERVER_ERROR); | 1111 NGX_HTTP_INTERNAL_SERVER_ERROR); |
1118 return; | 1112 return; |
1119 } | 1113 } |
1120 | |
1121 } | 1114 } |
1122 } | 1115 } |
1123 | 1116 |
1124 uri = &r->upstream->headers_in.x_accel_redirect->value; | 1117 uri = &r->upstream->headers_in.x_accel_redirect->value; |
1125 args.len = 0; | 1118 args.len = 0; |
1147 ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) | 1140 ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) |
1148 { | 1141 { |
1149 int tcp_nodelay; | 1142 int tcp_nodelay; |
1150 ssize_t size; | 1143 ssize_t size; |
1151 ngx_int_t rc; | 1144 ngx_int_t rc; |
1152 ngx_uint_t i, key; | 1145 ngx_uint_t i; |
1153 ngx_list_part_t *part; | 1146 ngx_list_part_t *part; |
1154 ngx_table_elt_t *h; | 1147 ngx_table_elt_t *h; |
1155 ngx_event_pipe_t *p; | 1148 ngx_event_pipe_t *p; |
1156 ngx_connection_t *c; | 1149 ngx_connection_t *c; |
1157 ngx_pool_cleanup_t *cl; | 1150 ngx_pool_cleanup_t *cl; |
1159 ngx_http_core_loc_conf_t *clcf; | 1152 ngx_http_core_loc_conf_t *clcf; |
1160 ngx_http_upstream_header_t *hh; | 1153 ngx_http_upstream_header_t *hh; |
1161 ngx_http_upstream_main_conf_t *umcf; | 1154 ngx_http_upstream_main_conf_t *umcf; |
1162 | 1155 |
1163 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); | 1156 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); |
1164 hh = (ngx_http_upstream_header_t *) umcf->headers_in_hash.buckets; | |
1165 | 1157 |
1166 part = &r->upstream->headers_in.headers.part; | 1158 part = &r->upstream->headers_in.headers.part; |
1167 h = part->elts; | 1159 h = part->elts; |
1168 | 1160 |
1169 for (i = 0; /* void */; i++) { | 1161 for (i = 0; /* void */; i++) { |
1176 part = part->next; | 1168 part = part->next; |
1177 h = part->elts; | 1169 h = part->elts; |
1178 i = 0; | 1170 i = 0; |
1179 } | 1171 } |
1180 | 1172 |
1181 key = h[i].hash % umcf->headers_in_hash.hash_size; | 1173 if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash, |
1182 | 1174 h[i].lowcase_key, h[i].key.len)) |
1183 if (hh[key].name.len == h[i].key.len | |
1184 && ngx_strcasecmp(hh[key].name.data, h[i].key.data) == 0) | |
1185 { | 1175 { |
1186 if (hh[key].copy_handler(r, &h[i], hh[key].conf) != NGX_OK) { | 1176 continue; |
1177 } | |
1178 | |
1179 hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash, | |
1180 h[i].lowcase_key, h[i].key.len); | |
1181 | |
1182 if (hh) { | |
1183 if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) { | |
1187 ngx_http_upstream_finalize_request(r, u, | 1184 ngx_http_upstream_finalize_request(r, u, |
1188 NGX_HTTP_INTERNAL_SERVER_ERROR); | 1185 NGX_HTTP_INTERNAL_SERVER_ERROR); |
1189 return; | 1186 return; |
1190 } | 1187 } |
1191 | 1188 |
1195 if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK) { | 1192 if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK) { |
1196 ngx_http_upstream_finalize_request(r, u, | 1193 ngx_http_upstream_finalize_request(r, u, |
1197 NGX_HTTP_INTERNAL_SERVER_ERROR); | 1194 NGX_HTTP_INTERNAL_SERVER_ERROR); |
1198 return; | 1195 return; |
1199 } | 1196 } |
1197 } | |
1198 | |
1199 if (r->headers_out.server && r->headers_out.server->value.data == NULL) { | |
1200 r->headers_out.server->hash = 0; | |
1201 } | |
1202 | |
1203 if (r->headers_out.date && r->headers_out.date->value.data == NULL) { | |
1204 r->headers_out.date->hash = 0; | |
1200 } | 1205 } |
1201 | 1206 |
1202 r->headers_out.status = u->headers_in.status_n; | 1207 r->headers_out.status = u->headers_in.status_n; |
1203 r->headers_out.status_line = u->headers_in.status_line; | 1208 r->headers_out.status_line = u->headers_in.status_line; |
1204 | 1209 |
1234 | 1239 |
1235 c = r->connection; | 1240 c = r->connection; |
1236 | 1241 |
1237 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 1242 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
1238 | 1243 |
1239 if (u->pipe == NULL) { | 1244 if (!u->buffering) { |
1240 | 1245 |
1241 if (u->input_filter == NULL) { | 1246 if (u->input_filter == NULL) { |
1242 u->input_filter_init = ngx_http_upstream_non_buffered_filter_init; | 1247 u->input_filter_init = ngx_http_upstream_non_buffered_filter_init; |
1243 u->input_filter = ngx_http_upstream_non_buffered_filter; | 1248 u->input_filter = ngx_http_upstream_non_buffered_filter; |
1244 u->input_filter_ctx = r; | 1249 u->input_filter_ctx = r; |
2052 return NGX_OK; | 2057 return NGX_OK; |
2053 } | 2058 } |
2054 | 2059 |
2055 | 2060 |
2056 static ngx_int_t | 2061 static ngx_int_t |
2062 ngx_http_upstream_process_buffering(ngx_http_request_t *r, ngx_table_elt_t *h, | |
2063 ngx_uint_t offset) | |
2064 { | |
2065 u_char c0, c1, c2; | |
2066 | |
2067 if (r->upstream->conf->change_buffering) { | |
2068 | |
2069 if (h->value.len == 2) { | |
2070 c0 = ngx_tolower(h->value.data[0]); | |
2071 c1 = ngx_tolower(h->value.data[1]); | |
2072 | |
2073 if (c0 == 'n' && c1 == 'o') { | |
2074 r->upstream->buffering = 0; | |
2075 } | |
2076 | |
2077 } else if (h->value.len == 3) { | |
2078 c0 = ngx_tolower(h->value.data[0]); | |
2079 c1 = ngx_tolower(h->value.data[1]); | |
2080 c2 = ngx_tolower(h->value.data[2]); | |
2081 | |
2082 if (c0 == 'y' && c1 == 'e' && c2 == 's') { | |
2083 r->upstream->buffering = 1; | |
2084 } | |
2085 } | |
2086 } | |
2087 | |
2088 return NGX_OK; | |
2089 } | |
2090 | |
2091 | |
2092 static ngx_int_t | |
2057 ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, | 2093 ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, |
2058 ngx_uint_t offset) | 2094 ngx_uint_t offset) |
2059 { | 2095 { |
2060 ngx_table_elt_t *ho, **ph; | 2096 ngx_table_elt_t *ho, **ph; |
2061 | 2097 |
2068 | 2104 |
2069 if (offset) { | 2105 if (offset) { |
2070 ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset); | 2106 ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset); |
2071 *ph = ho; | 2107 *ph = ho; |
2072 } | 2108 } |
2073 | |
2074 return NGX_OK; | |
2075 } | |
2076 | |
2077 | |
2078 static ngx_int_t | |
2079 ngx_http_upstream_conditional_copy_header_line(ngx_http_request_t *r, | |
2080 ngx_table_elt_t *h, ngx_uint_t offset) | |
2081 { | |
2082 ngx_flag_t *f; | |
2083 ngx_table_elt_t *ho; | |
2084 | |
2085 f = (ngx_flag_t *) ((char *) r->upstream->conf + offset); | |
2086 | |
2087 if (*f == 0) { | |
2088 return NGX_OK; | |
2089 } | |
2090 | |
2091 ho = ngx_list_push(&r->headers_out.headers); | |
2092 if (ho == NULL) { | |
2093 return NGX_ERROR; | |
2094 } | |
2095 | |
2096 *ho = *h; | |
2097 | 2109 |
2098 return NGX_OK; | 2110 return NGX_OK; |
2099 } | 2111 } |
2100 | 2112 |
2101 | 2113 |
2552 static char * | 2564 static char * |
2553 ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf) | 2565 ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf) |
2554 { | 2566 { |
2555 ngx_http_upstream_main_conf_t *umcf = conf; | 2567 ngx_http_upstream_main_conf_t *umcf = conf; |
2556 | 2568 |
2557 umcf->headers_in_hash.max_size = 100; | 2569 ngx_array_t headers_in; |
2558 umcf->headers_in_hash.bucket_limit = 1; | 2570 ngx_hash_key_t *hk; |
2559 umcf->headers_in_hash.bucket_size = sizeof(ngx_http_upstream_header_t); | 2571 ngx_hash_init_t hash; |
2560 umcf->headers_in_hash.name = "upstream_headers_in"; | 2572 ngx_http_upstream_header_t *header; |
2561 | 2573 |
2562 if (ngx_hash0_init(&umcf->headers_in_hash, cf->pool, | 2574 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) |
2563 ngx_http_upstream_headers_in, 0) != NGX_OK) | 2575 != NGX_OK) |
2564 { | 2576 { |
2565 return NGX_CONF_ERROR; | 2577 return NGX_CONF_ERROR; |
2566 } | 2578 } |
2567 | 2579 |
2568 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0, | 2580 for (header = ngx_http_upstream_headers_in; header->name.len; header++) { |
2569 "http upstream headers_in hash size: %ui, " | 2581 hk = ngx_array_push(&headers_in); |
2570 "max buckets per entry: %ui", | 2582 if (hk == NULL) { |
2571 umcf->headers_in_hash.hash_size, | 2583 return NGX_CONF_ERROR; |
2572 umcf->headers_in_hash.min_buckets); | 2584 } |
2585 | |
2586 hk->key = header->name; | |
2587 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len); | |
2588 hk->value = header; | |
2589 } | |
2590 | |
2591 hash.hash = &umcf->headers_in_hash; | |
2592 hash.key = ngx_hash_key_lc; | |
2593 hash.max_size = 512; | |
2594 hash.bucket_size = ngx_cacheline_size; | |
2595 hash.name = "upstream_headers_in_hash"; | |
2596 hash.pool = cf->pool; | |
2597 hash.temp_pool = NULL; | |
2598 | |
2599 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) { | |
2600 return NGX_CONF_ERROR; | |
2601 } | |
2573 | 2602 |
2574 return NGX_CONF_OK; | 2603 return NGX_CONF_OK; |
2575 } | 2604 } |