六、Nginx的Rewrite规则与实例
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_rate  10k;
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_pass  127.0.0.1;
}
if  ($slow){
limit_rate  10k;
}
if($invalid_referer){
return 403;
}
6.2.3 return 指令
语法:return code
nginx和网关怎么配合使用默认值:none
使⽤环境:server、location、if
该指令⽤于结束规则的执⾏并返回状态码给客户端。状态码可以使⽤这些值:204,400,402~406,408,410,411,413,416及500~504.此外,⾮标准状态码444将以不发送任何Header头的⽅式结束连接。
⽰例,如果访问的URL以“.sh”和“.bash”结尾,则返回状态码403:
location ~ .*\.(sh|bash)?$
{
return  403;
}
下⾯我们来详细介绍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 ^(.*)$  $host_without_www$1 permanent ;#$1 contains ‘/foo’,not ‘domain/foo’
}
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 ^/(.*)$ ic:9007/reserve last;
}
6.2.5 set 指令
语法:set variable value
默认值:none
使⽤环境:Server,location,if
该指令⽤于定义⼀个变量,并给变量赋值。变量的值可以为⽂本、变量及⽂本的变量的联合。实例如下:
set  $varname  ‘hello’

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。