Nginx实现子域名重写到带partner参数URL的配置方法
现有配置的核心问题
- 端口监听不匹配需求:配置仅监听80(HTTP)端口,未配置443端口SSL相关规则,无法处理HTTPS请求。
- 重写逻辑篡改了所有请求路径:
rewrite ^ /?partner=$subdomain break;规则会将任意请求的URI强制替换为根路径/,包括CSS、JS、图片等静态资源请求,直接导致静态资源无法被正常寻址加载。 - 指令执行优先级冲突:Nginx中rewrite模块指令执行优先级高于同location块内的
try_files,原配置的rewrite规则会先执行修改URI,导致try_files的静态文件查找逻辑完全失效,哪怕请求的是服务器上真实存在的文件,也会被强制转到根路径。 - 子域名匹配范围无约束:当前正则
~^(?<subdomain>.+?)\.domain\.com$会匹配所有多级子域名(例如a.b.domain.com会将a.b捕获为subdomain值),也没有为www.domain.com这类不需要走partner逻辑的子域名做单独规则,容易出现非预期匹配。
正确配置方案
核心需求是不改变用户访问的地址栏路径,内部给请求追加partner=子域名的参数,同时保证静态资源、前端路由正常工作,不需要通过rewrite修改URI,直接追加查询参数即可,参考配置如下(适配SPA单页应用场景):
# 优先匹配不需要走partner逻辑的子域名,例如www,规则优先级高于正则匹配 server { listen 80; listen 443 ssl http2; # 不需要HTTPS可删除本行及下面两行ssl配置 server_name www.domain.com; # 替换为你自己的SSL证书路径 ssl_certificate /path/to/your/fullchain.pem; ssl_certificate_key /path/to/your/privkey.pem; root /var/www/domain.com; index index.html; location / { try_files $uri $uri/ /index.html; } } server { listen 80; listen 443 ssl http2; # 不需要HTTPS可删除本行及下面两行ssl配置 # 替换为你自己的SSL证书路径 ssl_certificate /path/to/your/fullchain.pem; ssl_certificate_key /path/to/your/privkey.pem; # 仅匹配xxx.domain.com格式的三级子域名,若需要支持多级子域名可换回原正则 server_name ~^(?<subdomain>[^.]+)\.domain\.com$; root /var/www/domain.com; index index.html; location / { # 核心修正:不修改原有请求URI,仅追加partner参数,同时保留请求自带的其他参数 set $args "partner=$subdomain&$args"; # 保留原静态资源查找逻辑,静态文件直接返回,不存在的路径回退到index.html,参数会自动传递给前端/后端 try_files $uri $uri/ /index.html; } }
注:若需要允许用户手动传入的
partner参数覆盖子域名自动生成的值,将set $args "partner=$subdomain&$args";改为set $args "$args&partner=$subdomain";即可。
生效操作说明
- 配置修改完成后,先执行
nginx -t检查配置语法是否有误,避免配置错误导致Nginx服务中断。 - 语法校验通过后,执行
nginx -s reload重载配置即可生效。 - 如果你需要让HTTP请求自动跳转HTTPS,可以额外增加一个80端口的server块,配置301跳转规则即可。
- 如果你希望用户浏览器地址栏显式展示
?partner=xxx的参数形式,可将内部参数设置改为外部重定向规则,注意此时会改变地址栏显示。
内容的提问来源于stack exchange,提问作者ionic75
相关产品推荐
相关产品推荐

