当前位置:首页 > 休闲 > nginx url重写 正文

nginx url重写

来源:烟消火灭网   作者:综合   时间:2026-10-17 05:54:47

nginx的重写url重写,说白了就是重写玩字符串匹配和替换。但玩得好不好,重写差别大了去了——有人用它把旧链接平稳迁移到新结构,重写有人却因为一条规则写错,重写整站404,重写流量腰斩。重写

先看最基础的重写东西。nginx里重写靠两个指令:rewrite和location。重写前者直接改uri,重写后者负责按路径分流。重写很多人混淆这两者,重写其实记忆点很简单:rewrite是重写“改”,location是重写“选”。你要先改还是重写先选,决定了规则放置的位置。

举个我实际处理过的案例。某电商网站原来商品页是/product.php?id=123,后来改成了/goods/123.html。旧链接被搜索引擎收录了上千条,直接下线等于放弃流量。我加了这么一段:

location ~ ^/product\.php$ {  if ($arg_id) {  rewrite ^ /goods/$arg_id.html permanent; } } 

注意几个细节。第一,if里用了$arg_id,nginx自动把查询参数变成变量,这比用$request_uri正则截取干净得多。第二,结尾的permanent返回301,告诉搜索引擎“这页面搬家了,以后别来旧的”。第三,没匹配到id参数时,什么都不做,直接落回原规则——避免误伤。

但如果你以为重写就是正则加跳转,那就天真了。真正坑人的是last和break的区别。这俩都能终止当前重写流程,但last会重新发起location匹配,break则停留在当前location里继续处理。用错场景,轻则多绕一圈,重则死循环。

举个例子。静态资源目录/static/下有个文件被移动了,你想做内部重写:

location /static/ {  rewrite ^/static/(.*)$ /new-static/$1 break; try_files $uri =404; } 

这里必须用break,因为try_files要检查重写后的路径是否存在。如果用last,nginx会重新匹配location,但/new-static/可能没有对应location块,直接掉进默认规则,逻辑就乱了。

还有个常被忽略的点:rewrite发生在location匹配之前还是之后?答案是——如果rewrite写在server块,它在location匹配前执行;如果写在location块内,那是在匹配后执行。这个顺序直接影响你的规则设计。我见过有人把全局重写写在server级,结果某个location内的特殊规则永远跑不到,排查半天。

说个更接地气的场景。防止图片盗链,很多人用valid_referers,但配合重写能玩出花:

location ~* \.(jpg|png|gif)$ {  valid_referers none blocked *.mysite.com; if ($invalid_referer) {  rewrite ^/images/(.*)$ /images/watermark-$1 last; } } 

这样盗链请求会被重写到带水印的图片,而不是直接403。既保留了访问体验,又保护了版权。当然,这种玩法性能开销大,高流量站点慎用。

最后提醒一句:重写规则写多了,日志就是你的朋友。打开rewrite_log on;,nginx会记录每一步重写路径,定位问题比瞎猜快十倍。我每次调规则都开着这个,看到日志里一行行“rewritten redirect”,心里踏实。

URL重写没有银弹,只有不断试错。但掌握好rewrite和location的配合,理解last与break的语义,再熟悉几个变量,你已经能解决九成问题。剩下那一成,等遇到了再查文档吧——反正我每次也是这么干的。

标签:

责任编辑:百科