Nginx 的 return 与 rewrite 指令是日常运维中使用频率极高的两个工具:前者直接返回状态码(常用于 301 永久跳转),后者通过正则改写 URL 内部路径。本文讲清两者的区别、典型用法和各类框架的伪静态规则写法,配合真实示例,帮你快速掌握。
本文要点
return 301与rewrite的核心区别- 常见跳转场景:www↔根域、HTTP→HTTPS、旧路径→新路径
- WordPress、Discuz、Laravel 等主流程序的伪静态规则
- rewrite 正则的 flag:last、break、redirect、permanent
- 调试重定向的实用技巧
return vs rewrite:先搞清区别
| 指令 | 处理阶段 | 主要用途 | 性能 |
|---|---|---|---|
| return | 早期,无需正则 | 直接返回响应码与 URL | 更快 |
| rewrite | 正则匹配后 | 改写 URI,可内部跳转或外部重定向 | 略慢 |
能用 return 解决的场景,优先用 return;需要根据 URL 内容做复杂变换才用 rewrite。
return 301 常见用法
HTTP 强制跳转到 HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}www 跳转到根域(去 www)
server {
listen 443 ssl;
server_name www.example.com;
# ssl 配置...
return 301 https://example.com$request_uri;
}根域跳转到 www(加 www)
server {
listen 443 ssl;
server_name example.com;
# ssl 配置...
return 301 https://www.example.com$request_uri;
}旧路径跳转到新路径
# 单条旧路径跳转
location = /old-page.html {
return 301 /new-page.html;
}
# 旧目录整体跳转
location ^~ /old-blog/ {
return 301 /blog/;
}注意保留请求参数
使用
$request_uri(含查询参数)而非 $uri(不含查询参数)进行跳转,避免 SEO 或功能依赖参数的页面丢失参数。rewrite 指令详解
基本语法
rewrite 正则 替换字符串 [flag];flag 含义
| flag | 含义 |
|---|---|
| last | 内部重新搜索 location(最常用) |
| break | 停止处理后续 rewrite,在当前 location 继续 |
| redirect | 临时 302 跳转(外部重定向) |
| permanent | 永久 301 跳转(外部重定向) |
rewrite 示例
# 去掉 .html 后缀(访问 /about 自动处理 about.html)
rewrite ^/(.+)\.html$ /$1 permanent;
# 把 /product/123 转写为 /product.php?id=123
rewrite ^/product/(\d+)$ /product.php?id=$1 last;常见框架伪静态规则
WordPress
location / {
try_files $uri $uri/ /index.php?$args;
}Laravel / 其他 PHP MVC 框架
location / {
try_files $uri $uri/ /index.php?$query_string;
}Discuz!
location / {
try_files $uri $uri/ /index.php;
}
location ~* \.php$ {
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}Typecho
location / {
index index.php;
if (-f $request_filename/index.php){
rewrite (.*) $1/index.php break;
}
if (-f $request_filename/index.html){
rewrite (.*) $1/index.html break;
}
if (!-f $request_filename){
rewrite (.*) /index.php last;
}
}优先用 try_files
对于 PHP 框架的伪静态,
try_files 写法比复杂 rewrite 更简洁高效。WordPress、Laravel 等主流框架官方也推荐 try_files 写法。调试重定向
# 查看跳转链(不自动跟随跳转)
curl -I http://example.com
# 跟随所有跳转,显示最终落地页
curl -ILv http://example.com
# 本地快速测试(无需配置 DNS)
curl -H 'Host: example.com' http://127.0.0.1/浏览器有重定向缓存
301 跳转会被浏览器缓存,开发调试时频繁改跳转规则,建议用 curl 而非浏览器测试,避免缓存干扰。Chrome 无痕模式 + 禁用缓存也可以。
小结
- 优先用
return 301,它快且不需要正则 rewrite + last适合内部路径改写;permanent适合外部 301- PHP 框架伪静态优先用
try_files写法 - 调试跳转用
curl -ILv,避免浏览器缓存干扰
常见问题
return 301 和 rewrite permanent 有什么区别?
结果相同,都返回 301 状态码。return 301 更简洁高效,不需要正则匹配;rewrite permanent 需要先匹配正则再重定向,性能略差。优先用 return 301。
为什么改了跳转规则浏览器还是走旧的?
301 跳转被浏览器缓存,需要清空浏览器缓存或用无痕窗口测试。改为 302 临时测试完成后再改回 301 也是常用技巧。
try_files 和 rewrite 哪个适合 PHP 框架?
优先用 try_files,写法简洁且性能更好。大多数主流 PHP 框架(WordPress、Laravel、ThinkPHP)官方文档都推荐 try_files 写法。
rewrite 的 last 和 break 有什么区别?
last 会重新在所有 location 中搜索匹配(可能再次触发其他 location);break 停止当前 rewrite 规则组,在当前 location 内继续处理,不会重新搜索 location。