模块ngx_http_rewrite_module
- 指令
- break
- if
- return
- rewrite
- rewrite_log
- set
- uninitialized_variable_warn
- 内部实现
ngx_http_rewrite_module
模块被用来修改请求URI, 通过使用正则表达式, 重定向, 重新选择配置(根据重写后的uri选择location).
ngx_http_rewrite_module
模块指令以下面的顺序被处理:
- 在
server
块中顺序执行rewrite
模块指令 location
的搜索根据请求的URI- 在匹配的
location
中顺序执行rewrite
模块指令 - 如果重写的URI不断循环匹配, 这个循环的次数不超过10次
指令
break
语法: break
默认: -
上下文: server, location, if
停止处理当前一系列的ngx_http_rewrite_module
模块指令(不会进行重定向).
如果指令在location
中, 那么请求的进一步处理继续在location
中. 例如:
if($slow){
limit_rate 10k;
break;
}
if
语法: if(condition) { ... }
默认: -
上下文: server, location
判断条件condition
可以是以下的任意一种:
一个变量名; 如果这个变量为空字符串或者”0”,则为false
版本1.0.1之前, 只要是以”0”开头的字符串都将判断为false.
变量的比较, 使用
=
或者!=
操作符- 通过正则表达式匹配一个变量,
~
是区别大小写的匹配,~*
是不区分大小写的匹配. 反向的操作符也是同样适用的,!~
和!~*
. 正则表达式用 1− 9变量表示捕获到的值. 如果正则表达式中包含”}”或”;”等符号, 整个表达式应该用单引号或者双引号包含起来. - 检查文件是否存在, 使用
-f
和!-f
操作符. - 检查目录是否存在, 使用
-d
和!-d
操作符. - 检查文件, 目录或者链接是否存在, 使用
-e
和!-e
操作符. - 检查是否为可执行文件, 使用
-x
和!-x
操作符.
例如:
f ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
f ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
f ($request_method = POST) {
return 405;
f ($slow) {
limit_rate 10k;
f ($invalid_referer) {
return 403;
>
$invalid_referer值通过valid_referers指令来设置
return
语法: return code [text];
return code URL;
return URL;
默认: -
上下文: server, location, if
停止并返回特定的代码到客户端. 非标准代码444
将关闭一个连接, 而且不发送响应头部.
从0.8.42版本开始, 它能够返回重定向URL(代码301, 302, 303和307), 也支持返回响应体正文. 而且, 响应体正文和重定向URL可以包含变量.
rewrite
语法: rewrite regex replacement [flag];
默认: -
上下文: server, location, if
如果一个正则表达式匹配一个请求URI, 那么这个URI将被replacement
字符串给代替. rewrite
指令按照在配置文件中的顺序依次执行. 通过使用flag
可以做更多的操作. 如果replacement
是以”http://”或者”https://”开头的字符串, 那么将停止处理, 并返回重定向到客户端.
可选的flag
可以是下面的一个:
- last: 停止处理当前一系列
ngx_http_rewrite_module
指令, 然后搜索新的location
匹配修改后(rewrite)的URI; - break: 停止处理当前一系列
ngx_http_rewrite_module
指令和break
指令; - redirect: 返回一个临时的302重定向; 如果替换后的字符串没有以
http://
和https://
开头, 则使用这个重定向; - permanent: 返回一个永久的301重定向;
例如:
server {
...
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
return 403;
...
}
如果这些rewrite
指令在/download/
location中, 那么last
就应该改为break
, 否则nginx将做10次循环然后返回500错误.(重写后的/download/mp3/xxx.mp3
又将匹配到/download
的location, 然后就会在这个location中不断循环)
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;
rewrite_log
语法: rewrite_log on | off;
默认: rewrite_log off;
上下文: http, server, location, if
开启或关闭将ngx_http_rewrite_module
模块指令的处理结果记录到error_log
的notice
级别.
set
语法: set $variable value;
默认: -
上下文: server, location, if
设置一个变量
uninitialized_variable_warn
语法: uninitialized_variable_warn on | off;
默认: uninitialized_variable_warn on;
上下文: http, server, location, if
控制对未初始化变量的警报是否要被记录.
内部实现
ngx_http_rewrite_module
模块指令在配置阶段编译到内部指令中, 在处理请求过程中被解读. 解释器是一个简单虚拟堆栈机.
例如, 以下指令:
location /download/ {
if ($forbidden) {
return 403;
}
if ($slow) {
limit_rate 10k;
}
rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break;
}
将被翻译成下面的执行指令
variable $forbidden
check against zero
return 403
end of code
variable $slow
check against zero
match of regular expression
copy "/"
copy $1
copy "/mp3/"
copy $2
copy ".mp3"
end of regular expression
end of code
注意的是,没有对应limit_rate
指令的执行指令, 因为这个指令没有关联ngx_http_rewrite_module
模块.