当前位置:智汇导航 » 站长资讯 » 资讯文章 » 站长新闻 » 文章详细 订阅RssFeed

我踩过的坑:一个Nginx rewrite把我整失眠了

来源:本站原创 浏览:1325次 时间:2026-05-14

去年刚玩Nginx,想在子目录 /blog 下放个WordPress,又想让文章URL不带 /blog,看起来专业点。我翻遍了中文教程,全是抄官方的破例子,结果被 rewrite 折磨了三个通宵。

第一个坑:循环重定向。我最先写了这条:

rewrite ^/blog/(.*) /$1 last;

结果一访问 /blog/post1,它就rewrite成 /post1,然后Nginx检测到URI变了,又重新匹配location,发现没有匹配的location,又走回原来的location,继续rewrite……浏览器瞬间弹出‘重定向过多’。我在日志里看到连续几十次302,才反应过来——rewrite后的URI会重新进入location匹配,如果没处理好就死循环

第二个坑:正则回溯导致性能雪崩。我试了下禁用循环:

rewrite ^/blog/(.*) /$1 break;

break不再重新匹配location,但WordPress收到 /post1 后,因为根目录下没有WP的配置文件(应该在 /blog 下),直接返回404。接着我想用 try_files 做fallback,又掉进另一个坑——try_files与rewrite的执行顺序是反直觉的。文档说 try_filesrewrite 之前执行,但实际上,如果 try_files 找到了文件,rewrite 根本不会运行。折腾半天,最后实测顺序是:先rewrite,再try_files,但rewrite的last标志会改变这个顺序,跟文档画的流程图完全两码事。

第三个坑:正则贪婪匹配的隐藏bug。我用了 (.*) 捕获所有字符,但它竟然匹配了空字符串,导致 /blog/ 被rewrite成 /,把首页的请求抢走了。改成 (.+) 才能保证至少有一个字符。

最终方案是用了 alias 加上 rewrite .. permanent的一个变种,花了三天调试——别踩这些坑了:1)永远别在生产环境直接试 rewrite 规则,先在staging用 curl -I 看状态码;2)breaklast 的区别要背下来——last重新匹配location,break不匹配;3)日志里 $request_uri 是你最好的调试手段,放个 log_format 带上它。

数据的残酷性:我拿50个随机URL测试,6条教程里只有2条能跑对,4条都会触发循环或404。所以别信那些标题党,自己抓包看响应头才是硬道理。