nginx 可通过 $http_变量读取请求头实现动态路由,推荐用 set 定义后端变量再 proxy_pass 引用;if + rewrite 适用于重定向,但不可在 if 中直接 proxy_pass;需注意 header 转变量的命名规范(小写、下划线)及调试验证方法。

当 Nginx 需要根据客户端携带的特定 HTTP Header(如 X-Env、My-Version 或 Authorization)决定将请求转发到不同后端时,不能依赖 proxy_pass 的静态配置,而应结合变量与条件判断实现动态路由。关键在于:Header 可被 Nginx 直接读取为变量,但重定向(rewrite)或代理目标(proxy_pass)必须在运行时解析,且需规避 if 在 location 中的限制风险。
Header 映射规则与变量命名规范
Nginx 会自动将 HTTP 请求头转换为小写、用下划线连接的变量名,例如:
-
X-Forwarded-For→$http_x_forwarded_for -
My-Custom-Id→$http_my_custom_id -
Accept-Language→$http_accept_language
注意:Header 名中所有连字符(-)均转为下划线(_),且全部小写;变量前缀固定为 $http_,不可省略。
使用 if + rewrite 实现 Header 触发的重定向
适用于简单跳转场景(如灰度发布引导页、环境切换入口)。需确保 rewrite 在 location 块内,且配合 last 或 redirect 标志:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 匹配指定值并跳转:
if ($http_x_env = "staging") { rewrite ^(.*)$ https://staging.example.com$1 redirect; } - 正则匹配多值:
if ($http_user_agent ~* "(curl|wget)") { rewrite ^(.*)$ /api/health break; } - 组合判断(支持 && 和 ||):
if ($http_x_version = "v2" && $http_x_debug != "0") { rewrite ^(.*)$ /debug/v2$1 last; }
⚠️ 注意:if 在 location 内可用,但在 server 级直接使用可能引发未定义行为;避免在 if 中嵌套 proxy_pass,Nginx 不允许。
基于 Header 动态 proxy_pass(推荐方案)
更健壮的方式是把后端地址设为变量,再由 proxy_pass 引用。这样既避免 if 的局限性,又支持复杂路由逻辑:
- 定义上游变量:
set $backend "http://default-backend:8000";<br>if ($http_x_env = "prod") { set $backend "http://prod-api:9000"; }<br>if ($http_x_env = "dev") { set $backend "http://dev-api:9001"; } - 在 location 中引用:
location /api/ { proxy_pass $backend; proxy_set_header Host $host; } - 支持路径拼接(如带子路径):
set $backend "http://legacy-app";<br>if ($http_x_legacy = "1") { set $backend "http://legacy-app:8080/old"; }<br>proxy_pass $backend;(此时proxy_pass结尾无斜杠,Nginx 会保留原始 URI 路径)
验证与调试要点
Header 路由易因大小写、空格或缺失而失效,建议按以下步骤确认:
- 用
curl -H "X-Env: staging" https://your-domain.com/test测试请求是否携带正确 Header - 开启 Nginx debug 日志:
error_log /var/log/nginx/debug.log debug;,查看变量赋值和匹配过程 - 检查响应头是否含
X-Upstream等自定义标识,便于后端或监控识别路由路径 - 若 Header 来自前端 JS 设置,注意浏览器同源策略可能导致 Header 被过滤(需服务端显式声明
Access-Control-Allow-Headers)










