Mercurial > hg > nginx
comparison src/http/modules/proxy/ngx_http_proxy_upstream.c @ 485:4ebe09b07e30 release-0.1.17
nginx-0.1.17-RELEASE import
*) Change: the ngx_http_rewrite_module was rewritten from the scratch.
Now it is possible to redirect, to return the error codes, to check
the variables and referrers. The directives can be used inside
locations. The redirect directive was canceled.
*) Feature: the ngx_http_geo_module.
*) Feature: the proxy_set_x_var and fastcgi_set_var directives.
*) Bugfix: the location configuration with "=" modifier may be used in
another location.
*) Bugfix: the correct content type was set only for requests that use
small caps letters in extension.
*) Bugfix: if the proxy_pass or fastcgi_pass directives were set in the
location, and access was denied, and the error was redirected to a
static page, then the segmentation fault occurred.
*) Bugfix: if in a proxied "Location" header was a relative URL, then a
host name and a slash were added to them; the bug had appeared in
0.1.14.
*) Bugfix: the system error message was not logged on Linux.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 03 Feb 2005 19:33:37 +0000 |
parents | c52408583801 |
children | 31ff3e943e16 |
comparison
equal
deleted
inserted
replaced
484:60452f1c0c62 | 485:4ebe09b07e30 |
---|---|
84 | 84 |
85 | 85 |
86 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) | 86 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) |
87 { | 87 { |
88 size_t len; | 88 size_t len; |
89 ngx_int_t escape; | 89 ngx_uint_t i, escape, *index; |
90 ngx_uint_t i; | |
91 ngx_buf_t *b; | 90 ngx_buf_t *b; |
92 ngx_chain_t *chain; | 91 ngx_chain_t *chain; |
93 ngx_list_part_t *part; | 92 ngx_list_part_t *part; |
94 ngx_table_elt_t *header; | 93 ngx_table_elt_t *header; |
95 ngx_http_request_t *r; | 94 ngx_http_request_t *r; |
95 ngx_http_variable_t *var; | |
96 ngx_http_variable_value_t *value; | |
97 ngx_http_core_main_conf_t *cmcf; | |
96 ngx_http_proxy_upstream_conf_t *uc; | 98 ngx_http_proxy_upstream_conf_t *uc; |
97 | 99 |
98 r = p->request; | 100 r = p->request; |
99 uc = p->lcf->upstream; | 101 uc = p->lcf->upstream; |
100 | 102 |
113 escape = 0; | 115 escape = 0; |
114 } | 116 } |
115 | 117 |
116 len += uc->uri.len | 118 len += uc->uri.len |
117 + r->uri.len - uc->location->len + escape | 119 + r->uri.len - uc->location->len + escape |
118 + 1 + r->args.len /* 1 is for "?" */ | 120 + sizeof("?") - 1 + r->args.len |
119 + sizeof(http_version) - 1 | 121 + sizeof(http_version) - 1 |
120 + sizeof(connection_close_header) - 1 | 122 + sizeof(connection_close_header) - 1 |
121 + 2; /* 2 is for "\r\n" at the header end */ | 123 + sizeof(CRLF) - 1; |
122 | 124 |
123 | 125 |
124 if (p->lcf->set_x_url) { | 126 if (p->lcf->set_x_url) { |
125 len += sizeof(x_url_header) - 1 | 127 len += sizeof(x_url_header) - 1 |
126 + 4 /* 4 is for "s://" */ | 128 + sizeof("s://") - 1 |
127 + r->port_text->len | 129 + r->port_text->len |
128 + r->unparsed_uri.len | 130 + r->unparsed_uri.len |
129 + 2; /* 2 is for "\r\n" at the header end */ | 131 + sizeof(CRLF) - 1; |
130 | 132 |
131 if (r->headers_in.host) { | 133 if (r->headers_in.host) { |
132 len += r->headers_in.host_name_len; | 134 len += r->headers_in.host_name_len; |
133 | 135 |
134 } else { | 136 } else { |
138 } | 140 } |
139 | 141 |
140 | 142 |
141 if (p->lcf->preserve_host && r->headers_in.host) { | 143 if (p->lcf->preserve_host && r->headers_in.host) { |
142 len += sizeof(host_header) - 1 | 144 len += sizeof(host_header) - 1 |
143 + r->headers_in.host_name_len | 145 + r->headers_in.host_name_len + sizeof(":") - 1 + uc->port_text.len |
144 + 1 /* 1 is for ":" */ | 146 + sizeof(CRLF) - 1; |
145 + uc->port_text.len | 147 } else { |
146 + 2; /* 2 is for "\r\n" */ | 148 len += sizeof(host_header) - 1 + uc->host_header.len |
147 } else { /* 2 is for "\r\n" */ | 149 + sizeof(CRLF) - 1; |
148 len += sizeof(host_header) - 1 + uc->host_header.len + 2; | 150 } |
149 } | 151 |
150 | 152 |
151 | 153 if (p->lcf->set_x_real_ip) { |
152 if (p->lcf->set_x_real_ip) { /* 2 is for "\r\n" */ | 154 len += sizeof(x_real_ip_header) - 1 + INET_ADDRSTRLEN - 1 |
153 len += sizeof(x_real_ip_header) - 1 + INET_ADDRSTRLEN - 1 + 2; | 155 + sizeof(CRLF) - 1; |
154 } | 156 } |
155 | 157 |
156 | 158 |
157 if (p->lcf->add_x_forwarded_for) { | 159 if (p->lcf->add_x_forwarded_for) { |
158 if (r->headers_in.x_forwarded_for) { | 160 if (r->headers_in.x_forwarded_for) { |
159 len += sizeof(x_forwarded_for_header) - 1 | 161 len += sizeof(x_forwarded_for_header) - 1 |
160 + r->headers_in.x_forwarded_for->value.len | 162 + r->headers_in.x_forwarded_for->value.len |
161 + 2 /* 2 is ofr ", " */ | 163 + sizeof(", ") - 1 + INET_ADDRSTRLEN - 1 + sizeof(CRLF) - 1; |
162 + INET_ADDRSTRLEN - 1 | 164 |
163 + 2; /* 2 is for "\r\n" */ | |
164 } else { | 165 } else { |
165 len += sizeof(x_forwarded_for_header) - 1 + INET_ADDRSTRLEN - 1 + 2; | 166 len += sizeof(x_forwarded_for_header) - 1 + INET_ADDRSTRLEN - 1 |
166 /* 2 is for "\r\n" */ | 167 + sizeof(CRLF) - 1; |
168 } | |
169 } | |
170 | |
171 | |
172 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
173 | |
174 var = cmcf->variables.elts; | |
175 index = p->lcf->x_vars.elts; | |
176 | |
177 for (i = 0; i < p->lcf->x_vars.nelts; i++) { | |
178 | |
179 if (!(value = ngx_http_get_variable(r, index[i]))) { | |
180 continue; | |
181 } | |
182 | |
183 if (value->text.len) { | |
184 len += sizeof("X-") - 1 + var[index[i]].name.len + sizeof(": ") - 1 | |
185 + value->text.len + sizeof(CRLF) - 1; | |
167 } | 186 } |
168 } | 187 } |
169 | 188 |
170 | 189 |
171 part = &r->headers_in.headers.part; | 190 part = &r->headers_in.headers.part; |
189 | 208 |
190 if (&header[i] == r->headers_in.connection) { | 209 if (&header[i] == r->headers_in.connection) { |
191 continue; | 210 continue; |
192 } | 211 } |
193 | 212 |
194 /* 2 is for ": " and 2 is for "\r\n" */ | 213 len += header[i].key.len + sizeof(": ") - 1 |
195 len += header[i].key.len + 2 + header[i].value.len + 2; | 214 + header[i].value.len + sizeof(CRLF) - 1; |
196 } | 215 } |
197 | 216 |
198 #if (NGX_DEBUG) | 217 #if (NGX_DEBUG) |
199 len++; | 218 len++; |
200 #endif | 219 #endif |
201 | 220 |
202 ngx_test_null(b, ngx_create_temp_buf(r->pool, len), NULL); | 221 if (!(b = ngx_create_temp_buf(r->pool, len))) { |
203 ngx_alloc_link_and_set_buf(chain, b, r->pool, NULL); | 222 return NULL; |
223 } | |
224 | |
225 if (!(chain = ngx_alloc_chain_link(r->pool))) { | |
226 return NULL; | |
227 } | |
228 | |
229 chain->buf = b; | |
230 chain->next = NULL; | |
204 | 231 |
205 | 232 |
206 /* the request line */ | 233 /* the request line */ |
207 | 234 |
208 if (p->upstream->method) { | 235 if (p->upstream->method) { |
225 r->uri.data + uc->location->len, | 252 r->uri.data + uc->location->len, |
226 r->uri.len - uc->location->len); | 253 r->uri.len - uc->location->len); |
227 } | 254 } |
228 | 255 |
229 if (r->args.len > 0) { | 256 if (r->args.len > 0) { |
230 *(b->last++) = '?'; | 257 *b->last++ = '?'; |
231 b->last = ngx_cpymem(b->last, r->args.data, r->args.len); | 258 b->last = ngx_cpymem(b->last, r->args.data, r->args.len); |
232 } | 259 } |
233 | 260 |
234 b->last = ngx_cpymem(b->last, http_version, sizeof(http_version) - 1); | 261 b->last = ngx_cpymem(b->last, http_version, sizeof(http_version) - 1); |
235 | 262 |
247 if (p->lcf->preserve_host && r->headers_in.host) { | 274 if (p->lcf->preserve_host && r->headers_in.host) { |
248 b->last = ngx_cpymem(b->last, r->headers_in.host->value.data, | 275 b->last = ngx_cpymem(b->last, r->headers_in.host->value.data, |
249 r->headers_in.host_name_len); | 276 r->headers_in.host_name_len); |
250 | 277 |
251 if (!uc->default_port) { | 278 if (!uc->default_port) { |
252 *(b->last++) = ':'; | 279 *b->last++ = ':'; |
253 b->last = ngx_cpymem(b->last, uc->port_text.data, | 280 b->last = ngx_cpymem(b->last, uc->port_text.data, |
254 uc->port_text.len); | 281 uc->port_text.len); |
255 } | 282 } |
256 | 283 |
257 } else { | 284 } else { |
258 b->last = ngx_cpymem(b->last, uc->host_header.data, | 285 b->last = ngx_cpymem(b->last, uc->host_header.data, |
259 uc->host_header.len); | 286 uc->host_header.len); |
260 } | 287 } |
261 *(b->last++) = CR; *(b->last++) = LF; | 288 *b->last++ = CR; *b->last++ = LF; |
262 | 289 |
263 | 290 |
264 /* the "X-URL" header */ | 291 /* the "X-URL" header */ |
265 | 292 |
266 if (p->lcf->set_x_url) { | 293 if (p->lcf->set_x_url) { |
269 sizeof(x_url_header) - 1); | 296 sizeof(x_url_header) - 1); |
270 | 297 |
271 #if (NGX_OPENSSL) | 298 #if (NGX_OPENSSL) |
272 | 299 |
273 if (r->connection->ssl) { | 300 if (r->connection->ssl) { |
274 *(b->last++) = 's'; | 301 *b->last++ = 's'; |
275 } | 302 } |
276 | 303 |
277 #endif | 304 #endif |
278 | 305 |
279 *(b->last++) = ':'; *(b->last++) = '/'; *(b->last++) = '/'; | 306 *b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/'; |
280 | 307 |
281 if (r->headers_in.host) { | 308 if (r->headers_in.host) { |
282 b->last = ngx_cpymem(b->last, r->headers_in.host->value.data, | 309 b->last = ngx_cpymem(b->last, r->headers_in.host->value.data, |
283 r->headers_in.host_name_len); | 310 r->headers_in.host_name_len); |
284 } else { | 311 } else { |
288 | 315 |
289 b->last = ngx_cpymem(b->last, r->port_text->data, r->port_text->len); | 316 b->last = ngx_cpymem(b->last, r->port_text->data, r->port_text->len); |
290 b->last = ngx_cpymem(b->last, r->unparsed_uri.data, | 317 b->last = ngx_cpymem(b->last, r->unparsed_uri.data, |
291 r->unparsed_uri.len); | 318 r->unparsed_uri.len); |
292 | 319 |
293 *(b->last++) = CR; *(b->last++) = LF; | 320 *b->last++ = CR; *b->last++ = LF; |
294 } | 321 } |
295 | 322 |
296 | 323 |
297 /* the "X-Real-IP" header */ | 324 /* the "X-Real-IP" header */ |
298 | 325 |
299 if (p->lcf->set_x_real_ip) { | 326 if (p->lcf->set_x_real_ip) { |
300 b->last = ngx_cpymem(b->last, x_real_ip_header, | 327 b->last = ngx_cpymem(b->last, x_real_ip_header, |
301 sizeof(x_real_ip_header) - 1); | 328 sizeof(x_real_ip_header) - 1); |
302 b->last = ngx_cpymem(b->last, r->connection->addr_text.data, | 329 b->last = ngx_cpymem(b->last, r->connection->addr_text.data, |
303 r->connection->addr_text.len); | 330 r->connection->addr_text.len); |
304 *(b->last++) = CR; *(b->last++) = LF; | 331 *b->last++ = CR; *b->last++ = LF; |
305 } | 332 } |
306 | 333 |
307 | 334 |
308 /* the "X-Forwarded-For" header */ | 335 /* the "X-Forwarded-For" header */ |
309 | 336 |
314 | 341 |
315 b->last = ngx_cpymem(b->last, | 342 b->last = ngx_cpymem(b->last, |
316 r->headers_in.x_forwarded_for->value.data, | 343 r->headers_in.x_forwarded_for->value.data, |
317 r->headers_in.x_forwarded_for->value.len); | 344 r->headers_in.x_forwarded_for->value.len); |
318 | 345 |
319 *(b->last++) = ','; *(b->last++) = ' '; | 346 *b->last++ = ','; *b->last++ = ' '; |
320 | 347 |
321 } else { | 348 } else { |
322 b->last = ngx_cpymem(b->last, x_forwarded_for_header, | 349 b->last = ngx_cpymem(b->last, x_forwarded_for_header, |
323 sizeof(x_forwarded_for_header) - 1); | 350 sizeof(x_forwarded_for_header) - 1); |
324 } | 351 } |
325 | 352 |
326 b->last = ngx_cpymem(b->last, r->connection->addr_text.data, | 353 b->last = ngx_cpymem(b->last, r->connection->addr_text.data, |
327 r->connection->addr_text.len); | 354 r->connection->addr_text.len); |
328 *(b->last++) = CR; *(b->last++) = LF; | 355 *b->last++ = CR; *b->last++ = LF; |
356 } | |
357 | |
358 | |
359 for (i = 0; i < p->lcf->x_vars.nelts; i++) { | |
360 | |
361 if (!(value = ngx_http_get_variable(r, index[i]))) { | |
362 continue; | |
363 } | |
364 | |
365 if (value->text.len == 0) { | |
366 continue; | |
367 } | |
368 | |
369 *b->last++ = 'X'; *b->last++ = '-'; | |
370 | |
371 b->last = ngx_cpymem(b->last, var[index[i]].name.data, | |
372 var[index[i]].name.len); | |
373 | |
374 *b->last++ = ':'; *b->last++ = ' '; | |
375 | |
376 b->last = ngx_cpymem(b->last, value->text.data, value->text.len); | |
377 | |
378 *b->last++ = CR; *b->last++ = LF; | |
329 } | 379 } |
330 | 380 |
331 | 381 |
332 part = &r->headers_in.headers.part; | 382 part = &r->headers_in.headers.part; |
333 header = part->elts; | 383 header = part->elts; |
370 continue; | 420 continue; |
371 } | 421 } |
372 | 422 |
373 b->last = ngx_cpymem(b->last, header[i].key.data, header[i].key.len); | 423 b->last = ngx_cpymem(b->last, header[i].key.data, header[i].key.len); |
374 | 424 |
375 *(b->last++) = ':'; *(b->last++) = ' '; | 425 *b->last++ = ':'; *b->last++ = ' '; |
376 | 426 |
377 b->last = ngx_cpymem(b->last, header[i].value.data, | 427 b->last = ngx_cpymem(b->last, header[i].value.data, |
378 header[i].value.len); | 428 header[i].value.len); |
379 | 429 |
380 *(b->last++) = CR; *(b->last++) = LF; | 430 *b->last++ = CR; *b->last++ = LF; |
381 | 431 |
382 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 432 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
383 "http proxy header: \"%V: %V\"", | 433 "http proxy header: \"%V: %V\"", |
384 &header[i].key, &header[i].value); | 434 &header[i].key, &header[i].value); |
385 } | 435 } |
386 | 436 |
387 /* add "\r\n" at the header end */ | 437 /* add "\r\n" at the header end */ |
388 *(b->last++) = CR; *(b->last++) = LF; | 438 *b->last++ = CR; *b->last++ = LF; |
389 | 439 |
390 #if (NGX_DEBUG) | 440 #if (NGX_DEBUG) |
391 *(b->last) = '\0'; | 441 *b->last = '\0'; |
392 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 442 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
393 "http proxy header:\n\"%s\"", b->pos); | 443 "http proxy header:\n\"%s\"", b->pos); |
394 #endif | 444 #endif |
395 | 445 |
396 return chain; | 446 return chain; |