Nginx的rewrite模块是使用正则表达式来重定向用户的URL请求,而rewrite可以出现的地方有4个:NGX_HTTP_SRV_CONF NGX_HTTP_SIF_CONF NGX_HTTP_LOC_CONF和NGX_HTTP_LIF_CONF对应关系为:
NGX_HTTP_SRV_CONF:配置文件中的server域中的任何地方;
NGX_HTTP_SIF_CONF:配置文件中server域中的if配置中;
NGX_HTTP_LOC_CONF:配置文件中的location域中的任何地方;
NGX_HTTP_LIF_CONF:配置文件中的location域中的if配置中;
rewrite模块指令说明:
1.
rewrite指令
语法格式:rewrite regex replacement [flag];
其中regex为正则表达式,replacement是用来替换匹配的regex的,flag为标志位,简单来说就是用replacement值来替换匹配regex的值,即基于正则表达式的查找替换;
重写示例:
location / {
root html;
rewrite ^/images/(.*)$ /img/$1;
}
如访问http:///images/a.htm那么就会匹配这个location从而被重写为再次以这个URL进行访问时同样又会被该location所匹配,这次因为不匹配重新规则,所以返回html下的响应文件。从这里可以看出,进行重写后会产生另一个新的请求,而这个新请求又会再次被location检查;
如果rewrite规则有多条时,如
location / {
root html;
rewrite ^/images/(.*)$ /img/$1;
rewrite ^/img/(.*)$ /images/$1;
}
当匹配第一个时被重写,然后又匹配第二个被重写,翻来覆去从而进入死循环。而这些标志位就是来控制被重写后是否继续检查匹配与否。
flag有四种:
last:一旦被当前规则匹配并重写后立即停止检查后续的匹配规则,然后通过重写的地址重新发起请求
break:一旦被当前规则匹配并重写后立即停止检查后续的匹配规则,直接响应而不在重新发起请求
redirect:返回302临时重定向
permanent:返回301永久重定向
对于上述例子来说,使用last依旧会产生循环,但是Nginx最多循环10次,如果10次之后依然没有结果返回,那么就返回500错误;
而且,last和break标记用来实现URI重写,浏览器地址栏的URL不变,但在服务器端访问的路径发生了变化。redirect和permanent标记用来实现URL跳转,浏览器地址栏会显示跳转后的URL地址;
2.
rewrite_log指令
语法格式:rewrite_log on | off;
使用环境:http, server, location, if
是否把重写过程写入错误日志中,默认off且默认级别为notice,早期可以打开该功能来验证重写规则的 正确性,但是这会增加服务器负担,建议生产环境下关闭;
3.
return指令
语法格式:return code [text];
return code URL;
return URL;
使用环境:server, location, if
用于结束rewrite规则的执行并返回状态码给客户端,如204 400 402-406 500-504等,此外,非标准状态码444将以不发送任何Header头的方式结束连接;
4.
if指令
语法格式:if (condition) { ... }
使用环境:server, location
用于检查一个条件是否符合,如果符合则执行大括号内的语句,if指令不支持嵌套,不支持多个条件&&和||处理,condition一般分为两类,一是通过内置的参数和指定的字符串做比较,二是判断文件或目录存在性
可以被指定的条件:
(1)变量名,错误的值包括:空字符串"",或者0;
(2)变量比较可以使用=和!=运算符;
(3)正则表达式模式匹配可以使用~*和~符号;
~表示区分字母大小写的匹配
~*表示不区分字母大小写的匹配
!~和~!的作用相反,!~*和~*的作用相反,表示不匹配为真
(4)-f和!-f用来判断文件是否存在
(5)-d和!-d用来判断目录是否存在
(6)-e和!-e用来判断文件或目录是否存在
(7)-x和!-x用来判断文件是否可执行
部分正则表达式可以在()内,其值通过变量$1-$9访问;
if指令示例:
Referer信息防盗链
location ~* \.(gif|jpg|png|gif)$ {
root /html/images/;
valid_referers none blocked *.a.com;
if ($invalid_referer) {
rewrite ^/(.*) http:///403.html;
}
}
关于referer模块可以查阅:
5.
break指令
语法格式:break;
使用环境:server, location, if
该指令的作用是完成当前的规则集后,不在处理rewrite指令;
如:
if ($slow) {
limit_rate 10k;
break;
}
6.
set指令
语法格式:set $variable value;
使用环境:server, location, if
该指令用于定义一个变量,并给变量赋值。变量的值包括文本,变量以及它们的联合;
如:
set $varname "hello";
7.
uninitialized_variable_warn指令
语法格式: uninitialized_variable_warn on | off;
使用环境: http, server, location, if
该指令引用开启或关闭记录关于未初始化变量的警告信息,默认开启;
附:
Nginx Rewrite可以使用的全局变量
在if location rewrite指令中可以使用如下全局变量
$args #这个变量等于请求行中(GET请求)的参数,如:foo=123&bar=blahblah
$content_length #请求头中的Content-length字段
$content_type #请求头中的Content-Type字段
$document_root #root或alias指令在当前请求中的值
$document_uri #与uri类似
$host #请求主机头字段,或者为匹配请求的服务器名称
$http_user_agent #客户端agent信息
$http_cookie #客户端cookie信息
$limit_rate #限制响应速率
$request_body_file #客户端请求主体信息的临时文件名
$request_method #客户端请求的方式,通常为GET或POST
$remote_addr #客户端的IP地址
$remote_port #客户端的端口
$remote_user #已经过Auth Basic Module验证的用户名
$request_filename #当前请求的文件路径,由root或alias指令与URI请求生成
$request_uri #包含请求参数的原始URI 如”/foo/bar.php?arg=baz”
$scheme #HTTP方法(http https)
$server_protocol #请求使用的协议,通常是HTTP/1.0 HTTP/1.1或HTTP/2.0
$server_addr #接受请求的服务器的地址,在完成一次系统调用后可以确定这个值
$server_name #接受请求的服务器的名称
$server_port #接受请求的服务器的端口
$query_string #和$args类似
$uri #当前请求中的URI,当请求处理(如内部重定向或using index files)时该值会被改变
相关资料:
官方文档:
wiki百科:
《实战Nginx》(张宴著)