ngx_http_rewrite_module模块的指令按以下顺序处理:
- server级别中定义的指令的顺序
- 基于请求URI查询的location
- 找到的location中指令按顺序执行
- 如果请求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会被解析,如果结果是真值,该模块会被执行,请求会分配到if指令的配置中。if指令中的配置继承自上级配置。
条件可以是下面的值:
- 变量名,如果变量值为“0”或空字符串,则结果为false。1.0.1版本之前,以“0”开头的字符串被认为是false。
- 使用“=”或“!=”操作符进行比较
- 匹配以“~”(大小写敏感)及“~*”(大小写不敏感)开头的正则表达式。正则表达式可以包含捕获,可以在后面用$1~$9使用。“!~”和“!~*”操作符也是可以用的。如果正则表达式包含“}”或“;”字符,整个正则表达式需要用单引号或双引号包裹。
- 通过“-f”或“!-f”操作符检测文件存在性。
- 通过“-d”或“!-d”操作符检测目录存在性。
- 通过“-e”或“!-e”操作符检测文件、目录或符号链接存在性。
- 通过“-x”或“!-x”操作符检测可执行文件的存在性。
例子:
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /msie/$1 break; } if ($http_cookie ~* "id=([^;]+)(?:;|$)") { set $id $1; } if ($request_method = POST) { return 405; } if ($slow) { limit_rate 10k; } if ($invalid_referer) { return 403; }
$invalid_referer内嵌变量由valid_referers指令设置。
return
语法:return code [text]
return code URL
return URL
默认:—
上下文:server, location, if
停止处理,并返回指定的code给客户端。非标准错误码444关闭连接并不返回响应头。
从0.8.42版本起,可以定义重定向URL(为301、302、303或307错误码),或响应体文本(其他错误码)。响应体文本及重定向URL可以包含变量。特殊的情况下,重定向URL可以定义为当前服务器的本地URI,这种情况下,完整的URL由请求的模式($scheme)和server_name_in_redirect及port_in_redirect指令决定。
302的临时重定向URL定义为唯一的参数。该参数应该由“http://”、“https://”或“$scheme”字符串。URL可以包含变量。
0.7.51版本前,只有下面的返回码可以返回:204, 400, 402 — 406, 408, 410, 411, 413, 416, 500 — 504。
307错误码在1.1.16 和 1.0.13版本前不会当做重定向。
rewrite
语法:rewrite regex replacement [flag]
默认:—
上下文:server, location, if
如果指定的正则表达式匹配请求URI,URI会按照replacement字符串进行改变。rewrite指令按照它们出现在配置文件中的顺序执行。可以使用标识对后续处理进行终结。如果替换字符串以“http://”或“https://”开始,处理停止并返回重定向到客户端。
可选flag参数可以是下面值之一:
last
停止处理当前ngx_http_rewrite_module的指令,并开始寻找匹配URI的新location。
break
停止处理ngx_http_rewrite_module的指令,同break指令。
redirect
如果替换字符串不以“http://”和“https://”开头,返回临时响应码302。
permanent
返回永久重定向返回码301。
完整的重定向URL根据请求模式($scheme)和server_name_in_redirect 和 port_in_redirect指令构成。
例子:
server { ... 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; }
如果replacement字符串包含新的请求参数,之前的请求参数会追加到后面。如果不希望这样,在替换字符串后面加一个问号,避免追加参数,例如:
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模块无关。单独的配置会为if块创建。如果条件为true,请求会分配到该配置上,限速10k。
指令
rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break;
可以变得更短,如果正则表达式中第一个“/”在括号里:
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
对应的指令为:
match of regular expression copy $1 copy "/mp3/" copy $2 copy ".mp3" end of regular expression end of code