十三、将请求的URL基于正则表达式进行rewrite重写

使用Tengine提供的全局变量或自定义变量,结合正则表达式和标志位实现URL重写以及重定向,通常可以实现http跳转至https、域名1跳转至域名2URL1跳转至URL2等功能。

1、 Perl兼容正则表达式:

Ø  .:匹配除换行符\n以外的任意单个字符

Ø  ?:匹配之前的字符0次或1

Ø  +:匹配之前的字符至少1

Ø  *:匹配之前的字符任意次

Ø  \d:匹配数字

Ø  ^:匹配字符串的开始

Ø  $:匹配字符串的结尾

Ø  {m}:重复m

Ø  {m,}:重复至少m

Ø  {m,n}:重复至少m次,最多n

Ø  [a]:匹配单个字符a

Ø  [a-z]:匹配a-z小写字母中的任意一个

Ø  [^ ]:匹配任何不包括在指定字符集内的任意字符

Ø  |:匹配 | 之前或之后的部分

Ø  ():分组,组成一组用于匹配的实体,通常配合 | 使用。小括号()之间匹配的内容,可以在后面通过$1来引用,$2表示的是前面第二个()里的内容


2、 if

if主要用来判断一些在rewrite语句中无法直接匹配的条件,比如检测文件存在与否

用法:if(条件) {}

Ø  if表达式中的条件为true时,执行if代码块中的语句

Ø  当表达式只是一个变量时,如果值为空或者任何以0开头的字符串都会当作false

Ø  直接比较内容时,使用=!=

Ø  使用正则表达式匹配时,使用

  ²  ~:区分大小写的模式匹配

  ²  ~*:不区分大小写的模式匹配

  ²  !~:区分大小写的模式不匹配

  ²  !~*:不区分大小写的模式不匹配

Ø  使用-f-d-e-x检测文件和目录

  ²  -f!-f用来判断文件是否存在

  ²  -d!-d用来判断目录是否存在

  ²  -e!-e用来判断文件和目录是否存在

  ²  -x!-x用来判断文件是否可执行


3、 return:用来直接设置http返回状态,比如403404等。301302不可用return返回,因为301302不能简单的只返回状态码,还必须有重定向的URL


4、 break:用来立即停止rewrite检测


5、 rewrite

flag标志位

Ø  last:执行该rewrite规则后,停止处理后续的rewrite指令集,对于重写后的URL会重新匹配location

Ø  break:执行该rewrite规则后,停止处理后续的rewrite指令集,不再进行location匹配

Ø  redirect:重写完成之后会返回客户端302状态响应码(临时重定向),地址栏会显示跳转后的地址

Ø  permanent:重写完成之后会返回客户端301(永久重定向),地址栏会显示跳转后的地址


示例1

server段中新增如下2location(没有flag):

location /aaa.html {

rewrite "^/aaa.html$" /bbb.html;

rewrite "^/bbb.html$" /ddd.html;

}

 

location /bbb.html {

rewrite "^/bbb.html$" /ccc.html;

}

创建测试页:

# echo "aaa html" > /usr/local/tengine/html/aaa.html

# echo "bbb html" > /usr/local/tengine/html/bbb.html

# echo "ccc html" > /usr/local/tengine/html/ccc.html

# echo "ddd html" > /usr/local/tengine/html/ddd.html

# nginx -t  # nginx -s reload

测试:# curl http://localhost/aaa.html

blob.png


示例2

server段中新增如下2locationflaglast):

location /aaa.html {

rewrite "^/aaa.html$" /bbb.html last;

rewrite "^/bbb.html$" /ddd.html;

}

 

location /bbb.html {

rewrite "^/bbb.html$" /ccc.html;

}

# nginx -t  # nginx -s reload

测试:# curl http://localhost/aaa.html

blob.png

解释:aaa.html --> bbb.html --> 由于flaglast,所以不会将bbb.html --> ddd.html --> 重新匹配bbb.html --> ccc.html


示例3

server段中新增如下2locationflagbreak):

location /aaa.html {

rewrite "^/aaa.html$" /bbb.html break;

rewrite "^/bbb.html$" /ddd.html;

}

 

location /bbb.html {

rewrite "^/bbb.html$" /ccc.html;

}

# nginx -t  # nginx -s reload

测试:# curl http://localhost/aaa.html

blob.png

