Nginx rewrite重写规则怎么写?常用实例与避坑指南

来源:站长源码作者:狼行天下头衔:草根站长
导读:本期聚焦于狼行天下创作的《Nginx rewrite重写规则怎么写?常用实例与避坑指南》,敬请观看详情。Nginx rewrite是做URL重定向和伪静态时绕不开的功能,但正则表达式写错、flag用错导致死循环的问题屡见不鲜。本文从rewrite指令的执行顺序讲起,详细解析last、break、redirect、permanent四种flag的区别,并结合实际案例演示301跳转、域名迁移、去尾部斜杠、伪静态等常见写法,最后总结生产环境中容易踩的坑,帮助你写出正确高效的重写规则。

Nginx rewrite模块是实现URL重写和跳转的核心功能,无论是域名迁移、HTTP强制跳转HTTPS,还是给动态页面做伪静态,都离不开它。不过rewrite的语法看似简单,背后却涉及location匹配顺序、flag标志位、正则捕获组等一系列细节,稍有疏忽就会出现死循环、跳转失效或者性能下降的问题。本文结合具体实例,把rewrite的用法和常见坑讲清楚。

Nginx rewrite重写规则怎么写?常用实例与避坑指南

一、rewrite指令的基本语法与执行顺序

rewrite的完整语法是rewrite regex replacement [flag];,其中regex是要匹配的URI正则表达式,replacement是替换后的目标地址,flag是可选的标志位。这条指令只能写在server、location或者if块中,作用对象是请求的URI部分,不包含主机名和查询参数。

一个典型的例子:

server {
    listen 80;
    server_name ippipp.com;
    # 把 /old-page.html 重写为 /new-page.html
    rewrite ^/old-page\.html$ /new-page.html last;
    # 把所有 /article/数字 的请求重写为动态脚本
    rewrite ^/article/(\d+)$ /article.php?id=$1 last;
}

这里要注意几个细节。正则中的^$分别锚定URI的开头和结尾,点号.必须转义成\.才能匹配字面意义上的点,否则会匹配任意字符。$1表示正则中第一个圆括号捕获的内容,如果有多个括号,依次用$1$2引用。如果replacement中包含新的查询参数,原有的查询串默认会自动拼接在后面,若想丢弃原参数,可以在目标地址末尾加一个?

执行顺序也是必须理解的一点。Nginx收到请求后,先在server块内按顺序执行rewrite指令,然后确定命中的location,再在该location内执行rewrite。如果重写后的URI发生了变化,Nginx会重新去匹配location,这就是很多死循环问题的根源。

二、四种flag的区别与实例演示

flag决定了重写之后Nginx的后续行为,一共有四种:lastbreakredirectpermanent,用错它们是初学者最常见的问题。

  • last:停止当前rewrite指令集的执行,用重写后的URI重新搜索location,适合内部重写。
  • break:停止rewrite指令的执行,但不再重新匹配location,直接在当前location内处理请求,常用于静态资源目录。
  • redirect:返回302临时重定向,浏览器地址栏会变化,适合临时调整。
  • permanent:返回301永久重定向,搜索引擎会把权重转移到新地址,适合域名迁移。

看一下last和break的实际差异:

location /download/ {
    # break后不再重新匹配location,直接按当前上下文处理
    rewrite ^/download/(.*)$ /data/files/$1 break;
    # 下方location内的fastcgi等配置仍然生效
}

location /api/ {
    # last会重新匹配location,重写后的URI会命中其他location
    rewrite ^/api/v1/(.*)$ /api/index.php?route=$1 last;
}

如果把/download/的break换成last,重写后的/data/files/xxx会重新去匹配location,可能命中别的处理逻辑,导致文件找不到。而/api/的场景恰恰需要重新匹配,让新的URI走PHP处理。判断标准很简单:重写后需要交给其他location处理就用last,重写后就在当前location内消化就用break。

301永久重定向的典型场景是老域名迁移:

server {
    listen 80;
    server_name old-domain.com;
    # 整站迁移到新域名,保留原有路径
    rewrite ^/(.*)$ http://new-domain.com/$1 permanent;
}

三、常见实战案例

1. HTTP强制跳转HTTPS

这是线上最常见的需求,推荐用return而不是rewrite,效率更高:

server {
    listen 80;
    server_name ippipp.com;
    return 301 https://$host$request_uri;
}

2. 去掉URL末尾的斜杠

统一/dir//dir两种形式有利于SEO:

# 把 /foo/ 重写为 /foo
if ($request_uri ~ ^/(.*)/$) {
    return 301 /$1;
}

3. 多级目录伪静态

/goods/12/34.html映射为/goods.php?cate=12&id=34

location / {
    rewrite ^/goods/(\d+)/(\d+)\.html$ /goods.php?cate=$1&id=$2 last;
}

4. 根据User Agent做跳转

移动端访问跳转到wap站点:

if ($http_user_agent ~* "(iphone|android)") {
    rewrite ^/$ https://m.ipipp.com/ redirect;
}

四、生产环境避坑要点

第一,警惕死循环。比如写了rewrite ^/(.*)$ /index.php/$1 last;,而/index.php所在的location又包含这条rewrite规则,URI会无限重写。Nginx虽然内置了十次循环上限并返回500错误,但这说明配置本身有逻辑问题。解决办法是合理划分location,或者改用break。

第二,能用return就不要用rewrite。对于固定的跳转,return 301 https://$host$request_uri;比rewrite更简洁高效,return直接结束处理,省去了正则匹配的开销。rewrite应该留给确实需要正则捕获的场景。

第三,注意if的陷阱。rewrite模块的if指令功能有限,只适合做字符串和正则比较,不要在if里写嵌套逻辑或者尝试set以外的内容操作。官方文档也明确说过if is evil,能用map和location替代就尽量替代。

第四,修改配置后一定要用nginx -t检查语法,再用nginx -s reload平滑加载。同时建议在测试环境用curl的-I参数验证返回码和Location头是否符合预期,确认无误后再推到线上,避免301这种影响面大的变更出问题。

掌握这些原则后,rewrite基本能覆盖日常绝大多数URL处理需求。核心还是理解location匹配机制与flag的行为差异,写规则前先画出请求流转路径,很多问题就能提前规避。

Nginx rewrite重写规则Nginx配置修改时间:2026-09-08 19:18:54

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260908/52934.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。