当前位置: 首页 > 工具软件 > Rewrite > 使用案例 >

Nginx重写功能(rewrite与location)

乌和畅
2023-12-01

一 、常用的nginx 正则表达式

字符涵义以及示例
^匹配输入字符串的起始位置
$匹配输入字符串的结束位置
*匹配前面的字符零次或多次;如“ol*”能匹配“o”及“ol”、“oll”
+匹配前面的字符一次或多次;如“ol+”能匹配“ol”及“oll”、“olll”,但不能匹配“o”
?匹配前面的字符零次或一次;例如“do(es)?”能匹配“do”或者“does”,”?”等效于”{0,1}”
.匹配除“\n”之外的任何单个字符,若要匹配包括“\n”在内的任意字符,请使用诸如“[.\n]”之类的模式
\将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用。如“\n”匹配一个换行符,而“ ” 则 匹 配 “ ”则匹配“
\d匹配纯数字
\D匹配非数字字符,等价于[^0-9]
\s匹配空白字符(空格或者制表符)
\S匹配非空字符
\w匹配包括下划线的任何字符,等价于[a-zA-Z0-9_]
\W匹配任何非单词字符。 等价于 [^a-zA-Z0-9_]
{n}重复 n 次
{n,}重复 n 次或更多次
{n,m}重复 n 到 m 次
[ ]定义匹配的字符范围
[c]匹配单个字符 c
[a-z]匹配 a-z 小写字母的任意一个
[a-zA-Z0-9]匹配所有大小写字母或数字
()表达式的开始和结束位置
|或运算符

二 、nginx 配置文件里 location 项

2.1 localtion 作用

location 用于匹配用户访问的URL,来适用哪一个目录中的资源

2.2 location 可以分为三类

  • 精准匹配 : location = / {…}
  • 一般匹配 : location / {…}
  • 正则匹配 : location ~ / {…}

2.3 location 的常用匹配规则

字符涵义
=进行普通字符精确匹配,也就是完全匹配
^~表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其它 location
~区分大小写的匹配
~*不区分大小写的匹配
!~区分大小写的匹配取非
!~*不区分大小写的匹配取非

2.4 location 的 优先级与匹配规则

  1. 首先是 精确匹配 =

    eg: location = /test/ { }

  2. 其次是 前缀匹配 ^~\

    eg: location ^~ /test/ { }

  3. 其次是按文件中顺序的正则匹配 ~ 或 ~*

    eg: location ~ /test/ { }

  4. 然后是一般匹配 ,后面不带 / 的匹配

    eg: locaton /test/ { }

  5. 最后是 交给 / 通用匹配

    eg: location / { }

首先看匹配的优先级 精确匹配 > 前缀匹配 > 正则匹配 > 一般匹配 > 通用匹配

当 没有精确匹配,只有前缀匹配,或者 正则匹配 时,同等级的优先级遵循匹配即停止原则。即当都是正则匹配时,哪个localtion 写在配置文件的上面,就匹配哪个

一般匹配,则遵循最长匹配原则,当只有一般匹配符合时,哪个location 匹配的url 最长,则使用哪个。但是,如果有符合规则的精确匹配,前缀匹配,正则匹配,则使用优先级高的。

2.5 location 示例说明

1)location = / {}
=为精确匹配 / ,主机名后面不能带任何字符串,比如访问 / 和 /data,则 / 匹配,/data 不匹配
再比如 location = /abc,则只匹配/abc ,/abc/或 /abcd不匹配。

(2)location / {}
因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求 比如访问 / 和 /data, 则 / 匹配, /data 也匹配,
但若后面是正则表达式会和最长字符串优先匹配(最长匹配原则)

(3)location /test/ {}
匹配任何以 /test/ 开头的地址,匹配符合以后,还要继续往下搜索其它 location
只有其它 location后面的正则表达式没有匹配到时,才会采用这一条

(4)location /test/abc {}
匹配任何以 /test/abc 开头的地址,匹配符合以后,还要继续往下搜索其它 location
只有其它 location后面的正则表达式没有匹配到时,才会采用这一条

(5)location ^~ /images/ {}
匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条(匹配即停止原则)

(6)location ~* .(gif|jpg|jpeg)$ {}
匹配所有以 gif、jpg或jpeg 结尾的请求
然而,所有请求 /images/ 下的图片会被 location ^~ /images/ 处理,因为 ^~ 的优先级更高,所以到达不了这一条正则

(7)location /images/abc {}
最长字符匹配到 /images/abc ,如果只有一般匹配,则会使用它,但时由于有 正则匹配和前缀匹配,而一般匹配优先级最低,继续往下搜索其它 location,会发现 ^~ 和 ~ 存在

(8)location ~ /images/abc {}
匹配以/images/abc 开头的,优先级次之,只有去掉 location ^~ /images/ 才会采用这一条

