转:Nginx中if条件语句不支持proxy_set_header的解决方案 | CHEGVA
最近开发有个需求,需要通过一个域名加国家地区代码跳转到不同机房的服务。由于中间还要走一层ingress,需要设置下指定域名的头,ingress才能打到指定后端服务。
在if语句中通过proxy_set_header来实现,发现nginx不支持,检测会报错:
nginx: [emerg] "proxy_set_header" directive is not allowed here in /home/anzhihe/app/nginx/conf/vhost/global.chegva.com.conf:12
网上查了下,主要有两种解决方案,通过if加设置变量来解决或者使用map。
The "if" directive is a block directive and creates a separate context (or, rather, two separate contexts - "if in server", "if in location"). When a directive is allowed in a specific context, this is explicitly documented. For example, the set directive:
Context: server, location, if
So the set
directive is allowed inside server
, location
, and if
blocks.
The proxy_set_header
is not allowed inside if
blocks, and there are no plans to change this. If you want to pass headers conditionally, consider using proxy_set_header
with values set conditionally instead, for example:
# default value is empty
set $x_value "";
if ($arg_test) {
set $x_value "present only when test argument set";
}
# the header will be only sent if $x_value is not empty
proxy_set_header X-Header $x_value;
You may also use map
to provide a value. Depending on the particular use case it may also be a better idea to use distinct server
or location
blocks instead.
if statements aren't a good way of setting custom headers because they may cause statements outside the if block to be ignored.
You can use a map directive instead which is not prone to the same problems.
# outside server blocks
map $http_X_Amz_Cf_Id $is_cloudfront {
default "No";
~. "Yes"; # Regular expression to match any value
}
Then:
# inside location block
proxy_set_header X_Custom_Header $is_cloudfront;
最终配置如下:
upstream sgp_chegva_com {
server sgp-pubproxy.chegva.com:443 weight=1 max_fails=2 fail_timeout=10s;
check interval=3000 rise=3 fall=3 timeout=1000 type=tcp default_down=false;
}
upstream ind_chegva_com {
server ind-pubproxy.chegva.com:443 weight=1 max_fails=2 fail_timeout=10s;
check interval=3000 rise=3 fall=3 timeout=1000 type=tcp default_down=false;
}
server {
listen 80;
server_name global.chegva.com;
access_log /home/anzhihe/logs/nginx/global.chegva.com.log mainproxy;
error_log /home/anzhihe/logs/nginx/global.chegva.com.err;
error_page 403 404 500 502 503 504 https://chegva.com/error.html;
set $is_matched 0;
if ($request_uri ~* ^/([^/]*)/?(.*)) {
set $local $1;
}
location / {
if ($local = "es|it|us|uk|de|fr|jp") {
set $domain_name "sgp.chegva.com";
set $proxy_backend "sgp_chegva_com";
set $is_matched 1;
}
if ($is_matched = 0) {
set $domain_name "global.chegva.com";
set $proxy_backend "ind_chegva_com";
}
proxy_set_header Host $domain_name;
proxy_pass http://$proxy_backend;
}
}
参考: