开发笔记📐 发现👽 人物👮 趣闻💦
Nginx重定向HttpRewrite模块 用正则表达式改变URI

Nginx重定向HttpRewrite模块 用正则表达式改变URI
2018-06-12 01:23:36   点击:

.htaccess和HttpRewrite是新手经常容易犯错的地方,最近遇到这个问题也比较多,老九正好就把收藏的东西整理了一下。主要还是根据官方文档,补足些许翻译工作,后续有心得会再补充。另外Nginx各个版本也有细微区别,具体问题请具体分析。

HttpRewrite模块

该模块允许使用正则表达式改变URI,并且根据变量来转向以及选择配置。

如果在server级别设置该选项,那么他们将在location之前生效。如果在location还有更进一步的重写规则,location部分的规则依然会被执行。如果这个URI重写是因为location部分的规则造成的,那么location部分会再次被执行作为新的URI。

这个循环会执行10次,然后Nginx会返回一个500错误。

指令集:

[#break break]
[#if if]
[#return return]
[#rewrite rewrite]
[#set set]
[#uninitialized_variable_warn uninitialized_variable_warn]

break

语法: break

默认值: none

作用域: server, location, if

作用是完成当前的规则列

示例:

if ($slow) {
: limit_rate  10k;
: break;
}

 

if

语法: if (condition) { ... }

默认: none

作用域: server, location

检查条件的真值。如果条件评估为true,则执行花括号中指示的代码,并根据下一个块内的配置处理请求。如果从上一级继承,则指令内的配置。

可以被分配的条件:

  • 变量的名称,错误值为:空字符串“”,或任何以“0”开头的字符串;
  • 变量与使用“=”和“!=”等运算符进行比较的行;
  • 与使用符号的正则表达式匹配的模式“~*”和“~”,其中,'〜' 含义为符合,但是大小写敏感;而〜*大小写不敏感。而“!~”和“!~*”意思相反,表示“不匹配”;
  • 使用-f以及!-f检测一个文件是否存在;
  • 使用-d以及!-d检测一个目录是否存在;
  • 使用-e以及!-e检测是否存在一个文件,一个目录或者一个符号链接;
  • 使用-x以及!-x检测一个文件是否可执行;

注:正则表达式的部分可以放在括号中,然后可以在 $1 to $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;
}

特别的,内建变量的值$invalid_referer,是由指令有效的引用者给出的。

 

return

语法: return code

默认值: none

作用域: server, location, if

This directive concludes execution of the rules and returns the status code indicated to client. It is possible to use the following values: 204, 400, 402-406, 408, 410, 411, 413, 416 and 500-504. Furthermore, nonstandard code 444 closes the connection without sending any headers.

这个指令根据规则的执行情况,返回一个状态值给客户端。可使用值包括:204,400,402-406,408,410,411,413,416以及500-504。也可以发送非标准的444代码-未发送任何头信息下结束连接。

rewrite

语法: rewrite regex replacement flag

默认: none

作用域: server, location, if

这个指令根据表达式来更改URI,或者修改字符串。指令根据配置文件中的顺序来执行。

注意重写表达式只对相对路径有效。如果你想配对主机名,你应该使用if语句,如下:

if ($host ~* www\.(.*)) {
: set $host_without_www $1;
: rewrite ^(.*)$ http://$host_without_www$1 permanent; # $1 contains '/foo', not 'www.mydomain.com/foo'
}

flag使结束重写指令的执行成为可能。如果替换字符串以http://为头,客户端将被重定向,任何进一步的重写指令将被终止。

flag可以是下列任何一种:

last - 完成重写指令的处理,然后搜索相应的URI和位置

break - 完成重写指令的处理

redirect - 返回临时重定向,代码302;如果替换字符串是以http://开始的,redirect将被使用

permanent - 返回代码301的永久重定向

注意,如果重定向是相对的(没有主机部分),那么当重定向Nginx时,如果头匹配server_name指令的名称或server_name指令的名称(如果头不匹配或不存在),则使用“host”头。

如果标题不匹配或不存在,如果没有设置server_name,则使用本地主机名。如果希望Nginx始终使用“Host”标头,则可以使用通配符“*”server_name(但是要查看这样做的限制)。

例如:

rewrite  ^(/download/.*)/media/(.*)\..*$  $1/mp3/$2.mp3  last;
rewrite  ^(/download/.*)/audio/(.*)\..*$  $1/mp3/$2.ra   last;
return   403;

但是如果我们把这些指令放在location /download/中,那么就需要用break来替换last标志,否则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; 

 

set

语法: set variable value

默认值:无

作用域: server, location, if

指令为所指示的变量建立值。值可以使用文本、变量及其组合。

 

uninitialized_variable_warn

语法: uninitialized_variable_warn on|off

默认值: uninitialized_variable_warn on

作用域:http, server, location, if

启用或禁用关于未初始化变量的警告的日志记录。

在内部,重写指令在将配置文件加载到内部代码时编译,在解释器请求时可用。

这个解释器是一个简单的堆栈虚拟机。例如下面的指令

location /download/ {
: if ($forbidden) {
: return   403;
: }
: if ($slow) {
: limit_rate  10k;
: }
: rewrite  ^/(download/.*)/media/(.*)\..*$  /$1/mp3/$2.mp3  break;
}

将被编译成这个序列:

: variable $forbidden
: checking to zero
: recovery 403
: completion of entire code
: variable $slow
: checking to zero
: checkings of regular expression
: copying "/"
: copying $1
: copying "/mp3/"
: copying $2
: copying "..mpe"

: completion of regular expression
: completion of entire sequence

Nginx url 正则 rewrite 301

上一篇:Javascript在for循环中提供多个参数 - 逗号操作符
下一篇:nginx路由配置 从location对url匹配到Rewrite重写