nginx内部支持url rewrite,内部编译进去了rewrite模块,nginx的rewrite模块类似于apache的rewriterule功能;支持多种规则和正则表达式;
详细介绍如下:
Nginx Rewrite规则相关指令
Nginx Rewrite规则相关指令有if、rewrite、set、return、break等,其中rewrite是最关键的指令。一个简单的Nginx Rewrite规则语法如下:
rewrite ^/b/(.*).html /play.php?video=$1 break;
如果加上if语句,示例如下:
if (!-f $request_filename)
rewrite ^/img/(.*)$ /site/$host/images/$1 last;
指令
break
语法:break
默认值:none
使用字段:server, location, if
完成当前设置的规则,停止执行其他的重写指令。
示例:
if ($slow) {
limit_rate 10k;
break;
}
if
语法:if (condition) { … }
默认值:none
使用字段:server, location
注意:在使用if指令之前请查看if is evil page并且尽量考虑用try_files代替。
判断一个条件,如果条件成立,则后面的大括号内的语句将执行,相关配置从上级继承。
可以在判断语句中指定下列值:
一个变量的名称;不成立的值为:空字符传”“或者一些用“0”开始的字符串。
一个使用=或者!=运算符的比较语句。
使用符号~和~模式匹配的正则表达式:
~为区分大小写的匹配。
~不区分大小写的匹配(firefox匹配FireFox)。
!~和!~*意为“不匹配的”。
使用-f和!-f检查一个文件是否存在。
使用-d和!-d检查一个目录是否存在。
使用-e和!-e检查一个文件,目录或者软链接是否存在。
使用-x和!-x检查一个文件是否为可执行文件。
正则表达式的一部分可以用圆括号,方便之后按照顺序用$1-$9来引用。
示例配置:
if ($http_user_agent ~ 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 http://127.0.0.1;
}
if ($slow) {
limit_rate 10k;
}
if ($invalid_referer) {
return 403;
}
if ($args ~ post=140){
rewrite ^ http://example.com/ permanent;
}
内置变量$invalid_referer用指令valid_referers指定。
return
语法:return code
默认值:none
使用字段:server, location, if
这个指令结束执行配置语句并为客户端返回状态代码,可以使用下列的值:204,400,402-406,408,410, 411, 413, 416与500-504。此外,非标准代码444将关闭连接并且不发送任何的头部。
rewrite
语法:rewrite regex replacement flag
默认值:none
使用字段:server, location, if
按照相关的正则表达式与字符串修改URI,指令按照在配置文件中出现的顺序执行。
可以在重写指令后面添加标记。
如果替换的字符串以http://开头,请求将被重定向,并且不再执行多余的rewrite指令。
尾部的标记(flag)可以是以下的值:
last - 完成重写指令,之后搜索相应的URI或location。
break - 完成重写指令。
redirect - 返回302临时重定向,如果替换字段用http://开头则被使用。
permanent - 返回301永久重定向。
注意如果一个重定向是相对的(没有主机名部分),nginx将在重定向的过程中使用匹配server_name指令的“Host”头或者server_name指令指定的第一个名称,如果头不匹配或不存在,如果没有设置server_name,将使用本地主机名,如果你总是想让nginx使用“Host”头,可以在server_name使用“*”通配符(查看http核心模块中的server_name)。例如:
rewrite ^(/download/.)/media/(.)..$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.)/audio/(.)..$ $1/mp3/$2.ra last;
return 403;
但是如果我们将其放入一个名为/download/的location中,则需要将last标记改为break,否则nginx将执行10次循环并返回500错误。
location /download/ {
rewrite ^(/download/.)/media/(.)..$ $1/mp3/$2.mp3 break;
rewrite ^(/download/.)/audio/(.)..$ $1/mp3/$2.ra break;
return 403;
}
如果替换字段中包含参数,那么其余的请求参数将附加到后面,为了防止附加,可以在最后一个字符后面跟一个问号:
rewrite ^/users/(.*)$ /show?user=$1? last;
注意:大括号({和}),可以同时用在正则表达式和配置块中,为了防止冲突,正则表达式使用大括号需要用双引号(或者单引号)。例如要重写以下的URL:
/photos/123456
为:
/path/to/photos/12/1234/123456.png
则使用以下正则表达式(注意引号):
rewrite "/photos/([0-9] {2})([0-9] {2})([0-9] {2})" /path/to/photos/$1/$1$2/$1$2$3.png;
如果指定一个“?”在重写的结尾,Nginx将丢弃请求中的参数,即变量$args,当使用$request_uri或$uri&$args时可以在rewrite结尾使用“?”以避免nginx处理两次参数串。
在rewrite中使用$request_uri将www.example.com重写到example.com:
server {
server_name www.example.com;
rewrite ^ http://example.com$request_uri? permanent;
}
同样,重写只对路径进行操作,而不是参数,如果要重写一个带参数的URL,可以使用以下代替:
if ($args ^~ post=100){
rewrite ^ http://example.com/new-address.html? permanent;
}
注意$args变量不会被编译,与location过程中的URI不同(参考http核心模块中的location)。