最近开发有个需求,需要通过一个域名加国家地区代码跳转到不同机房的服务。由于中间还要走一层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; } }
参考: