直接在80端口server块中用rewrite ^ https://$host$request_uri permanent可实现http强制跳转https,匹配任意请求并保留完整路径与参数;多域名适配用$host,例外路径可用if+break跳过;但return 301更高效、官方推荐。

直接在监听 80 端口的 server 块里加一条 rewrite 指令就能实现 HTTP 强制跳转 HTTPS。
核心写法是:
server {
listen 80;
server_name example.com www.example.com;
rewrite ^ https://$host$request_uri permanent;
}
这条规则的意思是:匹配任意请求(^),跳转到 https:// + 当前请求头里的域名($host)+ 完整原始路径和参数($request_uri),并返回 301 状态码(permanent)。
为什么用 $request_uri 而不是 $uri 或 $1
-
$request_uri包含路径和问号后的全部查询参数,比如/login?next=/admin&ref=test,不会丢参; -
$uri只有路径部分,不带?及之后内容; - 如果用
rewrite ^(.*)$ ... $1,虽然也能捕获路径,但$1同样不含查询参数,必须额外拼上$is_args$args才完整,容易遗漏。
多域名场景下推荐用 $host
-
$host来自请求头的Host字段,自动适配用户实际访问的域名(如api.example.com、www.example.com); - 避免硬编码或只写
$server_name导致子域名跳转错误(例如api.example.com被跳到https://example.com)。
如需跳过某些路径(如健康检查)
可在 rewrite 前加判断:
if ($request_uri ~ ^/(health|debug|ping)) {
break;
}
rewrite ^ https://$host$request_uri permanent;
注意:if 在 server 上下文中仅支持简单匹配,不能嵌套 return 或 rewrite;break 表示终止后续重写流程,请求继续走正常处理链。
和 return 301 的区别
-
rewrite ... permanent会触发 Nginx 的重写引擎,走正则匹配流程,稍有性能开销; -
return 301 https://$host$request_uri;更轻量、语义更明确,Nginx 官方更推荐用于纯跳转场景; - 两者效果一致,都是发 301 响应,但
return是首选,rewrite更适合已有复杂重写逻辑需复用的场景。
不复杂但容易忽略











