一、rewritereturn 的核心区别是什么

原笔记在同一章里先讲了 return,再讲 rewrite,其实已经暗示了两者的分工:

  • return 更适合简单直接地返回状态码或固定新地址
  • rewrite 更适合基于 URI 做匹配和改写

也就是说,rewrite 的重点不是“立刻返回”,而是:

  • 先匹配 URI
  • 再根据正则结果重写 URL

这也是它更灵活、同时也更容易写复杂的原因。

二、rewrite 主要匹配什么内容

原笔记特别提醒了一点:

  • rewrite 匹配的是 URI
  • 不是完整的 URL

这意味着在写规则时,关注的是:

  • 域名后面的路径部分

而不是整条完整网址。

这和前面 location 匹配 URI 的思路是相通的。

三、rewrite 指令的基本格式

原笔记把格式概括为:

rewrite 找什么 替换成什么 [标记];

可以进一步理解成:

  • 左边:匹配规则,支持具体内容、正则、捕获分组
  • 右边:替换后的内容,可以用后向引用
  • 最后:可选标记,决定改写后的处理方式

原笔记还提到,这个思路和 sed 's###g' 非常像,本质上都是“匹配再替换”。

四、案例:把整个站点跳转到另一个域名

原笔记的示例配置如下:

server {
  listen 80;
  server_name rewrite.oldboylinux.cn;
  rewrite ^(.*)$ http://www.baidu.com$1;
}

这条规则的含义是:

  • 把用户请求的 URI 全部捕获到 $1
  • 再拼接到新域名后面

例如访问:

/aaa

就会跳成:

http://www.baidu.com/aaa

这类写法很适合:

  • 旧域名整体迁移到新域名
  • 原路径还需要尽量保留下来

五、为什么默认会得到 302

原笔记在第一次测试时发现:

  • 没写额外标记时
  • 返回的是 302 Found

这是因为 rewrite 默认使用的是:

redirect

也就是临时跳转。

原笔记的测试结果正好验证了这一点:

  • 访问旧地址
  • 返回 302

这说明没有显式指定时,Nginx 会把它当成临时改写跳转处理。

六、如何改成 301 永久跳转

原笔记随后把配置改成:

server {
  listen 80;
  server_name rewrite.oldboylinux.cn;
  rewrite ^(.*)$ http://www.baidu.com$1 permanent;
}

此时再次测试,就会返回:

  • 301 Moved Permanently

这也是原笔记想强调的核心区别:

  • redirect 对应 302
  • permanent 对应 301

在真实业务里,一般可以这样理解:

  • 新旧地址都还可能同时使用,用 302
  • 旧地址要彻底废弃、权重和收录转移到新地址,用 301

七、breaklast 又是什么

原笔记最后补充了另外两个非常常见的标记:

7.1 break

原笔记的解释是:

  • 一旦匹配到包含 break 的规则
  • 即使后面还有其他 location 规则
  • 也不再继续执行后续改写逻辑

可以把它理解为:

  • 当前这次改写在这里停止
  • 不再继续往后跑

7.2 last

原笔记对 last 的描述更偏向“重新开始一轮匹配”:

  • 命中带 lastrewrite
  • 当前改写阶段停止
  • Nginx 会重新发起一次内部请求
  • 再次和 location 规则进行匹配

因此,last 更像是:

  • 改写完成后,再拿新 URI 去重新走一轮匹配流程

这也是它和 break 最大的区别。

八、原笔记总结的常见标记含义

可以把原笔记中的几个标记整理成下面这张表:

标记 含义
redirect 302,临时跳转
permanent 301,永久跳转
break 终止继续执行后续改写流程
last 重新发起内部请求,再走一轮匹配

这几个标记决定的不是“匹配不匹配”,而是“匹配成功后接下来怎么处理”。

九、小结

rewrite 的核心价值在于:
它可以让你基于 URI 和正则表达式,对访问路径做更灵活的改写。

原笔记这一节最值得先记住的几件事是:

  • rewrite 匹配的是 URI
  • 默认标记是 redirect,也就是 302
  • permanent 用于 301
  • breaklast 决定改写后是否继续执行或重新匹配

当简单跳转用 return 不够时,rewrite 往往就是更合适的下一步。