Nginx rewrite指令仅作用于URI路径部分,无法修改协议、端口、host或query string;强制HTTP→HTTPS跳转应优先使用return 301 https://$host$request_uri,简洁高效且安全。

直接用 rewrite 指令无法修改协议(如 HTTP → HTTPS)或端口号(如 :8080 → :443),因为 rewrite 只作用于 URI 路径部分,不处理 scheme(协议)、host(域名)、port(端口)或 query string(查询参数)。要实现协议与端口的变更,必须结合其他指令或配置方式。
强制跳转 HTTPS(改协议)
最常用、最推荐的方式是使用 return,而不是 rewrite ... permanent:
-
return 301 https://$host$request_uri;—— 简洁高效,无正则开销,保留完整路径和参数 - 放在监听 80 的
server块中,确保所有 HTTP 请求都被重定向 - 注意:
$host不带端口;若需显式指定 HTTPS 端口(如https://example.com:8443),可写死:https://example.com:8443$request_uri
修改目标端口(通常用于反向代理场景)
端口号本身不出现在客户端请求的 URI 中,所以“修改端口”实际是指:把请求转发到后端服务的不同端口。这靠 proxy_pass 实现,不是 rewrite:
-
location /api/ { proxy_pass http://127.0.0.1:8080/; }→ 转发到本地 8080 端口 -
location /admin/ { proxy_pass https://backend:8443/; }→ 转发到后端 8443 端口(HTTPS) - 关键点:
proxy_pass后的 URL 决定了目标协议和端口;末尾的/影响路径是否被替换
根据条件动态切换协议或后端地址
可用 if + set 配合 proxy_pass 变量(需注意 if 在 location 外慎用):
- 例如:对特定 User-Agent 强制走 HTTPS 后端
set $backend "http://127.0.0.1:8080";if ($http_user_agent ~* "mobile") { set $backend "https://127.0.0.1:8443"; }-
proxy_pass $backend;—— 注意:变量形式的proxy_pass不能与rewrite混用在同一个 location 中做路径改写,否则行为不可控
不推荐的做法:用 rewrite 拼接完整 URL
虽然语法上允许 rewrite ^(.*)$ https://example.com:8443$1 permanent;,但存在明显问题:
- 它只适用于简单跳转,且硬编码 host 和 port,缺乏灵活性
- 若用户访问的是
http://example.com:8080/path,该规则不会自动识别原端口,容易出错 - 正则匹配和重写带来额外开销,
return更轻量、更安全 - Nginx 官方文档明确建议:能用
return就不用rewrite ... redirect