(9)location /images/abc/1.html {}
匹配/images/abc/1.html 文件,如果和正则 ~ /images/abc/1.html 相比,正则优先级更高

2.6 网站使用中的三个匹配规则

2.6.1 第一个必选规则

直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,比如说官网。
这里是直接转发给后端应用服务器了,也可以是一个静态首页

复制location = / {
    proxy_pass http://tomcat_server/;
}

2.6.2 第二个必选规则是处理静态文件请求

这是nginx作为http服务器的强项!
有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用

复制location ^~ /static/ {
	root /webroot/static/;
}
 
location ~* \.(html|gif|jpg|jpeg|png|css|js|ico)$ {
	root /webroot/res/;
	}

2.6.3第三个规则就是通用规则

比如用来转发带.php、.jsp后缀的动态请求到后端应用服务器
非静态文件请求就默认是动态请求

复制location / {
    proxy_pass http://tomcat_server;
} 

三 访问重新rewrite

3.1 rewrite 概述

rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向

rewrite只能放在server{},location{},if{}中,并且默认只能对域名后边的除去传递的参数外的字符串起作用

例如:

http://www.lhq.com/a/gyq/index.php?id=1&u=str 只对/a/gyq/index.php 部分重写

3.2 rewrite 跳转实现

Nginx: 通过 ngx_http_rewrite_module 模块支持URL重写,支持 if 判断,但是不支持else

跳转: 从一个 location 跳转到 另一个location ,循环最多可以执行10次。超出后,返回nginx 500 错误

PCRE 支持: perl 兼容正则表达式的语法规则匹配

重写模块 set 指令: 创建新的变量,并设其值

3.3 rewrite 执行顺序如下:

(1) 执行 server 块里面的 rewrite 指令

(2) 执行 location 匹配

(3) 执行选定的 location 中的 rewrite 指令

语法: rewrite [flag];

regex :表示正则匹配规则

replacement :表示跳转后的内容

flag :表示 rewrite 支持的 flag 标记

flag标记说明

last :本条规则匹配完成后,继续向下匹配新的location URI规则,一般用在 server 和 if 中

break :本条规则匹配完成即终止,不再匹配后面的任何规则,一般使用在 location 中

redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址

permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址。

四 rewrite 示例

4.1 基于域名的跳转

应用场景:现在公司旧域名www.benet.com有业务需求变更,需要使用新域名www.stevelu.com代替,但是旧域名不能废除,需要跳转到新域名上,而且后面的参数保持不变。

4.1.1 配置域名跳转

复制vim /usr/local/nginx/conf/nginx.conf
    
    server {
        listen       80;
        server_name  www.benet.com;  #设置域名

        charset utf-8;

        access_log  logs/benet.access.log ;   #设置日志路径


        location  / {
            if ($host = 'www.benet.com') {   #变量host 为rewrite 的全局变量,代表请求头字段或者主机名
                rewrite ^/(.*)$   http://www.stevelu.com/$1  permanent;  #$1 为正则匹配之后的内容,即 “www.benet.com/" 后面的字符串
            }
            root   html;
            index  index.html index.htm;
        }
        .......
    }
    
 

4.1.2 访问测试

echo '192.168.109.131  www.benet.com   www.mynet.com'  >> /etc/hosts
 
 #注意,网页文件应该放在 /usr/local/nginx/html/目录中
 echo '<h1> hello </h1>'  > /usr/local/nginx/html/index.html
 
 
 /usr/local/nginx  -s reload 

 firefox  http://www.benet.com

4.2 基于客户端IP 访问跳转

应用场景

要求:今天公司业务新版本上线,要求所有 IP 访问任何内容都显示一个固定维护页面,只有公司 IP :192.168.109.131 访问正常

4.2.1 修改配置文件,实现 ip 访问跳转

复制 vim /usr/local/nginx/conf/nginx.conf
 
 server {
        listen       80;
        server_name  www.benet.com;

        charset utf-8;

        access_log  logs/benet.access.log ;
      
       #设置是否合法的IP 标记
        set $rewrite true;  #设置变量rewrite,变量值为boole 值,true
        
        #判断是否合法的IP 标记
        if  ($remote_addr = "192.168.109.131" ) {
            set $rewrite false;        #当客户端的ip 为 192.168.23.104,将变量值设置为false,不进行重写
        }


       #除了  192.168.109.131,其他的iP 都是非法ip,进行重写跳转到 维护界面
       if  ($rewrite = true) {   #变量值为true 时,进行重写
            rewrite (.+) /weihu.html;   #将域名后面的路径重写为 /weihu.html。这里不可以加上 permanent,否则会陷入死循环
        }

        # 设置网页www.benet.com/gyq.html 的内容
        location = /gyq.html {   
             root /var/www/html;    
        }
        
        
        location  / {
            root   html;
            index  index.html index.htm;
        }
     .......
}
   
   
   echo  "<h1> hello </h1>" > /usr/local/nginx/html/index.html
   mkdir -p /var/www/html/
   echo "<h1> gyq </h1>"   >  /var/www/html/index.html
   
   nginx -s reload  #重载 nginx 配置文件

