如何避免Nginx中基于Cookie和Header的Map配置重复?
如何避免重复编写Nginx的map配置?
我现在有两套逻辑完全一致的Nginx map配置:一套基于Cookie值,另一套基于请求头,如下所示:
基于Cookie的map配置
map $cookie_version $version_host { default 172.17.0.1:8001; 2.65.1 172.17.0.1:8001; 2.65.2 172.17.0.1:8003; }
基于请求头的map配置
map $http_app_version $version_api_host { default 172.17.0.1:8001; 2.65.1 172.17.0.1:8001; 2.65.2 172.17.0.1:8003; }
我的server块配置如下:
server { listen 443 ssl; ssl_certificate /etc/ssl/nexello.crt; ssl_certificate_key /etc/ssl/nexello.key; server_name _; proxy_set_header Host $host; proxy_set_header X-FORWARDED-FOR $remote_addr; charset utf-8; location / { # Web端访问 # 用Cookie而非请求头是因为请求到达这里时,JavaScript还没来得及设置请求头 if ($cookie_token) { proxy_pass https://$version_host; } # API端访问 # 这里用请求头是因为调用API的客户端可以完全控制请求头 if ($http_authorization) { proxy_pass https://$version_api_host; } # 未授权跳转 # 如果既没有请求头也没有Cookie,说明没有访问令牌,跳转到认证服务 proxy_pass https://172.17.0.1:7001; } }
请问有没有办法避免重复编写这两套逻辑相同的map配置?
解决方案1:统一版本变量,复用单个map
先把Cookie和请求头的版本值合并成一个统一变量,再基于这个变量编写一套map即可:
- 定义统一版本变量
可以用map或set指令实现,这里推荐map的方式(避免if指令的潜在问题):
# 优先取请求头的版本,没有则取Cookie的版本,都没有则为空 map "" $unified_version { default ""; $http_app_version $http_app_version; $cookie_version $cookie_version; }
- 编写单套map配置
基于统一变量定义映射规则:
map $unified_version $target_host { default 172.17.0.1:8001; 2.65.1 172.17.0.1:8001; 2.65.2 172.17.0.1:8003; }
- 修改server块逻辑
直接在不同场景下使用统一的$target_host:
server { listen 443 ssl; ssl_certificate /etc/ssl/nexello.crt; ssl_certificate_key /etc/ssl/nexello.key; server_name _; proxy_set_header Host $host; proxy_set_header X-FORWARDED-FOR $remote_addr; charset utf-8; location / { if ($cookie_token) { proxy_pass https://$target_host; } if ($http_authorization) { proxy_pass https://$target_host; } proxy_pass https://172.17.0.1:7001; } }
解决方案2:用include引入外部规则片段
如果需要保留两个独立的map变量,但不想重复写映射规则,可以把规则单独抽成外部文件:
- 创建规则文件
新建/etc/nginx/conf.d/version-rules.conf,内容为:
default 172.17.0.1:8001; 2.65.1 172.17.0.1:8001; 2.65.2 172.17.0.1:8003;
- 在map中引入规则
修改原有的两个map配置,通过include引入外部规则:
map $cookie_version $version_host { include /etc/nginx/conf.d/version-rules.conf; } map $http_app_version $version_api_host { include /etc/nginx/conf.d/version-rules.conf; }
这种方式无需修改server块的原有逻辑,只需要维护外部规则文件即可。
内容的提问来源于stack exchange,提问作者Mathias Hillmann
相关产品推荐
相关产品推荐

