comparison src/http/modules/proxy/ngx_http_proxy_upstream.c @ 34:aab2ea7c0458 NGINX_0_1_17

nginx 0.1.17 *) 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; bug appeared in 0.1.14. *) Bugfix: the system error message was not logged on Linux.
author Igor Sysoev <http://sysoev.ru>
date Thu, 03 Feb 2005 00:00:00 +0300
parents 7ca9bdc82b3f
children a39d1b793287
comparison
equal deleted inserted replaced
33:27f09a550803 34:aab2ea7c0458
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;