4.2.2 访问测试

192.168.109.131 主机访问

echo "192.168.109.131 www.benet.com " >> /etc/hosts
firefox  http://www.benet.com    

192.168.109.132 主机访问

复制echo "192.168.109.132 www.benet.com " >> /etc/hosts
firefox http://www.benet.com

4.3 基于旧域名跳转到新域名后面加目录(把原本域名的主机名变为现在的目录名

现在访问的是 http://bbs.benet.com/post,现在需要将这个域名下面的访问都跳转到http://www.benet.com/bbs/post

4.3.1修改配置文件

复制vim /usr/local/nginx/conf/ngixn.conf    
server {        
	listen       80;        
	server_name  bbs.benet.com;        
	charset utf-8;        
	access_log  
	logs/bbs.benet.access.log  main;        
	location  /test {            
		rewrite (.+)   http://www.betnet.com/bbs/$1  permanent;        
		}  #$1 表示位置变量,值是 /test        
	location / {            
		root   html;            
		index  index.html index.htm;        
		}       
	...... 
}

4.3.2 访问测试

复制mkdir -p /usr/local/nginx/html/bbs/test
echo "this is 1.html" > /usr/local/nginx/html/bbs/test/1.html
echo "192.168.109.132 bbs.benet.com" >> /etc/hosts
nginx  -s reload
firefox http://bbs.benet.com/test/1.html

4.4 基于参数匹配跳转

访问http://www.benet.com/100-(100|200)-100.html 跳转到http://www.benet.com页面

4.4.1 修改配置文件

复制vim /usr/localnginx/conf/nginx.conf
 server {
        listen       80;
        server_name  www.benet.com;

        charset utf-8;

        listen       80;
        server_name  www.benet.com;

        charset utf-8;

        access_log  logs/www.benet.access.log ;

        if ($request_uri ~ ^/100-(100|200)-(\d+).html$) {  #uri为 完整的url除去$host部分. \d 表示匹配数字。
                rewrite (.+) http://www.benet.com permanent;
        }



        location / {
            root   html;
            index  index.html index.htm;
        }
       .....
  }


#$request_uri: 包含请求参数的原始URI,不包含主机名,如: http://www.kgc.com/abc/bbs/index.html?a=1&b=2中的/abc/bbs/index.php?a=1&b=2

#$$uri:这个变量指当前的请求URI,不包括任何参数,如: /abc/bbs/index.html

#$document_uri: 与$uri相同, 这个变量指当前的请求URI,不包括任何传递参数,如:/abc/bbs/index.html

4.4.2 访问测试

复制firefox http;//www.benet.com/1oo-200-100.html

4.5 基于目录下所有的php 结尾的文件跳转

要求访问 http://www.benet.com/upload/123.php 跳转到首页。

4.5.1 修改配置文件

复制 vim /usr/local/nginx/conf/nginx.conf
 server {
        listen       80;
        server_name  www.benet.com;

        charset utf-8;

        access_log  logs/www.benet.access.log ;

		#将/upload/路径后面,所有.php 结尾的转发
        location ~* /upload/.*\.php$ {   
             rewrite (.+)  http://www.benet.com permanent;
        }

        location / {
            root   html;
            index  index.html index.htm;
        }
        .....
   }

4.5.2 访问测试

复制nginx -s  reload 
firefox http://www.benet.com/upload/123.php

4.6 基于最普通一条 URL 请求的跳转

要求访问一个具体的页面如 http://www.benet.com/abc/888.html 跳转到首页

4.6.1 修改配置文件

复制vim /usr/local/nginx/conf/nginx.conf

    server {
        listen       80;
        server_name  www.benet.com;

        charset utf-8;

        access_log  logs/www.benet.access.log ;

        location ~*  ^/abc/123.html {   
             rewrite (.+)  http://www.benet.com permanent;
        }

        location / {
            root   html;
            index  index.html index.htm;
        }
        ......
     }

4.6.2 测试

复制nginx -s reload
firefox http://www.benet.com/abc/123.html

4.7 rewrite 总结

location 用于匹配 用户访问请求的URL ,来使用哪一个目录中的网页资源,

rewrite … permanent 修改url 后再次请求访问

rewrite /weihu.html 按照修改域名后的 url 直接跳转到对应的 location

location ~ … if ($request_uri) {

rewrite 如果对全URL 重写,则重写部分就以http:// 开头,后面跟上重写后的URL。 http://…

如果不以http://… 开始重写, 默认只对于域名后的路径重写,对 ?后传递的参数无效如http://www.benet.com/abc/?.. ,则只 对 " abc" 进行重写

}

 类似资料: