comparison src/http/modules/ngx_http_proxy_module.c @ 654:753f505670e0 NGINX_1_1_11

nginx 1.1.11 *) Feature: the "so_keepalive" parameter of the "listen" directive. Thanks to Vsevolod Stakhov. *) Feature: the "if_not_empty" parameter of the "fastcgi/scgi/uwsgi_param" directives. *) Feature: the $https variable. *) Feature: the "proxy_redirect" directive supports variables in the first parameter. *) Feature: the "proxy_redirect" directive supports regular expressions. *) Bugfix: the $sent_http_cache_control variable might contain a wrong value if the "expires" directive was used. Thanks to Yichun Zhang. *) Bugfix: the "read_ahead" directive might not work combined with "try_files" and "open_file_cache". *) Bugfix: a segmentation fault might occur in a worker process if small time was used in the "inactive" parameter of the "proxy_cache_path" directive. *) Bugfix: responses from cache might hang.
author Igor Sysoev <http://sysoev.ru>
date Mon, 12 Dec 2011 00:00:00 +0400
parents f200748c0ac8
children 9d21dad0b5a1
comparison
equal deleted inserted replaced
653:8c96af2112c1 654:753f505670e0
14 typedef ngx_int_t (*ngx_http_proxy_redirect_pt)(ngx_http_request_t *r, 14 typedef ngx_int_t (*ngx_http_proxy_redirect_pt)(ngx_http_request_t *r,
15 ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr); 15 ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr);
16 16
17 struct ngx_http_proxy_redirect_s { 17 struct ngx_http_proxy_redirect_s {
18 ngx_http_proxy_redirect_pt handler; 18 ngx_http_proxy_redirect_pt handler;
19 ngx_str_t redirect;
20 19
21 union { 20 union {
22 ngx_str_t text; 21 ngx_http_complex_value_t complex;
23 22 #if (NGX_PCRE)
24 struct { 23 ngx_http_regex_t *regex;
25 void *lengths; 24 #endif
26 void *values; 25 } redirect;
27 } vars; 26
28 27 ngx_http_complex_value_t replacement;
29 void *regex;
30 } replacement;
31 }; 28 };
32 29
33 30
34 typedef struct { 31 typedef struct {
35 ngx_str_t key_start; 32 ngx_str_t key_start;
2287 return NGX_DECLINED; 2284 return NGX_DECLINED;
2288 } 2285 }
2289 2286
2290 2287
2291 static ngx_int_t 2288 static ngx_int_t
2292 ngx_http_proxy_rewrite_redirect_text(ngx_http_request_t *r, ngx_table_elt_t *h, 2289 ngx_http_proxy_rewrite_redirect_complex(ngx_http_request_t *r,
2293 size_t prefix, ngx_http_proxy_redirect_t *pr) 2290 ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr)
2294 { 2291 {
2295 size_t len; 2292 size_t len;
2296 u_char *data, *p; 2293 u_char *data, *p;
2297 2294 ngx_str_t redirect, replacement;
2298 if (pr->redirect.len > h->value.len - prefix 2295
2299 || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data, 2296 if (ngx_http_complex_value(r, &pr->redirect.complex, &redirect) != NGX_OK) {
2300 pr->redirect.len) != 0) 2297 return NGX_ERROR;
2298 }
2299
2300 if (redirect.len > h->value.len - prefix
2301 || ngx_rstrncmp(h->value.data + prefix, redirect.data,
2302 redirect.len) != 0)
2301 { 2303 {
2302 return NGX_DECLINED; 2304 return NGX_DECLINED;
2303 } 2305 }
2304 2306
2305 len = pr->replacement.text.len + h->value.len - pr->redirect.len; 2307 if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
2308 return NGX_ERROR;
2309 }
2310
2311 len = replacement.len + h->value.len - redirect.len;
2306 2312
2307 data = ngx_pnalloc(r->pool, len); 2313 data = ngx_pnalloc(r->pool, len);
2308 if (data == NULL) { 2314 if (data == NULL) {
2309 return NGX_ERROR; 2315 return NGX_ERROR;
2310 } 2316 }
2311 2317
2312 p = ngx_copy(data, h->value.data, prefix); 2318 p = ngx_copy(data, h->value.data, prefix);
2313 2319
2314 if (pr->replacement.text.len) { 2320 if (replacement.len) {
2315 p = ngx_copy(p, pr->replacement.text.data, pr->replacement.text.len); 2321 p = ngx_copy(p, replacement.data, replacement.len);
2316 } 2322 }
2317 2323
2318 ngx_memcpy(p, h->value.data + prefix + pr->redirect.len, 2324 ngx_memcpy(p, h->value.data + prefix + redirect.len,
2319 h->value.len - pr->redirect.len - prefix); 2325 h->value.len - redirect.len - prefix);
2320 2326
2321 h->value.len = len; 2327 h->value.len = len;
2322 h->value.data = data; 2328 h->value.data = data;
2323 2329
2324 return NGX_OK; 2330 return NGX_OK;
2325 } 2331 }
2326 2332
2327 2333
2334 #if (NGX_PCRE)
2335
2328 static ngx_int_t 2336 static ngx_int_t
2329 ngx_http_proxy_rewrite_redirect_vars(ngx_http_request_t *r, ngx_table_elt_t *h, 2337 ngx_http_proxy_rewrite_redirect_regex(ngx_http_request_t *r, ngx_table_elt_t *h,
2330 size_t prefix, ngx_http_proxy_redirect_t *pr) 2338 size_t prefix, ngx_http_proxy_redirect_t *pr)
2331 { 2339 {
2332 size_t len; 2340 ngx_str_t redirect, replacement;
2333 u_char *data, *p; 2341
2334 ngx_http_script_code_pt code; 2342 redirect.len = h->value.len - prefix;
2335 ngx_http_script_engine_t e; 2343 redirect.data = h->value.data + prefix;
2336 ngx_http_script_len_code_pt lcode; 2344
2337 2345 if (ngx_http_regex_exec(r, pr->redirect.regex, &redirect) != NGX_OK) {
2338 if (pr->redirect.len > h->value.len - prefix
2339 || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data,
2340 pr->redirect.len) != 0)
2341 {
2342 return NGX_DECLINED; 2346 return NGX_DECLINED;
2343 } 2347 }
2344 2348
2345 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); 2349 if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
2346
2347 e.ip = pr->replacement.vars.lengths;
2348 e.request = r;
2349
2350 len = h->value.len - pr->redirect.len;
2351
2352 while (*(uintptr_t *) e.ip) {
2353 lcode = *(ngx_http_script_len_code_pt *) e.ip;
2354 len += lcode(&e);
2355 }
2356
2357 data = ngx_pnalloc(r->pool, len);
2358 if (data == NULL) {
2359 return NGX_ERROR; 2350 return NGX_ERROR;
2360 } 2351 }
2361 2352
2362 p = ngx_copy(data, h->value.data, prefix); 2353 h->value = replacement;
2363
2364 e.ip = pr->replacement.vars.values;
2365 e.pos = p;
2366
2367 while (*(uintptr_t *) e.ip) {
2368 code = *(ngx_http_script_code_pt *) e.ip;
2369 code(&e);
2370 }
2371
2372 ngx_memcpy(e.pos, h->value.data + prefix + pr->redirect.len,
2373 h->value.len - pr->redirect.len - prefix);
2374
2375 h->value.len = len;
2376 h->value.data = data;
2377 2354
2378 return NGX_OK; 2355 return NGX_OK;
2379 } 2356 }
2357
2358 #endif
2380 2359
2381 2360
2382 static ngx_int_t 2361 static ngx_int_t
2383 ngx_http_proxy_add_variables(ngx_conf_t *cf) 2362 ngx_http_proxy_add_variables(ngx_conf_t *cf)
2384 { 2363 {
2747 pr = ngx_array_push(conf->redirects); 2726 pr = ngx_array_push(conf->redirects);
2748 if (pr == NULL) { 2727 if (pr == NULL) {
2749 return NGX_CONF_ERROR; 2728 return NGX_CONF_ERROR;
2750 } 2729 }
2751 2730
2752 pr->handler = ngx_http_proxy_rewrite_redirect_text; 2731 ngx_memzero(&pr->redirect.complex,
2732 sizeof(ngx_http_complex_value_t));
2733
2734 ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
2735
2736 pr->handler = ngx_http_proxy_rewrite_redirect_complex;
2753 2737
2754 if (conf->vars.uri.len) { 2738 if (conf->vars.uri.len) {
2755 pr->redirect = conf->url; 2739 pr->redirect.complex.value = conf->url;
2756 pr->replacement.text = conf->location; 2740 pr->replacement.value = conf->location;
2757 2741
2758 } else { 2742 } else {
2759 pr->redirect.len = conf->url.len + sizeof("/") - 1; 2743 pr->redirect.complex.value.len = conf->url.len
2760 2744 + sizeof("/") - 1;
2761 p = ngx_pnalloc(cf->pool, pr->redirect.len); 2745
2746 p = ngx_pnalloc(cf->pool, pr->redirect.complex.value.len);
2762 if (p == NULL) { 2747 if (p == NULL) {
2763 return NGX_CONF_ERROR; 2748 return NGX_CONF_ERROR;
2764 } 2749 }
2765 2750
2766 pr->redirect.data = p; 2751 pr->redirect.complex.value.data = p;
2767 2752
2768 p = ngx_cpymem(p, conf->url.data, conf->url.len); 2753 p = ngx_cpymem(p, conf->url.data, conf->url.len);
2769 *p = '/'; 2754 *p = '/';
2770 2755
2771 ngx_str_set(&pr->replacement.text, "/"); 2756 ngx_str_set(&pr->replacement.value, "/");
2772 } 2757 }
2773 } 2758 }
2774 } 2759 }
2775 2760
2776 #if (NGX_HTTP_SSL) 2761 #if (NGX_HTTP_SSL)
3254 static char * 3239 static char *
3255 ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 3240 ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3256 { 3241 {
3257 ngx_http_proxy_loc_conf_t *plcf = conf; 3242 ngx_http_proxy_loc_conf_t *plcf = conf;
3258 3243
3259 u_char *p; 3244 u_char *p;
3260 ngx_str_t *value; 3245 ngx_str_t *value;
3261 ngx_array_t *vars_lengths, *vars_values; 3246 ngx_http_proxy_redirect_t *pr;
3262 ngx_http_script_compile_t sc; 3247 ngx_http_compile_complex_value_t ccv;
3263 ngx_http_proxy_redirect_t *pr;
3264 3248
3265 if (plcf->redirect == 0) { 3249 if (plcf->redirect == 0) {
3266 return NGX_CONF_OK; 3250 return NGX_CONF_OK;
3267 } 3251 }
3268 3252
3316 "\"proxy_redirect default\" must go " 3300 "\"proxy_redirect default\" must go "
3317 "after the \"proxy_pass\" directive"); 3301 "after the \"proxy_pass\" directive");
3318 return NGX_CONF_ERROR; 3302 return NGX_CONF_ERROR;
3319 } 3303 }
3320 3304
3321 pr->handler = ngx_http_proxy_rewrite_redirect_text; 3305 pr->handler = ngx_http_proxy_rewrite_redirect_complex;
3306
3307 ngx_memzero(&pr->redirect.complex, sizeof(ngx_http_complex_value_t));
3308
3309 ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
3322 3310
3323 if (plcf->vars.uri.len) { 3311 if (plcf->vars.uri.len) {
3324 pr->redirect = plcf->url; 3312 pr->redirect.complex.value = plcf->url;
3325 pr->replacement.text = plcf->location; 3313 pr->replacement.value = plcf->location;
3326 3314
3327 } else { 3315 } else {
3328 pr->redirect.len = plcf->url.len + sizeof("/") - 1; 3316 pr->redirect.complex.value.len = plcf->url.len + sizeof("/") - 1;
3329 3317
3330 p = ngx_pnalloc(cf->pool, pr->redirect.len); 3318 p = ngx_pnalloc(cf->pool, pr->redirect.complex.value.len);
3331 if (p == NULL) { 3319 if (p == NULL) {
3332 return NGX_CONF_ERROR; 3320 return NGX_CONF_ERROR;
3333 } 3321 }
3334 3322
3335 pr->redirect.data = p; 3323 pr->redirect.complex.value.data = p;
3336 3324
3337 p = ngx_cpymem(p, plcf->url.data, plcf->url.len); 3325 p = ngx_cpymem(p, plcf->url.data, plcf->url.len);
3338 *p = '/'; 3326 *p = '/';
3339 3327
3340 ngx_str_set(&pr->replacement.text, "/"); 3328 ngx_str_set(&pr->replacement.value, "/");
3341 } 3329 }
3342 3330
3343 return NGX_CONF_OK; 3331 return NGX_CONF_OK;
3344 } 3332 }
3345 3333
3346 if (ngx_http_script_variables_count(&value[2]) == 0) { 3334
3347 pr->handler = ngx_http_proxy_rewrite_redirect_text; 3335 if (value[1].data[0] == '~') {
3348 pr->redirect = value[1]; 3336 #if (NGX_PCRE)
3349 pr->replacement.text = value[2]; 3337 u_char errstr[NGX_MAX_CONF_ERRSTR];
3350 3338 ngx_regex_compile_t rc;
3351 return NGX_CONF_OK; 3339
3352 } 3340 value[1].len--;
3353 3341 value[1].data++;
3354 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); 3342
3355 3343 ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
3356 vars_lengths = NULL; 3344
3357 vars_values = NULL; 3345 if (value[1].data[0] == '*') {
3358 3346 value[1].len--;
3359 sc.cf = cf; 3347 value[1].data++;
3360 sc.source = &value[2]; 3348 rc.options = NGX_REGEX_CASELESS;
3361 sc.lengths = &vars_lengths; 3349 }
3362 sc.values = &vars_values; 3350
3363 sc.complete_lengths = 1; 3351 rc.pattern = value[1];
3364 sc.complete_values = 1; 3352 rc.err.len = NGX_MAX_CONF_ERRSTR;
3365 3353 rc.err.data = errstr;
3366 if (ngx_http_script_compile(&sc) != NGX_OK) { 3354
3355 pr->redirect.regex = ngx_http_regex_compile(cf, &rc);
3356 if (pr->redirect.regex == NULL) {
3357 return NGX_CONF_ERROR;
3358 }
3359
3360 pr->handler = ngx_http_proxy_rewrite_redirect_regex;
3361
3362 #else
3363 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3364 "using regex \"%V\" requires PCRE library",
3365 &value[1]);
3366
3367 return NGX_CONF_ERROR; 3367 return NGX_CONF_ERROR;
3368 } 3368 #endif
3369 3369 } else {
3370 pr->handler = ngx_http_proxy_rewrite_redirect_vars; 3370
3371 pr->redirect = value[1]; 3371 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3372 pr->replacement.vars.lengths = vars_lengths->elts; 3372
3373 pr->replacement.vars.values = vars_values->elts; 3373 ccv.cf = cf;
3374 ccv.value = &value[1];
3375 ccv.complex_value = &pr->redirect.complex;
3376
3377 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3378 return NGX_CONF_ERROR;
3379 }
3380
3381 pr->handler = ngx_http_proxy_rewrite_redirect_complex;
3382 }
3383
3384
3385 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3386
3387 ccv.cf = cf;
3388 ccv.value = &value[2];
3389 ccv.complex_value = &pr->replacement;
3390
3391 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3392 return NGX_CONF_ERROR;
3393 }
3374 3394
3375 return NGX_CONF_OK; 3395 return NGX_CONF_OK;
3376 } 3396 }
3377 3397
3378 3398