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)