Mercurial > hg > nginx-vendor-current
comparison src/http/modules/ngx_http_proxy_module.c @ 662:e5fa0a4a7d27 NGINX_1_1_15
nginx 1.1.15
*) Feature: the "disable_symlinks" directive.
*) Feature: the "proxy_cookie_domain" and "proxy_cookie_path"
directives.
*) Bugfix: nginx might log incorrect error "upstream prematurely closed
connection" instead of correct "upstream sent too big header" one.
Thanks to Feibo Li.
*) Bugfix: nginx could not be built with the ngx_http_perl_module if the
--with-openssl option was used.
*) Bugfix: internal redirects to named locations were not limited.
*) Bugfix: calling $r->flush() multiple times might cause errors in the
ngx_http_gzip_filter_module.
*) Bugfix: temporary files might be not removed if the "proxy_store"
directive were used with SSI includes.
*) Bugfix: in some cases non-cacheable variables (such as the $args
variable) returned old empty cached value.
*) Bugfix: a segmentation fault might occur in a worker process if too
many SSI subrequests were issued simultaneously; the bug had appeared
in 0.7.25.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Wed, 15 Feb 2012 00:00:00 +0400 |
parents | d0f7a625f27c |
children | f5b859b2f097 |
comparison
equal
deleted
inserted
replaced
661:b49c1751031c | 662:e5fa0a4a7d27 |
---|---|
8 #include <ngx_config.h> | 8 #include <ngx_config.h> |
9 #include <ngx_core.h> | 9 #include <ngx_core.h> |
10 #include <ngx_http.h> | 10 #include <ngx_http.h> |
11 | 11 |
12 | 12 |
13 typedef struct ngx_http_proxy_redirect_s ngx_http_proxy_redirect_t; | 13 typedef struct ngx_http_proxy_rewrite_s ngx_http_proxy_rewrite_t; |
14 | 14 |
15 typedef ngx_int_t (*ngx_http_proxy_redirect_pt)(ngx_http_request_t *r, | 15 typedef ngx_int_t (*ngx_http_proxy_rewrite_pt)(ngx_http_request_t *r, |
16 ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr); | 16 ngx_table_elt_t *h, size_t prefix, size_t len, |
17 | 17 ngx_http_proxy_rewrite_t *pr); |
18 struct ngx_http_proxy_redirect_s { | 18 |
19 ngx_http_proxy_redirect_pt handler; | 19 struct ngx_http_proxy_rewrite_s { |
20 ngx_http_proxy_rewrite_pt handler; | |
20 | 21 |
21 union { | 22 union { |
22 ngx_http_complex_value_t complex; | 23 ngx_http_complex_value_t complex; |
23 #if (NGX_PCRE) | 24 #if (NGX_PCRE) |
24 ngx_http_regex_t *regex; | 25 ngx_http_regex_t *regex; |
25 #endif | 26 #endif |
26 } redirect; | 27 } pattern; |
27 | 28 |
28 ngx_http_complex_value_t replacement; | 29 ngx_http_complex_value_t replacement; |
29 }; | 30 }; |
30 | 31 |
31 | 32 |
52 | 53 |
53 ngx_array_t *proxy_lengths; | 54 ngx_array_t *proxy_lengths; |
54 ngx_array_t *proxy_values; | 55 ngx_array_t *proxy_values; |
55 | 56 |
56 ngx_array_t *redirects; | 57 ngx_array_t *redirects; |
58 ngx_array_t *cookie_domains; | |
59 ngx_array_t *cookie_paths; | |
57 | 60 |
58 ngx_str_t body_source; | 61 ngx_str_t body_source; |
59 | 62 |
60 ngx_str_t method; | 63 ngx_str_t method; |
61 ngx_str_t location; | 64 ngx_str_t location; |
121 static ngx_int_t | 124 static ngx_int_t |
122 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r, | 125 ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r, |
123 ngx_http_variable_value_t *v, uintptr_t data); | 126 ngx_http_variable_value_t *v, uintptr_t data); |
124 static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, | 127 static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, |
125 ngx_table_elt_t *h, size_t prefix); | 128 ngx_table_elt_t *h, size_t prefix); |
129 static ngx_int_t ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r, | |
130 ngx_table_elt_t *h); | |
131 static ngx_int_t ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r, | |
132 ngx_table_elt_t *h, u_char *value, ngx_array_t *rewrites); | |
133 static ngx_int_t ngx_http_proxy_rewrite(ngx_http_request_t *r, | |
134 ngx_table_elt_t *h, size_t prefix, size_t len, ngx_str_t *replacement); | |
126 | 135 |
127 static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf); | 136 static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf); |
128 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); | 137 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); |
129 static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, | 138 static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, |
130 void *parent, void *child); | 139 void *parent, void *child); |
132 ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_loc_conf_t *prev); | 141 ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_loc_conf_t *prev); |
133 | 142 |
134 static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, | 143 static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, |
135 void *conf); | 144 void *conf); |
136 static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, | 145 static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, |
146 void *conf); | |
147 static char *ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd, | |
148 void *conf); | |
149 static char *ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd, | |
137 void *conf); | 150 void *conf); |
138 static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, | 151 static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, |
139 void *conf); | 152 void *conf); |
140 #if (NGX_HTTP_CACHE) | 153 #if (NGX_HTTP_CACHE) |
141 static char *ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd, | 154 static char *ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd, |
143 static char *ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, | 156 static char *ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, |
144 void *conf); | 157 void *conf); |
145 #endif | 158 #endif |
146 | 159 |
147 static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data); | 160 static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data); |
161 | |
162 static ngx_int_t ngx_http_proxy_rewrite_regex(ngx_conf_t *cf, | |
163 ngx_http_proxy_rewrite_t *pr, ngx_str_t *regex, ngx_uint_t caseless); | |
148 | 164 |
149 #if (NGX_HTTP_SSL) | 165 #if (NGX_HTTP_SSL) |
150 static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf, | 166 static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf, |
151 ngx_http_proxy_loc_conf_t *plcf); | 167 ngx_http_proxy_loc_conf_t *plcf); |
152 #endif | 168 #endif |
192 NULL }, | 208 NULL }, |
193 | 209 |
194 { ngx_string("proxy_redirect"), | 210 { ngx_string("proxy_redirect"), |
195 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, | 211 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, |
196 ngx_http_proxy_redirect, | 212 ngx_http_proxy_redirect, |
213 NGX_HTTP_LOC_CONF_OFFSET, | |
214 0, | |
215 NULL }, | |
216 | |
217 { ngx_string("proxy_cookie_domain"), | |
218 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, | |
219 ngx_http_proxy_cookie_domain, | |
220 NGX_HTTP_LOC_CONF_OFFSET, | |
221 0, | |
222 NULL }, | |
223 | |
224 { ngx_string("proxy_cookie_path"), | |
225 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, | |
226 ngx_http_proxy_cookie_path, | |
197 NGX_HTTP_LOC_CONF_OFFSET, | 227 NGX_HTTP_LOC_CONF_OFFSET, |
198 0, | 228 0, |
199 NULL }, | 229 NULL }, |
200 | 230 |
201 { ngx_string("proxy_store"), | 231 { ngx_string("proxy_store"), |
645 u->finalize_request = ngx_http_proxy_finalize_request; | 675 u->finalize_request = ngx_http_proxy_finalize_request; |
646 r->state = 0; | 676 r->state = 0; |
647 | 677 |
648 if (plcf->redirects) { | 678 if (plcf->redirects) { |
649 u->rewrite_redirect = ngx_http_proxy_rewrite_redirect; | 679 u->rewrite_redirect = ngx_http_proxy_rewrite_redirect; |
680 } | |
681 | |
682 if (plcf->cookie_domains || plcf->cookie_paths) { | |
683 u->rewrite_cookie = ngx_http_proxy_rewrite_cookie; | |
650 } | 684 } |
651 | 685 |
652 u->buffering = plcf->upstream.buffering; | 686 u->buffering = plcf->upstream.buffering; |
653 | 687 |
654 u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); | 688 u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); |
2270 | 2304 |
2271 static ngx_int_t | 2305 static ngx_int_t |
2272 ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h, | 2306 ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h, |
2273 size_t prefix) | 2307 size_t prefix) |
2274 { | 2308 { |
2309 size_t len; | |
2275 ngx_int_t rc; | 2310 ngx_int_t rc; |
2276 ngx_uint_t i; | 2311 ngx_uint_t i; |
2312 ngx_http_proxy_rewrite_t *pr; | |
2277 ngx_http_proxy_loc_conf_t *plcf; | 2313 ngx_http_proxy_loc_conf_t *plcf; |
2278 ngx_http_proxy_redirect_t *pr; | |
2279 | 2314 |
2280 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); | 2315 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); |
2281 | 2316 |
2282 pr = plcf->redirects->elts; | 2317 pr = plcf->redirects->elts; |
2283 | 2318 |
2284 if (pr == NULL) { | 2319 if (pr == NULL) { |
2285 return NGX_DECLINED; | 2320 return NGX_DECLINED; |
2286 } | 2321 } |
2287 | 2322 |
2323 len = h->value.len - prefix; | |
2324 | |
2288 for (i = 0; i < plcf->redirects->nelts; i++) { | 2325 for (i = 0; i < plcf->redirects->nelts; i++) { |
2289 rc = pr[i].handler(r, h, prefix, &pr[i]); | 2326 rc = pr[i].handler(r, h, prefix, len, &pr[i]); |
2290 | 2327 |
2291 if (rc != NGX_DECLINED) { | 2328 if (rc != NGX_DECLINED) { |
2292 return rc; | 2329 return rc; |
2293 } | 2330 } |
2294 } | 2331 } |
2296 return NGX_DECLINED; | 2333 return NGX_DECLINED; |
2297 } | 2334 } |
2298 | 2335 |
2299 | 2336 |
2300 static ngx_int_t | 2337 static ngx_int_t |
2301 ngx_http_proxy_rewrite_redirect_complex(ngx_http_request_t *r, | 2338 ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r, ngx_table_elt_t *h) |
2302 ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr) | |
2303 { | 2339 { |
2304 size_t len; | 2340 size_t prefix; |
2305 u_char *data, *p; | 2341 u_char *p; |
2306 ngx_str_t redirect, replacement; | 2342 ngx_int_t rc, rv; |
2307 | 2343 ngx_http_proxy_loc_conf_t *plcf; |
2308 if (ngx_http_complex_value(r, &pr->redirect.complex, &redirect) != NGX_OK) { | 2344 |
2345 p = (u_char *) ngx_strchr(h->value.data, ';'); | |
2346 if (p == NULL) { | |
2347 return NGX_DECLINED; | |
2348 } | |
2349 | |
2350 prefix = p + 1 - h->value.data; | |
2351 | |
2352 rv = NGX_DECLINED; | |
2353 | |
2354 plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); | |
2355 | |
2356 if (plcf->cookie_domains) { | |
2357 p = ngx_strcasestrn(h->value.data + prefix, "domain=", 7 - 1); | |
2358 | |
2359 if (p) { | |
2360 rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 7, | |
2361 plcf->cookie_domains); | |
2362 if (rc == NGX_ERROR) { | |
2363 return NGX_ERROR; | |
2364 } | |
2365 | |
2366 if (rc != NGX_DECLINED) { | |
2367 rv = rc; | |
2368 } | |
2369 } | |
2370 } | |
2371 | |
2372 if (plcf->cookie_paths) { | |
2373 p = ngx_strcasestrn(h->value.data + prefix, "path=", 5 - 1); | |
2374 | |
2375 if (p) { | |
2376 rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 5, | |
2377 plcf->cookie_paths); | |
2378 if (rc == NGX_ERROR) { | |
2379 return NGX_ERROR; | |
2380 } | |
2381 | |
2382 if (rc != NGX_DECLINED) { | |
2383 rv = rc; | |
2384 } | |
2385 } | |
2386 } | |
2387 | |
2388 return rv; | |
2389 } | |
2390 | |
2391 | |
2392 static ngx_int_t | |
2393 ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r, ngx_table_elt_t *h, | |
2394 u_char *value, ngx_array_t *rewrites) | |
2395 { | |
2396 size_t len, prefix; | |
2397 u_char *p; | |
2398 ngx_int_t rc; | |
2399 ngx_uint_t i; | |
2400 ngx_http_proxy_rewrite_t *pr; | |
2401 | |
2402 prefix = value - h->value.data; | |
2403 | |
2404 p = (u_char *) ngx_strchr(value, ';'); | |
2405 | |
2406 len = p ? (size_t) (p - value) : (h->value.len - prefix); | |
2407 | |
2408 pr = rewrites->elts; | |
2409 | |
2410 for (i = 0; i < rewrites->nelts; i++) { | |
2411 rc = pr[i].handler(r, h, prefix, len, &pr[i]); | |
2412 | |
2413 if (rc != NGX_DECLINED) { | |
2414 return rc; | |
2415 } | |
2416 } | |
2417 | |
2418 return NGX_DECLINED; | |
2419 } | |
2420 | |
2421 | |
2422 static ngx_int_t | |
2423 ngx_http_proxy_rewrite_complex_handler(ngx_http_request_t *r, | |
2424 ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr) | |
2425 { | |
2426 ngx_str_t pattern, replacement; | |
2427 | |
2428 if (ngx_http_complex_value(r, &pr->pattern.complex, &pattern) != NGX_OK) { | |
2309 return NGX_ERROR; | 2429 return NGX_ERROR; |
2310 } | 2430 } |
2311 | 2431 |
2312 if (redirect.len > h->value.len - prefix | 2432 if (pattern.len > len |
2313 || ngx_rstrncmp(h->value.data + prefix, redirect.data, | 2433 || ngx_rstrncmp(h->value.data + prefix, pattern.data, |
2314 redirect.len) != 0) | 2434 pattern.len) != 0) |
2315 { | 2435 { |
2316 return NGX_DECLINED; | 2436 return NGX_DECLINED; |
2317 } | 2437 } |
2318 | 2438 |
2319 if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) { | 2439 if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) { |
2320 return NGX_ERROR; | 2440 return NGX_ERROR; |
2321 } | 2441 } |
2322 | 2442 |
2323 len = replacement.len + h->value.len - redirect.len; | 2443 return ngx_http_proxy_rewrite(r, h, prefix, pattern.len, &replacement); |
2324 | 2444 } |
2325 data = ngx_pnalloc(r->pool, len); | 2445 |
2326 if (data == NULL) { | 2446 |
2447 #if (NGX_PCRE) | |
2448 | |
2449 static ngx_int_t | |
2450 ngx_http_proxy_rewrite_regex_handler(ngx_http_request_t *r, ngx_table_elt_t *h, | |
2451 size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr) | |
2452 { | |
2453 ngx_str_t pattern, replacement; | |
2454 | |
2455 pattern.len = len; | |
2456 pattern.data = h->value.data + prefix; | |
2457 | |
2458 if (ngx_http_regex_exec(r, pr->pattern.regex, &pattern) != NGX_OK) { | |
2459 return NGX_DECLINED; | |
2460 } | |
2461 | |
2462 if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) { | |
2327 return NGX_ERROR; | 2463 return NGX_ERROR; |
2328 } | 2464 } |
2329 | 2465 |
2330 p = ngx_copy(data, h->value.data, prefix); | 2466 if (prefix == 0 && h->value.len == len) { |
2331 | 2467 h->value = replacement; |
2332 if (replacement.len) { | 2468 return NGX_OK; |
2333 p = ngx_copy(p, replacement.data, replacement.len); | 2469 } |
2334 } | 2470 |
2335 | 2471 return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement); |
2336 ngx_memcpy(p, h->value.data + prefix + redirect.len, | 2472 } |
2337 h->value.len - redirect.len - prefix); | 2473 |
2338 | 2474 #endif |
2339 h->value.len = len; | 2475 |
2340 h->value.data = data; | 2476 |
2477 static ngx_int_t | |
2478 ngx_http_proxy_rewrite_domain_handler(ngx_http_request_t *r, | |
2479 ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr) | |
2480 { | |
2481 u_char *p; | |
2482 ngx_str_t pattern, replacement; | |
2483 | |
2484 if (ngx_http_complex_value(r, &pr->pattern.complex, &pattern) != NGX_OK) { | |
2485 return NGX_ERROR; | |
2486 } | |
2487 | |
2488 p = h->value.data + prefix; | |
2489 | |
2490 if (p[0] == '.') { | |
2491 p++; | |
2492 prefix++; | |
2493 len--; | |
2494 } | |
2495 | |
2496 if (pattern.len != len || ngx_rstrncasecmp(pattern.data, p, len) != 0) { | |
2497 return NGX_DECLINED; | |
2498 } | |
2499 | |
2500 if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) { | |
2501 return NGX_ERROR; | |
2502 } | |
2503 | |
2504 return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement); | |
2505 } | |
2506 | |
2507 | |
2508 static ngx_int_t | |
2509 ngx_http_proxy_rewrite(ngx_http_request_t *r, ngx_table_elt_t *h, size_t prefix, | |
2510 size_t len, ngx_str_t *replacement) | |
2511 { | |
2512 u_char *p, *data; | |
2513 size_t new_len; | |
2514 | |
2515 new_len = replacement->len + h->value.len - len; | |
2516 | |
2517 if (replacement->len > len) { | |
2518 | |
2519 data = ngx_pnalloc(r->pool, new_len); | |
2520 if (data == NULL) { | |
2521 return NGX_ERROR; | |
2522 } | |
2523 | |
2524 p = ngx_copy(data, h->value.data, prefix); | |
2525 p = ngx_copy(p, replacement->data, replacement->len); | |
2526 | |
2527 ngx_memcpy(p, h->value.data + prefix + len, | |
2528 h->value.len - len - prefix); | |
2529 | |
2530 h->value.data = data; | |
2531 | |
2532 } else { | |
2533 p = ngx_copy(h->value.data + prefix, replacement->data, | |
2534 replacement->len); | |
2535 | |
2536 ngx_memmove(p, h->value.data + prefix + len, | |
2537 h->value.len - len - prefix); | |
2538 } | |
2539 | |
2540 h->value.len = new_len; | |
2341 | 2541 |
2342 return NGX_OK; | 2542 return NGX_OK; |
2343 } | 2543 } |
2344 | |
2345 | |
2346 #if (NGX_PCRE) | |
2347 | |
2348 static ngx_int_t | |
2349 ngx_http_proxy_rewrite_redirect_regex(ngx_http_request_t *r, ngx_table_elt_t *h, | |
2350 size_t prefix, ngx_http_proxy_redirect_t *pr) | |
2351 { | |
2352 size_t len; | |
2353 u_char *data; | |
2354 ngx_str_t redirect, replacement; | |
2355 | |
2356 redirect.len = h->value.len - prefix; | |
2357 redirect.data = h->value.data + prefix; | |
2358 | |
2359 if (ngx_http_regex_exec(r, pr->redirect.regex, &redirect) != NGX_OK) { | |
2360 return NGX_DECLINED; | |
2361 } | |
2362 | |
2363 if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) { | |
2364 return NGX_ERROR; | |
2365 } | |
2366 | |
2367 if (!prefix) { | |
2368 h->value = replacement; | |
2369 return NGX_OK; | |
2370 } | |
2371 | |
2372 len = prefix + replacement.len; | |
2373 | |
2374 data = ngx_pnalloc(r->pool, len); | |
2375 if (data == NULL) { | |
2376 return NGX_ERROR; | |
2377 } | |
2378 | |
2379 ngx_memcpy(data, h->value.data, prefix); | |
2380 ngx_memcpy(data + prefix, replacement.data, replacement.len); | |
2381 | |
2382 h->value.len = len; | |
2383 h->value.data = data; | |
2384 | |
2385 return NGX_OK; | |
2386 } | |
2387 | |
2388 #endif | |
2389 | 2544 |
2390 | 2545 |
2391 static ngx_int_t | 2546 static ngx_int_t |
2392 ngx_http_proxy_add_variables(ngx_conf_t *cf) | 2547 ngx_http_proxy_add_variables(ngx_conf_t *cf) |
2393 { | 2548 { |
2484 conf->upstream.cyclic_temp_file = 0; | 2639 conf->upstream.cyclic_temp_file = 0; |
2485 | 2640 |
2486 conf->redirect = NGX_CONF_UNSET; | 2641 conf->redirect = NGX_CONF_UNSET; |
2487 conf->upstream.change_buffering = 1; | 2642 conf->upstream.change_buffering = 1; |
2488 | 2643 |
2644 conf->cookie_domains = NGX_CONF_UNSET_PTR; | |
2645 conf->cookie_paths = NGX_CONF_UNSET_PTR; | |
2646 | |
2489 conf->http_version = NGX_CONF_UNSET_UINT; | 2647 conf->http_version = NGX_CONF_UNSET_UINT; |
2490 | 2648 |
2491 conf->headers_hash_max_size = NGX_CONF_UNSET_UINT; | 2649 conf->headers_hash_max_size = NGX_CONF_UNSET_UINT; |
2492 conf->headers_hash_bucket_size = NGX_CONF_UNSET_UINT; | 2650 conf->headers_hash_bucket_size = NGX_CONF_UNSET_UINT; |
2493 | 2651 |
2505 | 2663 |
2506 u_char *p; | 2664 u_char *p; |
2507 size_t size; | 2665 size_t size; |
2508 ngx_hash_init_t hash; | 2666 ngx_hash_init_t hash; |
2509 ngx_http_core_loc_conf_t *clcf; | 2667 ngx_http_core_loc_conf_t *clcf; |
2510 ngx_http_proxy_redirect_t *pr; | 2668 ngx_http_proxy_rewrite_t *pr; |
2511 ngx_http_script_compile_t sc; | 2669 ngx_http_script_compile_t sc; |
2512 | 2670 |
2513 if (conf->upstream.store != 0) { | 2671 if (conf->upstream.store != 0) { |
2514 ngx_conf_merge_value(conf->upstream.store, | 2672 ngx_conf_merge_value(conf->upstream.store, |
2515 prev->upstream.store, 0); | 2673 prev->upstream.store, 0); |
2758 } | 2916 } |
2759 | 2917 |
2760 if (conf->redirects == NULL && conf->url.data) { | 2918 if (conf->redirects == NULL && conf->url.data) { |
2761 | 2919 |
2762 conf->redirects = ngx_array_create(cf->pool, 1, | 2920 conf->redirects = ngx_array_create(cf->pool, 1, |
2763 sizeof(ngx_http_proxy_redirect_t)); | 2921 sizeof(ngx_http_proxy_rewrite_t)); |
2764 if (conf->redirects == NULL) { | 2922 if (conf->redirects == NULL) { |
2765 return NGX_CONF_ERROR; | 2923 return NGX_CONF_ERROR; |
2766 } | 2924 } |
2767 | 2925 |
2768 pr = ngx_array_push(conf->redirects); | 2926 pr = ngx_array_push(conf->redirects); |
2769 if (pr == NULL) { | 2927 if (pr == NULL) { |
2770 return NGX_CONF_ERROR; | 2928 return NGX_CONF_ERROR; |
2771 } | 2929 } |
2772 | 2930 |
2773 ngx_memzero(&pr->redirect.complex, | 2931 ngx_memzero(&pr->pattern.complex, |
2774 sizeof(ngx_http_complex_value_t)); | 2932 sizeof(ngx_http_complex_value_t)); |
2775 | 2933 |
2776 ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t)); | 2934 ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t)); |
2777 | 2935 |
2778 pr->handler = ngx_http_proxy_rewrite_redirect_complex; | 2936 pr->handler = ngx_http_proxy_rewrite_complex_handler; |
2779 | 2937 |
2780 if (conf->vars.uri.len) { | 2938 if (conf->vars.uri.len) { |
2781 pr->redirect.complex.value = conf->url; | 2939 pr->pattern.complex.value = conf->url; |
2782 pr->replacement.value = conf->location; | 2940 pr->replacement.value = conf->location; |
2783 | 2941 |
2784 } else { | 2942 } else { |
2785 pr->redirect.complex.value.len = conf->url.len | 2943 pr->pattern.complex.value.len = conf->url.len |
2786 + sizeof("/") - 1; | 2944 + sizeof("/") - 1; |
2787 | 2945 |
2788 p = ngx_pnalloc(cf->pool, pr->redirect.complex.value.len); | 2946 p = ngx_pnalloc(cf->pool, pr->pattern.complex.value.len); |
2789 if (p == NULL) { | 2947 if (p == NULL) { |
2790 return NGX_CONF_ERROR; | 2948 return NGX_CONF_ERROR; |
2791 } | 2949 } |
2792 | 2950 |
2793 pr->redirect.complex.value.data = p; | 2951 pr->pattern.complex.value.data = p; |
2794 | 2952 |
2795 p = ngx_cpymem(p, conf->url.data, conf->url.len); | 2953 p = ngx_cpymem(p, conf->url.data, conf->url.len); |
2796 *p = '/'; | 2954 *p = '/'; |
2797 | 2955 |
2798 ngx_str_set(&pr->replacement.value, "/"); | 2956 ngx_str_set(&pr->replacement.value, "/"); |
2799 } | 2957 } |
2800 } | 2958 } |
2801 } | 2959 } |
2960 | |
2961 ngx_conf_merge_ptr_value(conf->cookie_domains, prev->cookie_domains, NULL); | |
2962 | |
2963 ngx_conf_merge_ptr_value(conf->cookie_paths, prev->cookie_paths, NULL); | |
2802 | 2964 |
2803 #if (NGX_HTTP_SSL) | 2965 #if (NGX_HTTP_SSL) |
2804 if (conf->upstream.ssl == NULL) { | 2966 if (conf->upstream.ssl == NULL) { |
2805 conf->upstream.ssl = prev->upstream.ssl; | 2967 conf->upstream.ssl = prev->upstream.ssl; |
2806 } | 2968 } |
3283 { | 3445 { |
3284 ngx_http_proxy_loc_conf_t *plcf = conf; | 3446 ngx_http_proxy_loc_conf_t *plcf = conf; |
3285 | 3447 |
3286 u_char *p; | 3448 u_char *p; |
3287 ngx_str_t *value; | 3449 ngx_str_t *value; |
3288 ngx_http_proxy_redirect_t *pr; | 3450 ngx_http_proxy_rewrite_t *pr; |
3289 ngx_http_compile_complex_value_t ccv; | 3451 ngx_http_compile_complex_value_t ccv; |
3290 | 3452 |
3291 if (plcf->redirect == 0) { | 3453 if (plcf->redirect == 0) { |
3292 return NGX_CONF_OK; | 3454 return NGX_CONF_OK; |
3293 } | 3455 } |
3318 } | 3480 } |
3319 } | 3481 } |
3320 | 3482 |
3321 if (plcf->redirects == NULL) { | 3483 if (plcf->redirects == NULL) { |
3322 plcf->redirects = ngx_array_create(cf->pool, 1, | 3484 plcf->redirects = ngx_array_create(cf->pool, 1, |
3323 sizeof(ngx_http_proxy_redirect_t)); | 3485 sizeof(ngx_http_proxy_rewrite_t)); |
3324 if (plcf->redirects == NULL) { | 3486 if (plcf->redirects == NULL) { |
3325 return NGX_CONF_ERROR; | 3487 return NGX_CONF_ERROR; |
3326 } | 3488 } |
3327 } | 3489 } |
3328 | 3490 |
3344 "\"proxy_redirect default\" must go " | 3506 "\"proxy_redirect default\" must go " |
3345 "after the \"proxy_pass\" directive"); | 3507 "after the \"proxy_pass\" directive"); |
3346 return NGX_CONF_ERROR; | 3508 return NGX_CONF_ERROR; |
3347 } | 3509 } |
3348 | 3510 |
3349 pr->handler = ngx_http_proxy_rewrite_redirect_complex; | 3511 pr->handler = ngx_http_proxy_rewrite_complex_handler; |
3350 | 3512 |
3351 ngx_memzero(&pr->redirect.complex, sizeof(ngx_http_complex_value_t)); | 3513 ngx_memzero(&pr->pattern.complex, sizeof(ngx_http_complex_value_t)); |
3352 | 3514 |
3353 ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t)); | 3515 ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t)); |
3354 | 3516 |
3355 if (plcf->vars.uri.len) { | 3517 if (plcf->vars.uri.len) { |
3356 pr->redirect.complex.value = plcf->url; | 3518 pr->pattern.complex.value = plcf->url; |
3357 pr->replacement.value = plcf->location; | 3519 pr->replacement.value = plcf->location; |
3358 | 3520 |
3359 } else { | 3521 } else { |
3360 pr->redirect.complex.value.len = plcf->url.len + sizeof("/") - 1; | 3522 pr->pattern.complex.value.len = plcf->url.len + sizeof("/") - 1; |
3361 | 3523 |
3362 p = ngx_pnalloc(cf->pool, pr->redirect.complex.value.len); | 3524 p = ngx_pnalloc(cf->pool, pr->pattern.complex.value.len); |
3363 if (p == NULL) { | 3525 if (p == NULL) { |
3364 return NGX_CONF_ERROR; | 3526 return NGX_CONF_ERROR; |
3365 } | 3527 } |
3366 | 3528 |
3367 pr->redirect.complex.value.data = p; | 3529 pr->pattern.complex.value.data = p; |
3368 | 3530 |
3369 p = ngx_cpymem(p, plcf->url.data, plcf->url.len); | 3531 p = ngx_cpymem(p, plcf->url.data, plcf->url.len); |
3370 *p = '/'; | 3532 *p = '/'; |
3371 | 3533 |
3372 ngx_str_set(&pr->replacement.value, "/"); | 3534 ngx_str_set(&pr->replacement.value, "/"); |
3375 return NGX_CONF_OK; | 3537 return NGX_CONF_OK; |
3376 } | 3538 } |
3377 | 3539 |
3378 | 3540 |
3379 if (value[1].data[0] == '~') { | 3541 if (value[1].data[0] == '~') { |
3380 #if (NGX_PCRE) | |
3381 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
3382 ngx_regex_compile_t rc; | |
3383 | |
3384 value[1].len--; | 3542 value[1].len--; |
3385 value[1].data++; | 3543 value[1].data++; |
3386 | |
3387 ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); | |
3388 | 3544 |
3389 if (value[1].data[0] == '*') { | 3545 if (value[1].data[0] == '*') { |
3390 value[1].len--; | 3546 value[1].len--; |
3391 value[1].data++; | 3547 value[1].data++; |
3392 rc.options = NGX_REGEX_CASELESS; | 3548 |
3393 } | 3549 if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) { |
3394 | 3550 return NGX_CONF_ERROR; |
3395 rc.pattern = value[1]; | 3551 } |
3396 rc.err.len = NGX_MAX_CONF_ERRSTR; | 3552 |
3397 rc.err.data = errstr; | 3553 } else { |
3398 | 3554 if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 0) != NGX_OK) { |
3399 pr->redirect.regex = ngx_http_regex_compile(cf, &rc); | 3555 return NGX_CONF_ERROR; |
3400 if (pr->redirect.regex == NULL) { | 3556 } |
3401 return NGX_CONF_ERROR; | 3557 } |
3402 } | 3558 |
3403 | |
3404 pr->handler = ngx_http_proxy_rewrite_redirect_regex; | |
3405 | |
3406 #else | |
3407 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
3408 "using regex \"%V\" requires PCRE library", | |
3409 &value[1]); | |
3410 | |
3411 return NGX_CONF_ERROR; | |
3412 #endif | |
3413 } else { | 3559 } else { |
3414 | 3560 |
3415 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | 3561 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); |
3416 | 3562 |
3417 ccv.cf = cf; | 3563 ccv.cf = cf; |
3418 ccv.value = &value[1]; | 3564 ccv.value = &value[1]; |
3419 ccv.complex_value = &pr->redirect.complex; | 3565 ccv.complex_value = &pr->pattern.complex; |
3420 | 3566 |
3421 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | 3567 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { |
3422 return NGX_CONF_ERROR; | 3568 return NGX_CONF_ERROR; |
3423 } | 3569 } |
3424 | 3570 |
3425 pr->handler = ngx_http_proxy_rewrite_redirect_complex; | 3571 pr->handler = ngx_http_proxy_rewrite_complex_handler; |
3426 } | 3572 } |
3427 | 3573 |
3428 | 3574 |
3429 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | 3575 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); |
3430 | 3576 |
3435 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | 3581 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { |
3436 return NGX_CONF_ERROR; | 3582 return NGX_CONF_ERROR; |
3437 } | 3583 } |
3438 | 3584 |
3439 return NGX_CONF_OK; | 3585 return NGX_CONF_OK; |
3586 } | |
3587 | |
3588 | |
3589 static char * | |
3590 ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
3591 { | |
3592 ngx_http_proxy_loc_conf_t *plcf = conf; | |
3593 | |
3594 ngx_str_t *value; | |
3595 ngx_http_proxy_rewrite_t *pr; | |
3596 ngx_http_compile_complex_value_t ccv; | |
3597 | |
3598 if (plcf->cookie_domains == NULL) { | |
3599 return NGX_CONF_OK; | |
3600 } | |
3601 | |
3602 value = cf->args->elts; | |
3603 | |
3604 if (cf->args->nelts == 2) { | |
3605 | |
3606 if (ngx_strcmp(value[1].data, "off") == 0) { | |
3607 plcf->cookie_domains = NULL; | |
3608 return NGX_CONF_OK; | |
3609 } | |
3610 | |
3611 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
3612 "invalid parameter \"%V\"", &value[1]); | |
3613 return NGX_CONF_ERROR; | |
3614 } | |
3615 | |
3616 if (plcf->cookie_domains == NGX_CONF_UNSET_PTR) { | |
3617 plcf->cookie_domains = ngx_array_create(cf->pool, 1, | |
3618 sizeof(ngx_http_proxy_rewrite_t)); | |
3619 if (plcf->cookie_domains == NULL) { | |
3620 return NGX_CONF_ERROR; | |
3621 } | |
3622 } | |
3623 | |
3624 pr = ngx_array_push(plcf->cookie_domains); | |
3625 if (pr == NULL) { | |
3626 return NGX_CONF_ERROR; | |
3627 } | |
3628 | |
3629 if (value[1].data[0] == '~') { | |
3630 value[1].len--; | |
3631 value[1].data++; | |
3632 | |
3633 if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) { | |
3634 return NGX_CONF_ERROR; | |
3635 } | |
3636 | |
3637 } else { | |
3638 | |
3639 if (value[1].data[0] == '.') { | |
3640 value[1].len--; | |
3641 value[1].data++; | |
3642 } | |
3643 | |
3644 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
3645 | |
3646 ccv.cf = cf; | |
3647 ccv.value = &value[1]; | |
3648 ccv.complex_value = &pr->pattern.complex; | |
3649 | |
3650 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
3651 return NGX_CONF_ERROR; | |
3652 } | |
3653 | |
3654 pr->handler = ngx_http_proxy_rewrite_domain_handler; | |
3655 | |
3656 if (value[2].data[0] == '.') { | |
3657 value[2].len--; | |
3658 value[2].data++; | |
3659 } | |
3660 } | |
3661 | |
3662 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
3663 | |
3664 ccv.cf = cf; | |
3665 ccv.value = &value[2]; | |
3666 ccv.complex_value = &pr->replacement; | |
3667 | |
3668 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
3669 return NGX_CONF_ERROR; | |
3670 } | |
3671 | |
3672 return NGX_CONF_OK; | |
3673 } | |
3674 | |
3675 | |
3676 static char * | |
3677 ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
3678 { | |
3679 ngx_http_proxy_loc_conf_t *plcf = conf; | |
3680 | |
3681 ngx_str_t *value; | |
3682 ngx_http_proxy_rewrite_t *pr; | |
3683 ngx_http_compile_complex_value_t ccv; | |
3684 | |
3685 if (plcf->cookie_paths == NULL) { | |
3686 return NGX_CONF_OK; | |
3687 } | |
3688 | |
3689 value = cf->args->elts; | |
3690 | |
3691 if (cf->args->nelts == 2) { | |
3692 | |
3693 if (ngx_strcmp(value[1].data, "off") == 0) { | |
3694 plcf->cookie_paths = NULL; | |
3695 return NGX_CONF_OK; | |
3696 } | |
3697 | |
3698 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
3699 "invalid parameter \"%V\"", &value[1]); | |
3700 return NGX_CONF_ERROR; | |
3701 } | |
3702 | |
3703 if (plcf->cookie_paths == NGX_CONF_UNSET_PTR) { | |
3704 plcf->cookie_paths = ngx_array_create(cf->pool, 1, | |
3705 sizeof(ngx_http_proxy_rewrite_t)); | |
3706 if (plcf->cookie_paths == NULL) { | |
3707 return NGX_CONF_ERROR; | |
3708 } | |
3709 } | |
3710 | |
3711 pr = ngx_array_push(plcf->cookie_paths); | |
3712 if (pr == NULL) { | |
3713 return NGX_CONF_ERROR; | |
3714 } | |
3715 | |
3716 if (value[1].data[0] == '~') { | |
3717 value[1].len--; | |
3718 value[1].data++; | |
3719 | |
3720 if (value[1].data[0] == '*') { | |
3721 value[1].len--; | |
3722 value[1].data++; | |
3723 | |
3724 if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) { | |
3725 return NGX_CONF_ERROR; | |
3726 } | |
3727 | |
3728 } else { | |
3729 if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 0) != NGX_OK) { | |
3730 return NGX_CONF_ERROR; | |
3731 } | |
3732 } | |
3733 | |
3734 } else { | |
3735 | |
3736 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
3737 | |
3738 ccv.cf = cf; | |
3739 ccv.value = &value[1]; | |
3740 ccv.complex_value = &pr->pattern.complex; | |
3741 | |
3742 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
3743 return NGX_CONF_ERROR; | |
3744 } | |
3745 | |
3746 pr->handler = ngx_http_proxy_rewrite_complex_handler; | |
3747 } | |
3748 | |
3749 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
3750 | |
3751 ccv.cf = cf; | |
3752 ccv.value = &value[2]; | |
3753 ccv.complex_value = &pr->replacement; | |
3754 | |
3755 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
3756 return NGX_CONF_ERROR; | |
3757 } | |
3758 | |
3759 return NGX_CONF_OK; | |
3760 } | |
3761 | |
3762 | |
3763 static ngx_int_t | |
3764 ngx_http_proxy_rewrite_regex(ngx_conf_t *cf, ngx_http_proxy_rewrite_t *pr, | |
3765 ngx_str_t *regex, ngx_uint_t caseless) | |
3766 { | |
3767 #if (NGX_PCRE) | |
3768 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
3769 ngx_regex_compile_t rc; | |
3770 | |
3771 ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); | |
3772 | |
3773 rc.pattern = *regex; | |
3774 rc.err.len = NGX_MAX_CONF_ERRSTR; | |
3775 rc.err.data = errstr; | |
3776 | |
3777 if (caseless) { | |
3778 rc.options = NGX_REGEX_CASELESS; | |
3779 } | |
3780 | |
3781 pr->pattern.regex = ngx_http_regex_compile(cf, &rc); | |
3782 if (pr->pattern.regex == NULL) { | |
3783 return NGX_ERROR; | |
3784 } | |
3785 | |
3786 pr->handler = ngx_http_proxy_rewrite_regex_handler; | |
3787 | |
3788 return NGX_OK; | |
3789 | |
3790 #else | |
3791 | |
3792 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
3793 "using regex \"%V\" requires PCRE library", regex); | |
3794 return NGX_ERROR; | |
3795 | |
3796 #endif | |
3440 } | 3797 } |
3441 | 3798 |
3442 | 3799 |
3443 static char * | 3800 static char * |
3444 ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 3801 ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |