导读:本期聚焦于阿里山老登创作的《nginx跳转配置怎么设置?nginx 301重定向规则、示例与常见问题详解》,敬请观看详情。一次线上域名切换后,搜索引擎收录的旧链接全部返回404,排查才发现rewrite与return的优先级被忽略。nginx跳转配置看似简单,实际涉及return、rewrite、location匹配和参数保留,稍不注意就会产生多次跳转或丢失查询串。本文将梳理nginx 301重定向的配置方法,对比return 301与rewrite permanent的使用场景,说明正则捕获、域名归一、HTTP到HTTPS跳转、带参数跳转等典型写法。文中提供可直接使用的配置片段,并拆解常见报错与排查思路,比如循环重定向、POST变GET、端口丢失等。最后配套几组练习题帮助验证理解,适合需要快速落地nginx跳转规则的运维与开发人员阅读。本文不涉及具体年份版本差异,以nginx通用语法为准。

nginx跳转配置的核心指令只有两个:return和rewrite。前者适合明确的一对一跳转,后者适合需要正则匹配或条件判断的场景。两者都来自ngx_http_rewrite_module模块,但很多配置文件中出现的错误,并不是语法写错,而是执行顺序理解错。nginx在server层级和location层级都会处理rewrite指令,同一层级中return的执行优先于所有rewrite;一旦return执行,后续的重写规则全部停止。因此,如果在一个location里先写了return,再写若干rewrite,那些rewrite永远不会被执行。这个执行顺序是排查跳转失效问题的第一把钥匙。

nginx跳转配置怎么设置?nginx 301重定向规则、示例与常见问题详解

另外还要理解location的匹配阶段。nginx先根据请求URI匹配location,再执行对应location中的rewrite规则。精确匹配、前缀匹配、正则匹配的优先级不同,如果旧路径对应的location没有命中,跳转规则写在哪一层都不会生效。通常建议:简单路径跳转使用location = /old精确匹配;批量路径跳转使用location ~ ^/old/正则匹配;整站跳转放在server层级,直接return 301即可。

一、return指令的用法与优先级

return指令的基本语法是return code URL;。其中code可以是301、302、303、307、308等HTTP状态码。301表示永久重定向,搜索引擎会把收录权重转移到新地址,适合已经确定不再变化的旧链接。302表示临时跳转,浏览器不会更新收藏,搜索引擎也不会立即替换收录内容。如果只是活动页面临时换地址,不应该用301,而应该用302,避免错误传递永久迁移信号。

在同一个location中,return一旦执行,请求处理立即结束,nginx不会再执行该location内后面的rewrite或其他rewrite模块指令。这意味着配置顺序非常重要。例如下面这个错误示例中,rewrite永远不会生效:

location /demo/ {
    return 301 /new-demo/;
    # 下面的规则不会被执行
    rewrite ^/demo/(.*)$ /new-demo/$1 permanent;
}

正确做法是:如果目标地址是固定的,直接使用return 301;如果目标地址需要从URI中提取动态部分,则不要提前写return,改用rewrite配合permanent参数。或者把return放在if条件块中,仅当条件满足时才提前返回。另一个常见问题是return 301 /new-page;这种写法会丢失原始查询参数。如果需要保留查询参数,应该使用$request_uri或显式拼接$args。很多开发者在整站迁移时只写了路径,结果旧链接中的搜索参数全部丢失,导致落地页统计错乱。

return还支持不带URL的用法,例如return 301;这种写法会返回一个空Location头,实际场景中很少使用。为了让跳转语义更明确,建议始终携带完整目标URL,并且优先使用绝对URL,例如https://www.ipipp.com/new-page,而不是相对路径。使用相对路径虽然允许,但不同版本或反向代理场景下可能产生歧义,不利于排查。

二、rewrite指令与301永久重定向

rewrite指令的语法是rewrite regex replacement [flag];。其中permanent标志等同于301永久重定向,redirect等同于302临时跳转。与return相比,rewrite的优势在于可以使用正则表达式捕获原URI中的动态部分,并把这些部分拼接到新地址中。例如把旧的文章路径/article/123.html迁移到新的查询参数形式/post?id=123,用return很难做到,但用rewrite非常直观:

location ~ ^/article/([0-9]+)\.html$ {
    rewrite ^/article/([0-9]+)\.html$ /post?id=$1 permanent;
}

这里$1表示正则捕获到的一组数字。注意location本身已经写了正则,rewrite内部又写了一遍正则,这是为了同时完成匹配和替换。如果觉得重复,可以改用if加return,但nginx官方不推荐过度使用if,因为if在nginx中的行为并不像编程语言那样直观。对于路径格式固定的迁移,建议尽量用位置匹配加return;只有在确实需要动态捕获时,再使用rewrite。

rewrite与return的另一个差异是执行效率。return直接结束处理并返回响应,rewrite则会重新进入匹配流程,nginx会重新查找新的location。如果一次请求经历多次rewrite,会增加CPU开销,并可能造成循环跳转。因此nginx官方建议优先使用return,特别是在server层级做整站跳转时,直接写:

server {
    listen 80;
    server_name old.ipipp.com;
    return 301 https://www.ipipp.com$request_uri;
}

这个配置简单、清晰、性能最好。$request_uri包含原始URI以及查询参数,不会丢失?q=nginx这类内容。相比$uri,$request_uri不会被解码或规范化,更适合用于跳转原样保留。如果使用rewrite ^ $scheme://www.ipipp.com$request_uri permanent;也能实现类似效果,但写法和维护成本都不如return。

三、典型场景与完整配置示例

场景一:域名合并。很多网站同时持有ipipp.com和www.ipipp.com,搜索引擎会把它们当作两个站点,导致权重分散。通常做法是选择一个作为主域名,另一个301跳转过去。下面示例将www跳转到非www,同时兼容旧域名:

server {
    listen 80;
    server_name www.ipipp.com;
    return 301 http://ipipp.com$request_uri;
}

server {
    listen 80;
    server_name old-site.com www.old-site.com;
    return 301 https://www.ipipp.com$request_uri;
}

场景二:HTTP到HTTPS升级。证书配置完成后,需要在80端口上把流量跳到443端口。下面是一个常用的安全写法,default_server可以接收没有匹配到其他server_name的请求:

server {
    listen 80 default_server;
    server_name _;
    return 301 https://$host$request_uri;
}

这里使用$host而不是直接写死域名,可以适配多域名站点。但要注意,如果用户请求中带有异常Host头,$host可能会被带入跳转地址,造成开放重定向风险。对于安全要求较高的站点,建议明确列出允许的域名。如果架构中存在反向代理,HTTPS在代理层终止,源站的80端口请求可能带有X-Forwarded-Proto头,此时应根据该头判断而不是直接跳转。下面是一种常见写法:

server {
    listen 80;
    server_name ipipp.com;
    if ($http_x_forwarded_proto = "http") {
        return 301 https://$host$request_uri;
    }
}

场景三:路径迁移。旧栏目/legacy/整体迁到/new/,需要把URI中后面的部分原样保留。用rewrite permanent可以完成:

location /legacy/ {
    rewrite ^/legacy/(.*)$ /new/$1 permanent;
}

如果只想迁移某一个固定页面,精确匹配是更好的选择:

location = /old-page {
    return 301 /new-page;
}

需要保留查询参数时,可以在目标地址中追加$request_uri,但不要重复拼接。例如return 301 /new-page$request_uri;会把整个原始URI包括路径也带过去,这通常不是想要的。正确的做法是:目标路径固定时,用$query_string或者$args单独拼接;目标路径由变量决定时,用$request_uri表示原样保留。例如:

location = /old-page {
    return 301 /new-page?$args;
}

上面的配置可以保留原始查询参数,同时路径改成新地址。但要注意,如果原始请求没有查询参数,$args为空,最终URL末尾会多一个?,这是无害的,但如果介意可以结合if判断,不过增加复杂度通常没有必要。

四、常见问题与注意事项

第一个要警惕的是循环重定向。当两个规则互相跳转时,浏览器会提示重定向次数过多。例如用户在ipipp.com和www.ipipp.com之间来回跳,或者HTTP跳HTTPS后又从HTTPS跳回HTTP。排查方法是先查看响应头中的Location,确认目标地址是否符合预期,再检查server_name和location的匹配范围是否互相覆盖。使用curl -I可以只发HEAD请求查看状态码和Location:

curl -I http://ipipp.com/old-page

第二个问题是POST请求经过301后可能变成GET。这是HTTP标准行为,301、302在历史实现中会把POST改为GET。如果接口迁移后必须保留POST方法,应该使用307或308状态码。307是临时跳转并保留方法,308是永久跳转并保留方法。nginx的return和rewrite都支持这些状态码,但需要浏览器和客户端的兼容性。对于大部分网页页面跳转,301没有问题;对于API接口,建议先测试客户端是否支持308。

第三个问题是端口丢失。当nginx监听非标准端口时,使用$host或server_name拼接跳转地址,可能会漏掉原始端口。例如用户在http://ipipp.com:8080访问,跳转后变成https://ipipp.com,如果443端口服务不同,就会出错。需要保留端口时,可以用$http_host替代$host,因为$http_host会带上原始请求中的端口号。但$http_host来自客户端头,可能被伪造,安全场景需要过滤。正式生产环境建议显式写完整域名和端口。

第四个问题是location匹配优先级。nginx的匹配顺序是先精确匹配,再前缀匹配,最后正则匹配。正则匹配按照配置文件中出现顺序执行,一旦匹配到正则location,就不会再执行后续的正则location。因此,如果旧路径的正则规则写在一大堆正则后面,可能永远轮不到它执行。建议把跳转规则尽量放到server层级或精确location中,减少受匹配顺序影响的风险。每修改一次配置后,使用nginx -t检查语法,再平滑加载nginx -s reload,不要直接重启服务,避免短暂中断流量。

第五个问题是测试跳转时只看浏览器地址栏变化,忽略了中间跳转链。一次跳转可能经过多个301,每次都会增加延迟,而且搜索引擎也可能只追踪有限次跳转。可以用curl -I -L查看完整跳转链,确认是否最短路径。对于已经确认的旧地址,应该一次性跳到最终地址,而不是先跳到一个中间地址再跳第二次。

五、配套练习题推荐

第一题:现有域名a.ipipp.com需要永久迁到b.ipipp.com,要求保留完整URI和查询参数,请写出server层级配置。第二题:旧文章路径/news/2020/01/01/abc.html需要跳转到/article/abc,如何用正则捕获abc部分。第三题:配置一个location,当访问/old时301到/new,但/old?page=2需要跳转到/new?page=2,请写出两种实现方式并说明哪种更优。第四题:如果用户在HTTP和HTTPS之间出现循环跳转,应该检查哪些配置项?第五题:说明301与302在搜索引擎收录上的区别,以及为什么接口场景可能需要308。

这些练习题可以手动在测试环境验证。完成后再对照上文示例检查,尤其是是否保留了查询参数、是否避免了正则重复、是否误用了rewrite。nginx跳转配置最终的目标不是让页面打开,而是让搜索引擎、浏览器和接口客户端都用最低成本到达正确地址,同时保持URI语义完整。理解了return与rewrite的执行顺序和适用边界,大部分跳转需求都能用几行配置稳定解决。

nginx跳转配置nginx301重定向重定向规则修改时间:2026-09-22 10:02:46

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