|
| 1 | +# ngx_http_rewrite_module |
| 2 | + |
| 3 | +- [指令](#directives) |
| 4 | + - [break](#break) |
| 5 | + - [if](#if) |
| 6 | + - [return](#return) |
| 7 | + - [rewrite](#rewrite) |
| 8 | + - [rewrite_log](#rewrite_log) |
| 9 | + - [set](#set) |
| 10 | + - [uninitialized_variable_warn](#uninitialized_variable_warn) |
| 11 | +- [内部实现](#internals) |
| 12 | + |
| 13 | +`ngx_http_rewrite_module` 模块使用 PCRE 正则表达式更改请求 URI、返回重定向和有条件地选择配置。 |
| 14 | + |
| 15 | +[break](#break)、[if](#if)、[return](#return)、[rewrite](#rewrite) 和 [set](#set) 指令将按以下顺序处理: |
| 16 | + |
| 17 | +- 在 [server](ngx_http_core_module.md#server) 级别下,该模块的指令按顺序执行 |
| 18 | +- 重复执行: |
| 19 | + - 基于请求 URI 搜索 [location](ngx_http_core_module.md#location) |
| 20 | + - 在 location 内找的该模块的指令按顺序执行 |
| 21 | + - 如果请求 URI 被[重写](#rewrite),则重复循环,但不超过 [10 次](ngx_http_core_module.md#internal)。 |
| 22 | + |
| 23 | +<a id="directives"></a> |
| 24 | + |
| 25 | +## 指令 |
| 26 | + |
| 27 | +### break |
| 28 | + |
| 29 | +|\-|说明| |
| 30 | +|:------|:------| |
| 31 | +|**语法**|**break**;| |
| 32 | +|**默认**|——| |
| 33 | +|**上下文**|server、location、if| |
| 34 | + |
| 35 | +停止处理当前的 `ngx_http_rewrite_module` 指令集。 |
| 36 | + |
| 37 | +如果在该 [location](ngx_http_core_module.md#location) 内指定了指令,则请求的下一步处理在该位置将继续。 |
| 38 | + |
| 39 | +示例: |
| 40 | + |
| 41 | +```nginx |
| 42 | +if ($slow) { |
| 43 | + limit_rate 10k; |
| 44 | + break; |
| 45 | +} |
| 46 | +``` |
| 47 | + |
| 48 | +### if |
| 49 | + |
| 50 | +|\-|说明| |
| 51 | +|:------|:------| |
| 52 | +|**语法**|**if** `(condition) { ... }`;| |
| 53 | +|**默认**|——| |
| 54 | +|**上下文**|server、location| |
| 55 | + |
| 56 | +指定的 `condition` 求值之后,如果为 `true`,则执行在大括号内指定的该模块的指令,并在 `if` 指令内为该请求分配配置。`if` 指令内的配置继承自上一层的配置级别。 |
| 57 | + |
| 58 | +`condition` 可以是以下任何一种: |
| 59 | + |
| 60 | +- 变量名,如果变量的值为空字符串或 `0`,则为 `false` |
| 61 | + |
| 62 | + 在 1.0.1版本 之前,任何以 `0` 开头的字符串都被视为错误值。 |
| 63 | + |
| 64 | +- 使用 `=` 和 `!=` 运算符比较变量和字符串 |
| 65 | + |
| 66 | +- 使用 `~`(区分大小写的匹配)和 `~*`(不区分大小写的匹配)运算符,变量将与正则表达式进行匹配。正则表达式可以包含可供以后在 `$1..$9` 变量中重用的捕获。反操作符 `!~` 和 `!~*` 也可用。如果正则表达式包含 `}` 或 `;` 字符,则整个表达式应使用单引号或双引号包围起来。 |
| 67 | + |
| 68 | +- 使用 `-f` 和 `!-f` 运算符检查文件是否存在 |
| 69 | + |
| 70 | +- 使用 `-d` 和 `!-d` 运算符检查目录是否存在 |
| 71 | + |
| 72 | +- 使用 `-e` 和 `!-e` 运算符检查文件、目录或符号链接是否存在 |
| 73 | + |
| 74 | +- 使用 `-x` 和 `!-x` 运算符检查是否为可执行文件 |
| 75 | + |
| 76 | +示例: |
| 77 | + |
| 78 | +```nginx |
| 79 | +if ($http_user_agent ~ MSIE) { |
| 80 | + rewrite ^(.*)$ /msie/$1 break; |
| 81 | +} |
| 82 | +
|
| 83 | +if ($http_cookie ~* "id=([^;]+)(?:;|$)") { |
| 84 | + set $id $1; |
| 85 | +} |
| 86 | +
|
| 87 | +if ($request_method = POST) { |
| 88 | + return 405; |
| 89 | +} |
| 90 | +
|
| 91 | +if ($slow) { |
| 92 | + limit_rate 10k; |
| 93 | +} |
| 94 | +
|
| 95 | +if ($invalid_referer) { |
| 96 | + return 403; |
| 97 | +} |
| 98 | +``` |
| 99 | + |
| 100 | +> `$invalid_referer` 内嵌变量的值由 [valid_referers](ngx_http_referer_module.md#valid_referers) 指令设置。 |
| 101 | +
|
| 102 | +### return |
| 103 | + |
| 104 | +|\-|说明| |
| 105 | +|:------|:------| |
| 106 | +|**语法**|**return** `code [text]`;<br/> |
| 107 | +**return** `code URL`;<br/>**return** `URL`;| |
| 108 | +|**默认**|——| |
| 109 | +|**上下文**|server、location、if| |
| 110 | + |
| 111 | +停止处理并将指定的 `code` 返回给客户端。非标准代码 444 在不发送响应头的情况下关闭连接。 |
| 112 | + |
| 113 | +从 0.8.42 版本开始,可以指定重定向 URL(对 301、302、303、307 和 308 代码有效)或响应正文 `text`(对其他代码有效)。响应正文和重定向 URL 都可以包含变量。特殊情况下,可以将重定向 URL 指定为此服务器的本地 URI,在这种情况下,根据请求模式(`$scheme`)以及 [server_name_in_redirect](ngx_http_core_module.md#server_name_in_redirect) 和 [port_in_redirect](ngx_http_core_module.md#port_in_redirect) 指令形成完整重定向 URL。 |
| 114 | + |
| 115 | +另外,可以将代码为 302 的临时重定向的 `URL` 指定为唯一参数。这样的参数应该以 `http://`、`https://` 或 `$scheme` 字符串开头。`URL` 可以包含变量。 |
| 116 | + |
| 117 | +> 在 0.7.51 版本之前只能返回以下代码:204、400、402-406、408、410、411、413、416 和 500-504。 |
| 118 | +
|
| 119 | +> 在 1.1.16 版本和 1.0.13 版本之前,代码 307 不被视为重定向。 |
| 120 | +
|
| 121 | +> 在 1.13.0 版本之前,代码 308 不被视为重定向。 |
| 122 | +
|
| 123 | +另请参见 [error_page](ngx_http_core_module.md#error_page) 指令。 |
| 124 | + |
| 125 | +### rewrite |
| 126 | + |
| 127 | +|\-|说明| |
| 128 | +|:------|:------| |
| 129 | +|**语法**|**rewrite** `regex replacement [flag]`;| |
| 130 | +|**默认**|——| |
| 131 | +|**上下文**|server、location、if| |
| 132 | + |
| 133 | +如果指定的正则表达式与请求 URI 匹配,则 URI 将根据 `replacement` 中的指定进行更改。`rewrite` 指令按照它们在配置文件中的出现顺序依次执行。可以使用标志来终止指令的下一步处理。如果替换以 `http://`、`https://` 或 `$scheme` 开头的字符串,则处理流程将停止并将重定向返回给客户端。 |
| 134 | + |
| 135 | +可选的 `flag` 参数可以是以下之一: |
| 136 | + |
| 137 | +- `last` |
| 138 | + |
| 139 | + 停止处理当前的 `ngx_http_rewrite_module` 指令集并开始搜索新的 location 来匹配变更的 URI |
| 140 | + |
| 141 | +- `break` |
| 142 | + |
| 143 | + 与 [break](#break) 指令一样,停止处理当前的 `ngx_http_rewrite_module` 指令集; |
| 144 | + |
| 145 | +- `redirect` |
| 146 | + |
| 147 | + 返回带有 302 代码的临时重定向,如果替换字符串不以 `http://`、`https://` 或 `$scheme` 开头,则生效 |
| 148 | + |
| 149 | +- `permanent` |
| 150 | + |
| 151 | + 返回 301 代码的永久重定向 |
| 152 | + |
| 153 | +完整重定向 URL 根据请求模式(`$scheme`)以及 [server_name_in_redirect](ngx_http_core_module.hmdtml#server_name_in_redirect) 和 [port_in_redirect](ngx_http_core_module.md#port_in_redirect) 指令形成。 |
| 154 | + |
| 155 | +示例: |
| 156 | + |
| 157 | +```nginx |
| 158 | +server { |
| 159 | + ... |
| 160 | + rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last; |
| 161 | + rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last; |
| 162 | + return 403; |
| 163 | + ... |
| 164 | +} |
| 165 | +``` |
| 166 | + |
| 167 | +但是如果这些指令放在 `/download/` 位置,`last` 标志应该用 `break` 替换,否则 nginx 会产生 10 个循环并返回 500 错误: |
| 168 | + |
| 169 | +```nginx |
| 170 | +location /download/ { |
| 171 | + rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break; |
| 172 | + rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break; |
| 173 | + return 403; |
| 174 | +} |
| 175 | +``` |
| 176 | + |
| 177 | +如果 `replacement` 包含新请求参数,则先前的请求参数将最加在它们之后。如果不希望这样,可在 `replacement` 的末尾加上一个问号可以避免追加,例如: |
| 178 | + |
| 179 | +```nginx |
| 180 | +rewrite ^/users/(.*)$ /show?user=$1? last; |
| 181 | +``` |
| 182 | + |
| 183 | +如果正则表达式包含 `}` 或 `;` 字符,则整个表达式应使用单引号或双引号包围。 |
| 184 | + |
| 185 | +### rewrite_log |
| 186 | + |
| 187 | +|\-|说明| |
| 188 | +|:------|:------| |
| 189 | +|**语法**|**rewrite_log** `on` | `oof`;| |
| 190 | +|**默认**|rewrite_log off;| |
| 191 | +|**上下文**|http、server、location、if| |
| 192 | + |
| 193 | +启用或禁用在 `notice` 级别将 `ngx_http_rewrite_module` 模块指令处理结果记录到 [error_log](../核心功能.md#error_log) 中。 |
| 194 | + |
| 195 | +### set |
| 196 | + |
| 197 | +|\-|说明| |
| 198 | +|:------|:------| |
| 199 | +|**语法**|**set** `$variable value`;| |
| 200 | +|**默认**|——| |
| 201 | +|**上下文**|server、location、if| |
| 202 | + |
| 203 | +为指定的 `variable` 设置一个 `value`,`value` 可以包含文本、变量及其组合。 |
| 204 | + |
| 205 | +### uninitialized_variable_warn |
| 206 | + |
| 207 | +|\-|说明| |
| 208 | +|:------|:------| |
| 209 | +|**语法**|**uninitialized_variable_warn** `on` | `oof`;| |
| 210 | +|**默认**|uninitialized_variable_warn on;| |
| 211 | +|**上下文**|http、server、location、if| |
| 212 | + |
| 213 | +控制是否记录有关未初始化变量的警告。 |
| 214 | + |
| 215 | +<a id="internals"></a> |
| 216 | + |
| 217 | +## 内部实现 |
| 218 | + |
| 219 | +`ngx_http_rewrite_module` 模块指令在配置阶段编译为内部指令,其在请求处理期间被解释执行。解释器是一个简单的虚拟栈机器。 |
| 220 | + |
| 221 | +例如以下指令(directive): |
| 222 | + |
| 223 | +```nginx |
| 224 | +location /download/ { |
| 225 | + if ($forbidden) { |
| 226 | + return 403; |
| 227 | + } |
| 228 | +
|
| 229 | + if ($slow) { |
| 230 | + limit_rate 10k; |
| 231 | + } |
| 232 | +
|
| 233 | + rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break; |
| 234 | +} |
| 235 | +``` |
| 236 | +将会翻译成以下指令(instruction): |
| 237 | + |
| 238 | +``` |
| 239 | +variable $forbidden |
| 240 | +check against zero |
| 241 | + return 403 |
| 242 | + end of code |
| 243 | +variable $slow |
| 244 | +check against zero |
| 245 | +match of regular expression |
| 246 | +copy "/" |
| 247 | +copy $1 |
| 248 | +copy "/mp3/" |
| 249 | +copy $2 |
| 250 | +copy ".mp3" |
| 251 | +end of regular expression |
| 252 | +end of code |
| 253 | +``` |
| 254 | + |
| 255 | +请注意,上面的 [limit_rate](ngx_http_core_module.md#limit_rate) 指令没有相关指令(instruction),因为它与 `ngx_http_rewrite_module` 模块无关。这些单独配置是为 [if](#id) 块创建的。如果条件成立,则为此配置分配一个请求,其中 `limit_rate` 等于 10k。 |
| 256 | + |
| 257 | +指令: |
| 258 | + |
| 259 | +```nginx |
| 260 | +rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break; |
| 261 | +``` |
| 262 | + |
| 263 | +如果正则表达式中的第一个斜杠放在括号内,可以让生成的指令(instruction)变得更轻: |
| 264 | + |
| 265 | + |
| 266 | +```nginx |
| 267 | +rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break; |
| 268 | +``` |
| 269 | + |
| 270 | +生成的指令如下: |
| 271 | + |
| 272 | +``` |
| 273 | +match of regular expression |
| 274 | +copy $1 |
| 275 | +copy "/mp3/" |
| 276 | +copy $2 |
| 277 | +copy ".mp3" |
| 278 | +end of regular expression |
| 279 | +end of code |
| 280 | +``` |
| 281 | + |
| 282 | +## 原文档 |
| 283 | +[http://nginx.org/en/docs/http/ngx_http_rewrite_module.html](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html) |
0 commit comments