应直接使用return 301而非rewrite,因前者性能更高、语义更明确、避免正则开销与循环跳转;需在独立server块中配置,显式指定server_name并禁用$host防开放重定向,http与https必须分端口部署。

直接用 return 301,别写 rewrite
phpEnv 默认用 Nginx,而它的常见误区是套用 Apache 思路,比如在配置里堆 rewrite ^/old(.*)$ /new$1 permanent。这不仅多一层正则匹配开销,还容易因 location 块嵌套顺序出错,导致重定向不生效或循环跳转。
正确做法是在独立的 server 块里用 return 301 直接响应:
- 性能高:绕过 rewrite 引擎,Nginx 在 server 级就返回,无路径匹配耗时
- 语义明确:
return 301 https://example.com$request_uri;表示“所有请求都永久跳过去” - 避免歧义:不用考虑
location = /、location /的优先级问题
server_name 和 $host 别混用
很多人写成 return 301 https://$host$request_uri;,看似通用,但风险很大——如果请求头里带恶意 Host(比如伪造的 Host: evil.com),Nginx 会照单跳转过去,造成开放重定向漏洞。
安全写法是显式列出合法域名:
- 只重定向已知域名:
server_name www.example.com;+return 301 https://example.com$request_uri; - 若需同时处理多个旧域名,用空格分隔:
server_name old1.com old2.com www.old1.com; - 绝对不要依赖
$host构造跳转目标,除非你额外加了if ($host ~ ^(example\.com|www\.example\.com)$) { ... }白名单判断
HTTP → HTTPS 必须拆成两个 server 块
phpEnv 的 Nginx 配置通常把 HTTP 和 HTTPS 写在一个 server 里,用 if ($scheme = http) 判断跳转。这是错的 —— Nginx 官方明确不推荐在 server 块中用 if 做协议判断,它可能被 location 继承覆盖,或在 SSL 握手前就失效。
标准解法是严格分离:
- 第一个
server块监听80,只做跳转:listen 80; server_name example.com www.example.com; return 301 https://example.com$request_uri; - 第二个
server块监听443 ssl,专注 HTTPS 服务,里面不再出现任何return 301或if跳转逻辑 - 确保两个块的
server_name完全一致,否则部分域名可能漏掉跳转
改完配置后必须 reload,不能只 restart
phpEnv 的 Nginx 进程常驻,改完配置文件后执行 nginx -t 验证语法没错,下一步必须是 nginx -s reload。用 service nginx restart 或直接 kill 进程再启,会导致 php-fpm 连接中断、正在处理的请求丢弃,用户看到 502。
验证是否生效最简单的方法是命令行测:
-
curl -I http://www.example.com看响应头是否有HTTP/1.1 301 Moved Permanently和正确的Location -
curl -I http://example.com/test?x=1确认$request_uri是否完整保留路径和参数 - 浏览器访问时按 Ctrl+Shift+I 打开 Network 面板,过滤
Redirect类型,看状态码和跳转链是否干净(不应出现 302 或多次跳转)
最易忽略的是 $request_uri 末尾斜杠和编码问题:比如原始 URL 是 /a%20b/,重定向后必须仍是 /a%20b/,而不是被自动解码成 /a b/ —— 只要没在 return 里手动拼接路径,Nginx 默认原样透传,这点比 Apache 的 RewriteRule 更可靠。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











