Nginx 解耦复杂请求的核心是将跨域、路由、鉴权等通用能力前置剥离,通过 upstreams/、snippets/、conf.d/ 分层配置,用 include 精准加载并动态控制 Origin。

配置 Nginx 实现对复杂请求业务处理的解耦,核心不是让 Nginx 去“处理业务”,而是通过结构化、职责分离的配置方式,把跨域、路由、鉴权前置、协议适配等与业务逻辑无关的通用能力从后端代码中剥离出来,由 Nginx 统一承接。这样前端调用无感,后端专注接口实现,运维可独立灰度和治理。
按功能切分配置,避免混杂在 server 块里
把不同职责的配置提取为独立文件,放在规范目录下:
-
upstreams/:只放 upstream 定义,例如
api-backend.conf中定义多个后端集群(如 v1、v2、canary),不写任何 location 或 proxy_pass 逻辑 -
snippets/:存放可复用的通用片段,比如
cors-preflight.conf(专用于拦截并响应 OPTIONS)、auth-header-proxy.conf(统一透传 Authorization 和 Cookie) -
conf.d/:每个业务域一个文件,如
user-api.conf,仅包含 server 块 + include 引用,不写重复头或硬编码地址
用 include 精准加载,确保上下文合法
include 不是简单拼接文本,必须落在正确指令层级:
- 在 http 块开头
include upstreams/*.conf;,保证 upstream 可被后续所有 server 引用 - 在 server 块内
include snippets/cors-preflight.conf;,该文件内容必须是合法的 location 或 if 指令块 - 禁止在 location 块里 include 一个含 upstream 的文件——Nginx 启动会直接报错
针对复杂请求,单独封装预检处理逻辑
浏览器对 PUT/DELETE、application/json、带自定义 header 的请求会先发 OPTIONS。这部分逻辑应完全解耦,不和业务 location 耦合:
- 新建
snippets/cors-preflight.conf,内容仅含:
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin "$http_origin" always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE" always;
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization" always;
add_header Access-Control-Max-Age 86400 always;
add_header Content-Length 0 always;
add_header Content-Type 'text/plain; charset=utf-8' always;
return 204;
}
- 在各业务 server 的 location /api/ 块顶部 include 它,确保预检总被拦截,真实请求再走 proxy_pass
动态 Origin 控制,避免硬编码污染配置
不写死 Access-Control-Allow-Origin https://a.com,改用变量匹配白名单:
- 在 http 块定义 map:
map $http_origin $cors_origin {
~^https?://(localhost|dev\.example\.com|app\.example\.com)(:[0-9]+)?$ $http_origin;
default "";
}
- 在 cors 片段中使用
add_header Access-Control-Allow-Origin $cors_origin always; - 这样开发、测试、生产共用同一份配置,仅靠域名白名单区分环境


















