nginx的rewrite有个很奇特的特性 — rewrite后的url会再次进行rewrite检查,最多重试10次,10次后还没有终止的话就会返回HTTP 500。 用过nginx的朋友都知道location区块,location区块有点像Apache中的RewriteBase,但对于nginx来说location是控制的级别而已,里面的内容不仅仅是rewrite. 这里必须稍微先讲一点location的知识.location是nginx用来处理对同一个server不同的请求地址使用独立的配置的方式。 举例: location = / { ....配置A } location / { ....配置B } location ^~ /images/ { ....配置C } location ~* \.(gif|jpg|jpeg)$ { ....配置D }
访问 / 会使用配置A 如何判断命中哪个location暂且按下不婊, 我们在实战篇再回头来看这个问题. 现在我们只需要明白一个情况: nginx可以有多个location并使用不同的配. sever区块中如果有包含rewrite规则,则会最先执行,而且只会执行一次, 然后再判断命中哪个location的配置,再去执行该location中的rewrite, 当该location中的rewrite执行完毕时,rewrite并不会停止,而是根据rewrite过的URL再次判断location并执行其中的配置. 那么,这里就存在一个问题,如果rewrite写的不正确的话,是会在location区块间造成无限循环的.所以nginx才会加一个最多重试10次的上限. 比如这个例子 location /download/ { rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last; } 如果请求为 /download/eva/media/op1.mp3 则请求被rewrite到 /download/eva/mp3/op1.mp3。 结果rewrite的结果重新命中了location /download/ 虽然这次并没有命中rewrite规则的正则表达式,但因为缺少终止rewrite的标志,其仍会不停重试download中rewrite规则直到达到10次上限返回HTTP 500。 认真的朋友这时就会问了,上面的rewrite规则不是有标志位last么? last不是终止rewrite的意思么? 说到这里我就要抱怨下了,网上能找到关于nginx rewrite的文章中80%对last标志的解释都是 last – 基本上都用这个Flag
……这他妈坑爹呢!!! 什么叫基本上都用? 什么是不基本的情况? =皿= 我最终还是在stack overflow找到了答案: last和break最大的不同在于
– break是终止当前location的rewrite检测,而且不再进行location匹配 还是这个该死的例子 location /download/ { rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 ; rewrite ^(/download/.*)/movie/(.*)\..*$ $1/avi/$2.mp3 ; rewrite ^(/download/.*)/avvvv/(.*)\..*$ $1/rmvb/$2.mp3 ; } 上面没有写标志位,请各位自行脑补… 如果请求为 /download/acg/moive/UBW.avi
– last的情况是: 在第2行rewrite处终止,并重试location /download..死循环 也就是说,上面的某位试图下载eva op不但没下到反而被HTTP 500射了一脸的例子正是因为用了last标志所以才会造成死循环,如果用break就没事了. location /download/ { rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break; } 对于这个问题,我个人的建议是,如果是全局性质的rewrite,最好放在server区块中并减少不必要的location区块.location区块中的rewrite要想清楚是用last还是break. 有人可能会问,用break不就万无一失了么? 不对.有些情况是要用last的. 典型的例子就是wordpress的permalink rewrite 常见的情况下, wordpress的rewrite是放在location /下面,并将请求rewrite到/index.php 这时如果这里使用break乃就挂了,不信试试. b( ̄▽ ̄)d…因为nginx返回的是没有解释的index.php的源码… 这里一定要使用last才可以在结束location / 的rewrite, 并再次命中location ~ \.php$,将其交给fastcgi进行解释.其后返回给浏览器的才是解释过的html代码. (责任编辑:IT) |