六、Nginx的Rewrite规则与实例

2016-08-08 10:38:40来源:oschina作者:孟飞阳人点击


6.1 什么是Nginx的Rewrite规则

Rewrite主要的功能就是实现URI的重写,Nginx的Rewrite规则采用PCRE(Perl Compatible Regular Expressions)Perl 兼容正则表达式的语法进行规则匹配,如果您需要Nginx的Rewrite功能,在编辑Nginx之前,须要编译安装PCRE库。


正则表达式(Regular Expression)在计算机科学中,是指一个用来描述或匹配一系列符合某个句法规则的字符串的单个字符串。最初的正则表达式出现于理论计算机科学的自动控制理论和形式化语言理论中。在这些领域中有对计算(自动控制)的模型和对形式化语言描述与分类的研究。20世纪40年代,Warren McCulloch与Walter Pitts将神经系统中的神经元描述成小而简单的自动控制元。20世纪50年代,数学家斯蒂芬·科尔·克莱尼称之为正则集合的数学符号来描述此模型。肯·汤普逊将此符号系统引入编辑器QED,然后是UNIX上的编辑器ed,并最终引入grep。自此,正则表达式被广泛适用于各种Unix或类似UNIX的工具,例如Perl。


通过Rewrite规则,可以实现规范的URL、根据变量来做URL转向及选择配置。例如,一些使用MVC框架的程序只有一个入口,可以通过Rewrite来实现。一些动态URL地址需要伪装成静态HTML,便于搜索引擎抓取,也需要Rewrite来处理。一些由于目录结构、域名变化的旧URL,需要跳转到新的URL上,也可以通过Rewrite来处理。


6.2 Nginx Rewrite规则相关指令

Nginx Rewrite规则相关指令有if、rewrite、set、return、break等,其中rewrite是最关键的指令。一个简单的Nginx Rewrite规则语法如下:


rewrite ^/b/(.*)/.html /play.jsp?video=$1 break;

如果加上if语句,示例如下:


if(!-f$request_filename)
{ rewrite ^/img/(.*)$/site/$host/images/$1 last;
}6.2.1 break指令
语法:break
默认值:none
使用环境:server,location ,if

该指令的作用是完成当前的规则集,不在处理rewrite指令。


示例如下:


if($slow){
limit_rate10k;
break;
}6.2.2 if 指令
语法:if(condition){…….}
默认值:none
使用环境:server,location

该指令用于检查一个条件是否符合,如果条件符合,则执行大括号内的语句。if指令不支持嵌套,不支持多个条件&&和||处理。


以下信息可以被定为条件:


(1)变量名,错误的值包括:空字符串“”,或者任何以0开始的字符串。


(2)变量比较可以使用“=”和“!=”运算符


(3)正则表达式模式匹配可以使用“~”和“~*”符号;


(4)“~”符号表示区分大小写字母的匹配


(5)“~*”符号表示不区分大小写字母的匹配


(6)“!~”和“!~*”符号的作用刚好和“~”、“!~*”相反,表示不匹配


(7)“-f”和“~-f”用来判断文件是否存在


(8)“-d”和“!-d”用来判断目录是否存在;


(9)“-e”和“!-e”用来判断文件或目录是否存在


(10)“-x”和“!-x”用来判断文件是否可执行。


下面是实例代码:


if($http_user_agnet ~ MSIE){
rewrite ^(.*)$ /msie/$1 break;
}
if($http_cookie ~* “id=([^;] +)(?:;|$)”){
set $id $1;
}
if ($request_method = POST){ return 405;
}
if(! –f $request_filename){ break;
proxy_passhttp://127.0.0.1;
}
if ($slow){
limit_rate10k;
}
if($invalid_referer){
return 403;
}6.2.3 return 指令
语法:return code
默认值:none
使用环境:server、location、if

该指令用于结束规则的执行并返回状态码给客户端。状态码可以使用这些值:204,400,402~406,408,410,411,413,416及500~504.此外,非标准状态码444将以不发送任何Header头的方式结束连接。


示例,如果访问的URL以“.sh”和“.bash”结尾,则返回状态码403:


location ~ .*/.(sh|bash)?$
{
return403;
}

下面我们来详细介绍return指令支持的状态码。


204 No Content:服务器成功处理了请求,但无须返回任何实体内容,并且希望返回更新了的元信息。响应可能通过实体头部的形式,返回新的或更新后的元信息。如果存在这些头部信息,则应当与所请求的变量相呼应。


如果客户端是浏览器,那么用户浏览器应保留发送了该请求的页面,而不产生任何文档视图上的变化,即使按照规范新的或更新后的元信息,也应当被应用到用户浏览器活动视图中的文档。