解释:aaa.html --> bbb.html --> 由于flagbreak,所以不再进行location匹配


示例4

server段中新增如下代码:

rewrite "^/aaa.html$" /bbb.html;

 

location /ccc.html {

rewrite "^/ccc.html$" /eee.html;

}

 

location /bbb.html {

rewrite "^/bbb.html$" /ccc.html;

rewrite "^/ccc.html$" /ddd.html;

}

# nginx -t  # nginx -s reload

创建测试页:# echo "eee html" > /usr/local/tengine/html/eee.html

测试:# curl http://localhost/aaa.html

blob.png

解释:首先执行server段内的rewrite指令,即aaa.html --> bbb.html --> ccc.html --> ddd.html


示例5

server段中新增如下代码:

rewrite "^/aaa.html$" /bbb.html;

rewrite "^/ccc.html$" /ddd.html;

 

location /bbb.html {

rewrite "^/bbb.html$" /ccc.html;

}

 

location /ddd.html {

rewrite "^/ddd.html$" /eee.html;

}

# nginx -t  # nginx -s reload

测试:# curl http://localhost/aaa.html

blob.png

解释:首先执行server段内的rewrite指令,即aaa.html --> bbb.html --> ccc.html,执行结果不受rewritelocation的位置顺序影响,即location匹配迭代总是先执行server段内的rewrite指令,再进行location匹配,执行location段内的rewrite指令


6、 全局变量:

$content_lengthhttp请求头中的Content-length字段

$content_typehttp请求头中的Content-Type字段

$document_root:当前请求在root指令中指定的值

$host:请求主机头字段,如果请求中没有Host行,则为服务器名称

$http_user_agent:客户端agent信息

$http_cookie:客户端cookie信息

$limit_rate:限制连接速率

$request_method:客户端请求方法,通常为GETPOST

$remote_addr:客户端IP地址

$remote_port:客户端端口

$remote_user:已经经过Auth Basic Module验证的用户名

$request_filename:当前请求的文件路径,由rootalias指令与URL请求生成

$scheme:请求使用的协议,比如http或者是https

$server_protocol:请求使用的协议版本,通常是HTTP/1.0HTTP/1.1

$server_addr:服务器地址,在完成一次系统调用后可以确定这个值

$server_name:服务器名称

$server_port:请求到达服务器的端口号

$request_uri:包含请求参数的原始URL,不包含主机名,如:/foo/bar.php?arg=baz

$uri:不带请求参数的当前URL$uri不包含主机名,如:/foo/bar.html

$document_uri:与$uri相同


7、 生产环境常见案例:

(1)禁止使用curl命令下载文件:

未配置前:# curl http://localhost/index.html

blob.png

server段中新增如下代码:

if ($http_user_agent ~ curl) {

return 403;

}

# nginx -t  # nginx -s reload

测试:# curl http://localhost/index.html

blob.png


(2)基于浏览器实现分离:

server段中新增如下代码:

if ($http_user_agent ~ Firefox){

       rewrite ^/(.*)$ /firefox/$1 break;

}

if ($http_user_agent ~ MSIE){

      rewrite ^/(.*)$ /msie/$1 break;

}

if ($http_user_agent ~ Edge){

      rewrite ^/(.*)$ /edge/$1 break;

}

if ($http_user_agent ~ Chrome){

      rewrite ^/(.*)$ /chrome/$1 break;

}

创建测试页:

# mkdir -pv /usr/local/tengine/html/{firefox,msie,edge,chrome}

# echo "Firefox html" > /usr/local/tengine/html/firefox/index.html

# echo "MSIE html" > /usr/local/tengine/html/msie/index.html

# echo "Edge html" > /usr/local/tengine/html/edge/index.html

# echo "Chrome html" > /usr/local/tengine/html/chrome/index.html

# nginx -t  # nginx -s reload

测试:

使用火狐浏览器访问:http://192.168.1.222/index.html

blob.png


使用IE 9浏览器访问:http://192.168.1.222/index.html

blob.png


使用Edge浏览器访问:http://192.168.1.222/index.html

blob.png

备注:Windows 10中内置的浏览器为Microsoft Edge,之前为IE


使用谷歌浏览器访问:http://192.168.1.222/index.html

blob.png


使用未做规则匹配的360浏览器访问:http://192.168.1.222/index.html

blob.png


