Nginx url重写小结

难得休假,在家舒服得很,但是没有闲着。因为之前自己写过一个PHP的MVC框架(托管地址:https://github.com/c860/PFW),最近要用它+nginx+mysql做个中型的项目。所以就打算在家重温一下代码,顺便检查一下错误。


结果一检查,果然,路由模块在nginx下崩了。根本经受不起考验。在这里我说一个题外话。其实我比较赞成框架的运行尽量不要有太多依赖环境的说法。就是说,如果一个框架的安装还需要运行许多别的依赖,那么这个框架首先在安装这一步就给人比较糟糕的印象了。当然你可以集成,只要不需要使用者有过于繁琐的步骤,那么就是OK的——不作死就不会死。


说到nginx下路由崩溃的原因,根本是因为url重写这块没有处理好。之前自己写这个MVC框架的时候,还在用apache,所以用的是.htaccess。而到了nginx这一块,一开始的解决方案是用这个工具,把apache的规则转成nginx的规则:http://www.anilcetin.com/convert-apache-htaccess-to-nginx/ ,但是其实说实话,这个工具希望大家还是不要信任。因为转出来的规则要么是走了弯路,要么就是无法正确的处理你要的逻辑。所以希望大家看完我这篇文章之后,就不再需要这个工具了。


进入正题,先上干货:

nginx的重写语法和apache是相似的:

rewrite regex replacement flag

单纯看这一句不难吧?给个例子:

rewrite ^(.*)$ index.php last;

上面这个例子很简单,换成apache的语法是这样:

RewriteRule ^(.*)$ index.php [L]

是不是长得很像咧?再接下来:

跟nginx rewrite有关的指令有:if、rewrite、set、return。接下来我会说,先看rewrite命令的一些参数。

regex不用说就是正则表达式

replacement是替换的规则这个也好理解

flag其实就是规定这个重写规则执行后的动作,有如下几个选项:

last,break,redirect,permanent。

redirect是302,permanent是301,这两个不过多解释。

在这里我要详细讲一下last和break,在讲解它们两个之前先说一下location块。location块的格式如下:

location regex {

}

主要用来匹配一些路径规则,例如:

location /Download {
    rewrite ^/(.*)$ /dl/$1 break;
}

则表示当访问到Download目录的时候才执行rewrite规则。

现在说一下last和break。last和break都表示执行完该规则后不再执行当前一轮的匹配。而它们的区别在于,last执行完之后,会对新的url再执行额外的一轮规则匹配,也就是说如果存在多个location,那么在当前location执行完之后,它会跳到下一个location再执行匹配。而使用break的话则不会。(在这里特别说明一下,当使用last后,可能会出现循环匹配的情况,而nginx则规定了'10 cycle limit',也就是说最多执行10次循环匹配。)举个例子:

location /Download {
    rewrite ^/(.*)$ /dl/$1 break;
}
location /dl {
    rewrite ^/(.*)$ /Download/$1 break;
}

上面的第一个location在执行完之后,就会直接返回了,因为它使用的是break,不会再执行下一个location块。而如果使用last的话,则会将url改变成/dl之后再去执行又一轮的匹配,这第二轮的匹配则会匹配到/dl的location块,然后再改写url为/Download再去执行第三轮,又匹配到/Download的location,以此类推,直至第十轮的时候,nginx就会强制结束这个循环,并抛出500异常。


以上是rewrite的语法解释。应该已经解释得很清楚了。接下来我想讲一讲return。其实这里的return很清楚明白,它返回的就是http的状态码。return 404,return 200,return 301,return 500。这是你自己定的。


set语法,就是set语法就是设置nginx变量的语法,set $value_0 "1",那么就设置了一个变量名为value_0的变量,值为“1”。


if语法,用法和许多编程语言一样:

if( condition ) {

}

但是不同的是,坑爹的condition是不支持类似于AND OR那样的语法的。它这里可以用的条件判断有:

~,区分大小写匹配

!~,区分大小写不匹配

~*,不区分大小写匹配

!~*,不区分大小写不匹配

其实还有目录和文件的条件判断:

 -f 和 !-f 判断文件是否存在

 -d 和 !-d 判断目录是否存在

 -e 和 !-e 判断文件和目录是否存在

 -x 和 !-x 判断文件是否可执行

举个例子:

if ($http_user_agent ~ MSIE) {
        rewrite ^(.*)$ /nginx-ie/$1 break;
}

当浏览器为IE时执行重定向。

if (!-e $request_filename) {
    rewrite ^(.*)$ /404/index.php?$1 break;
}

当目录或文件不存在,转向404页面。

好了,到此,基本上我要说的就说完了。一些语法的基本用法我也说明了。如果不会的话建议去看一下官方文档吧。这篇文章的很多内容也是我根据自己的理解从官方文档翻译过来的。

官方文档地址:http://wiki.nginx.org/HttpRewriteModule


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值