400 Bad Request:由于包含语法错误,当前请求无法被服务器理解。


402 Payment Required:该状态码是为了将来可能的需求而预留的


403 Forbidden:服务器已经理解请求,但是拒绝执行。与401不同的是,身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交。如果这不是一个HEAD请求,而且服务器希望能够讲清楚为何请求不能被执行,就应该在实体内描述拒绝的原因。当然服务器也可以返回一个404响应,假如它不希望让客户端获得任何信息。


404 Not Found:请求失败,请求所希望得到的资源未在服务器上发现。


405 Method Not Allowed:请求行中指定的请求方法不能被用于请求相应的资源。该响应必须返回一个Allow头信息,用以表示出当前资源能够接受的请求方法的列表。


406 Not Acceptable:请求的资源的内容特性无法满足请求头中的条件,因而无法生成响应实体。


408 Request TimeOut:请求超时。客户端没有在服务器预备等待的时间内完成一个请求的发送。


410 Gone:被请求的资源在服务器上已经不再可用,而且没有任何已知的转发地址。这样的状况应当被认为是永久性的。如果可能,拥有连接编辑功能的客户端应当在获得用户许可后删除所有指向这个地址的引用。如果服务器不知道或无法确定这个状况是否是永久的,就应该使用404状态码。除非额外说明,否则这个响应是可缓存的.


411 Length Required:服务器拒绝在没有定义Content-Length头的情况下接受请求。在添加了表明请求消息体长度的有效Content-Length头之后,客户端可以再次提交该请求。


413 Request Entity Too Large:服务器拒绝处理当前请求,因为该请求提交的实体数据大小超过了服务器愿意或能够处理的范围。此种情况下,服务器可以关闭连接以免客户端继续发送此请求。如果这个状况是临时的,服务器应当返回一个Retry-After的响应头,以告知客户端可以在多少时间以后重新尝试。


500 Internal Server Error:服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器的程序码出错时出现。


501 Not Implemented:服务器不支持当前请求所需要的某个功能。当服务器无法识别请求的方法,并且无法支持其对任何资源的请求时。


502 Bad Gateway:作为网关或代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。


503 Service Unavailable:由于临时的服务器维护或过载,服务器当前无法处理请求。这个状况是临时的,并且将在一段时间以后恢复。如果能够预计延迟时间,那么响应中可以包含一个Retry-After头用以标明这个延迟时间。如果没有给出这个retry-after信息,那么客户端应当处理500响应的方式处理它。


注意:503状态码的存在并不意味着服务器在过载时候必须使用它。某些服务器只不过是希望拒绝客户端的连接。


504 Gateway TimeOut:作为网关或代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI)标识出的服务器,例如HTTP、FTP、LDAP或辅助服务器(例如DNS)收到响应。


注意:某些代理服务器在DNS查询超时时会返回400或500错误。


6.2.4 rewrite 指令
语法:rewrite regex replacement flag
默认值:none
使用环境:server,location,if

该指令根据表达式来重定向URI,或者修改字符串。指令根据配置文件中的顺序来执行。


注意重写表达式只对相对路径有效。如果你想配对主机名你应该使用If语句,代码如下:


if($host ~* www/.(.*)){
set $host_without_www $1;
rewrite ^(.*)$http://$host_without_www$1 permanent ;#$1 contains ‘/foo’,not ‘www.mydomain.com/foo’
}

如果替换串以Http://开头,将会采用301或302跳转进行URL重定向。


rewrite指令的最后一项参数为flag标记,支持的flag标记为:


last:相当于Apache里的[L]标记,表示完成rewrite;


break:本条规则匹配完成后,终止匹配,不在匹配后面的规则;


redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址


permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址。


在以上的标记中,last和break用来实现URI重写,浏览器地址栏的URL地址不变,但在服务器端访问的路径发生了变化。Redirect和Permanent用来实现URL跳转,浏览器地址栏会显示跳转后的URL地址。


last和break标记的实现功能类似,但二者之间有细微的差别,使用alias指令时必须用last标记,使用proxy_pass指令时要使用break标记。last标记在本条rewrite规则执行完毕后,会对其所在server{……}标签重新发起请求,而break标记则在本条规则匹配完成后,终止匹配,不在匹配后面的规则。例如以下这段规则,就必须使用break标记,使用last标记会导致死循环。实例:


if ($host ~* ^www/.gyic/.(.*?)$)
{
rewrite ^/(.*)$ http://www.gyic.com:9007/reserve last;
}

6.2.5 set 指令


语法:set variable value
默认值:none
使用环境:Server,location,if

该指令用于定义一个变量,并给变量赋值。变量的值可以为文本、变量及文本的变量的联合。实例如下:


set$varname‘hello’

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台