博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Nginx location 和 rewrite retry
阅读量:2431 次
发布时间:2019-05-10

本文共 2376 字,大约阅读时间需要 7 分钟。

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

访问 /documents/document.html 会使用配置B
访问 /images/1.gif 会使用配置C
访问 /documents/1.jpg 会使用配置D

如何判断命中哪个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

……这他妈坑爹呢!!! 什么叫基本上都用? 什么是不基本的情况? =皿=

有兴趣的可以放狗”基本上都用这个Flag”…

我最终还是在stack overflow找到了答案:

last和break最大的不同在于

– break是终止当前location的rewrite检测,而且不再进行location匹配

– last是终止当前location的rewrite检测,但会继续重试location匹配并处理区块中的rewrite规则

还是这个该死的例子

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..死循环

– break的情况是: 在第2行rewrite处终止,其结果为最终的rewrite地址.

也就是说,上面的某位试图下载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代码.

转载地址:http://ybsmb.baihongyu.com/

你可能感兴趣的文章
解析UTF8字符串,并截取每个字符到vector(C++代码)
查看>>
Outbrain
查看>>
视频站点下载地址汇总
查看>>
智能Web算法第二版前言和译者序
查看>>
Tuoc Luong博文
查看>>
机器学习SVM中关于函数间隔为什么可以设置为1
查看>>
leetcode 2. Add Two Numbers(两数相加) 解法 python
查看>>
leetcode 3. Longest Substring Without Repeating Characters(无重复最长子串) 解法 python
查看>>
leetcode 4. Median of Two Sorted Arrays 解法 python
查看>>
leetcode 1038. Binary Search Tree to Greater Sum Tree 解法 python
查看>>
leetcode 1037. Valid Boomerang 解法 python
查看>>
leetcode 9. Palindrome Number 解法 python
查看>>
leetcode 53. Maximum Subarray 解法 python
查看>>
Python 列表解析
查看>>
米洛个人修炼术:脊柱治疗师来教你对抗职业病
查看>>
米洛个人修炼术:上班效率低事情做不完首先因为这
查看>>
米洛个人修炼术:快速提升能力的简单方法
查看>>
专家说总咒骂的人是坦诚的,如果那样,我是不是太腹黑了
查看>>
不知道在MFC中如何从线程工作函数中向窗口发送消息?用好一个指针就够了
查看>>
记不住东西首先是因为你犯了一个毛病
查看>>