NGINX如何根据请求方法将同路径请求转发至不同后端服务器
Nginx同路径按请求方法转发配置实现方案
原有配置错误点
- Nginx没有内置的
request变量,请求方法需要通过系统内置的$request_method变量获取 - Nginx的
if指令语法要求条件必须包裹在括号中,变量引用需要加$前缀 - 直接在location的if块内编写
proxy_pass在部分Nginx版本会存在兼容性问题,更推荐使用预定义变量映射的方式实现
推荐实现方案
方案1:map映射(最优,适合全局多location复用)
需要在Nginx的http配置块中预先定义映射规则,逻辑清晰且性能更高:
http { # 映射请求方法对应的后端服务地址 map $request_method $product_backend { GET http://get-app-server:8080/products; POST http://post-app-server:8080/products; # 其他请求方法默认返回空 default ""; } # 映射请求方法对应的Host请求头 map $request_method $product_host { GET "get-app-server"; POST "post-app-server"; default ""; } server { listen 80; server_name localhost; location /get-product { # 非GET/POST请求直接返回405方法不允许 if ($product_backend = "") { return 405; } proxy_pass $product_backend; proxy_set_header Host $product_host; # 可自行补充其他proxy通用配置,比如获取真实IP等 } } }
方案2:单location内变量赋值(无需修改http块)
如果仅单location需要该规则,可以直接在server块内配置:
server { listen 80; server_name localhost; location /get-product { set $backend ""; set $backend_host ""; if ($request_method = GET) { set $backend http://get-app-server:8080/products; set $backend_host "get-app-server"; } if ($request_method = POST) { set $backend http://post-app-server:8080/products; set $backend_host "post-app-server"; } # 拦截不允许的请求方法 if ($backend = "") { return 405; } proxy_pass $backend; proxy_set_header Host $backend_host; } }
注意事项
- 两种方案都采用先给变量赋值再传递给
proxy_pass的方式,规避了if块内直接写proxy_pass的兼容性问题 - 如果需要保留原请求的URI后缀到后端,需要去掉
proxy_pass后面的/products路径,仅保留上游服务的地址和端口即可 - 其他请求方法的处理逻辑可根据业务需求自行调整,比如转发到通用后端,或者返回自定义错误码
内容的提问来源于stack exchange,提问作者Naved Akhtar
相关产品推荐
相关产品推荐

