comparison src/http/ngx_http_upstream.c @ 198:e6da4931e0e0 NGINX_0_3_46

nginx 0.3.46 *) 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 <http://sysoev.ru>
date Thu, 11 May 2006 00:00:00 +0400
parents 3689cd4e3228
children d2ae1c9f1fd3
comparison
equal deleted inserted replaced
197:93658b91fad2 198:e6da4931e0e0
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 }