访问日志格式如下:

blob.png


(3)实现访问http://blog.qiuyue.com时自动跳转到http://www.qiuyue.com/blog

server {

        listen 80;

        server_name blog.qiuyue.com;

        rewrite ^/(.*)$ http://www.qiuyue.com/blog/$1 permanent;

 

        location / {

 root html/blog;

 index index.html index.html;

        }

}

 

server {

         listen 80;

         server_name www.qiuyue.com;

 

         location / {

  root html/www;

  index index.html index.html;

         }

}

创建测试页:

# mkdir -pv /usr/local/tengine/html/{blog,www/blog}

# echo "http://blog.qiuyue.com/index.html" > /usr/local/tengine/html/blog/index.html

# echo "http://www.qiuyue.com/blog/index.html" > /usr/local/tengine/html/www/blog/index.html

# nginx -t  # nginx -s reload

修改本地Windows 10系统的hosts文件:

C:\Windows\System32\drivers\etc\hosts,末尾新增代码:

192.168.1.222 www.qiuyue.com blog.qiuyue.com

测试:

在浏览器中访问http://blog.qiuyue.com时自动跳转到http://www.qiuyue.com/blog

blob.png

回车后自动跳转:

blob.png


(4)实现访问http://www.qiuyue.com/bbs时自动跳转到http://bbs.qiuyue.com

server {

          listen 80;

          server_name www.qiuyue.com;

          rewrite ^/bbs/(.*)$ http://bbs.qiuyue.com/$1 permanent;

 

          location / {

    root html/www;

    index index.html index.html;

          }

}

 

server {

           listen 80;

           server_name bbs.qiuyue.com;

 

           location / {

    root html/bbs;

    index index.html index.html;

           }

}

创建测试页:

# mkdir -pv /usr/local/tengine/html/{bbs,www/bbs}

# echo "http://bbs.qiuyue.com/index.html" > /usr/local/tengine/html/bbs/index.html

# echo "http://www.qiuyue.com/bbs/index.html" > /usr/local/tengine/html/www/bbs/index.html

# nginx -t  # nginx -s reload

修改本地Windows 10系统的hosts文件:

C:\Windows\System32\drivers\etc\hosts,末尾新增代码:

192.168.1.222 www.qiuyue.com bbs.qiuyue.com

测试:

在浏览器中访问http://www.qiuyue.com/bbs时自动跳转到http://bbs.qiuyue.com

blob.png

回车后自动跳转:

blob.png


(5)实现访问qiuyue.com时自动跳转到www.qiuyue.com

server {

          listen 80;

          server_name qiuyue.com;

          rewrite ^/(.*)$ http://www.qiuyue.com/$1 permanent;

 

          location / {

    root html;

    index index.html index.html;

          }

}

 

server {

          listen 80;

          server_name www.qiuyue.com;


          location / {

    root html;

    index index.html index.html;

          }

}

# nginx -t  # nginx -s reload

修改本地Windows 10系统的hosts文件:

C:\Windows\System32\drivers\etc\hosts,末尾新增代码:

192.168.1.222 qiuyue.com www.qiuyue.com

测试:

在浏览器中访问qiuyue.com时自动跳转到www.qiuyue.com

blob.png

回车后自动跳转:

blob.png


(6)实现访问http://www.aaa.com时自动跳转到http://www.bbb.com

server {

         listen 80;

         server_name www.aaa.com;

         rewrite ^/(.*)$ http://www.bbb.com/$1 permanent;

 

         location / {

   root html/aaa;

   index index.html index.html;

         }

}


server {

          listen 80;

          server_name www.bbb.com;

 

          location / {

  root html/bbb;

  index index.html index.html;

          }

}

创建测试页:

# mkdir -pv /usr/local/tengine/html/{aaa,bbb}

# echo "http://www.aaa.com/index.html" > /usr/local/tengine/html/aaa/index.html

# echo "http://www.bbb.com/index.html" > /usr/local/tengine/html/bbb/index.html

# nginx -t  # nginx -s reload

修改本地Windows 10系统的hosts文件:

C:\Windows\System32\drivers\etc\hosts,末尾新增代码:

192.168.1.222 www.aaa.com www.bbb.com

测试:

在浏览器中访问http://www.aaa.com时自动跳转到http://www.bbb.com

blob.png

回车后自动跳转:

blob.png