Nginx服务的跳转Rewrite、正则表达式

1,235 阅读3分钟

一、Rewrite实际场景

1.1、配置跳转的原因

  • 为了让URL看起来更规范、合理
  • 企业会将动态URL地址伪装成静态地址提供服务
  • 网址换新域名后,期望用户可以通过旧的访问跳转到新的域名上
  • 服务端某些业务调整

1.2、Nginx跳转需求的实现方式

  • 使用rewrite进行匹配跳转(主要匹配的是具体的路径)
  • 使用if匹配全局变量后跳转,结合布尔值时间true和fales的跳转
  • 使用location匹配再跳转(可以匹配后执行proxy_pass,将请求跳转到其他服务上)

1.3、rewrite如何实现跳转

  • nginx服务基于http协议rewrite重写mudule模块
  • nginx:主从URL重写,其中有一个布尔值:返回值的结果只有true或者false;同时特性:只支持if单分支语句
  • 跳转:循环最多可以执行10次,超过后nginx将返回500错误
  • PCRE支持:perl兼容正则表达式的语法规则匹配
  • 重写模块set指令:自己设置即可以使用布尔值

1.4、rewrite功能

  • rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记位实现URL重写以及重定向。
  • 比如:更换域名后需要保持旧的域名能跳转到新的域名上、某网页发生改变需要跳转到新的页面、网站防盗链等等需求

1.5、rewrite生效位置

  • rewrite只能放在server{},location{},if{}中,并且默认只能对域名后边的除去传递的参数外的字符串起作用,
  • 例如http:/ /www . dabao. com/a/we/ index。php?id=1&u=str 只对/a/we/ index . php重写

image.png

1.6、rewrite 执行顺序

执行server 模块里面的rewrite 指令。
执行选定的location 中的rewrite 指令。
执行选定的location中 if中的rewrite指令
示例:
http {
server {
rewrite #优先级1
location ~*.(jpgIgif|swf)$ {
rewrite #优先级2
valid_ referers none blocked *.dog.com dog.com;
if ( $invalid referer ) {
rewrite ^/ http: L /www. dog. com/error.png; #优先级3
}
}
}
}

1.7、对域名或参数字符串

  • 使用if全局变量匹配

  • 使用proxy_ _pass反向代理

    • 把服务端的请求交给后面的服务处理
      首先ip地址定位,如何定位,
upstream apache_server {			##定义的是动态处理服务的地址池
apache-1_ip:端口
apache-2_ip:端口
}
通过location内的正常匹配去调用apache_server
location {
proxy_pass apache_server
} 

apache_server:是一个函数,是可以自定义server,需要upstream和location名字一致

二、Nginx 正则表达式

2.1、字符说明

^	匹配输入字符串的起始位置
$	匹配输入字符串的结束位置
*	匹配前面的字符0次或多次
+	匹配前面的字符1次或多次
?	匹配前面的字符0次或1次
.	匹配除“\n”之外的任何单个字符;字母,数字,符号都包含
\	将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用;使用诸如"[.\n]" 之类的模式,可匹配包括"\n" 在内的任意字符
\w	匹配字母或数字或下划线或汉字
\s	匹配任意的空白符
\b	匹配单词的开始和结束
\d	匹配纯数字
{n}	重复n次
{n,}	重复n次或更多次
[] 定义匹配的字符范围
[c]	匹配单个字符c
[a-z]		匹配a-z小写字母的任意一个
[a-zA-Z]	匹配a-z小写字母或A-Z大写字母的任意一个
()	表达式的开始和结束
|	或的运算符

2.2、rewrite 命令

基本格式:

  • rewrite [flag];
  • regex:表示正则匹配规则
  • replacement:表示跳转后的内容
  • flag:表示rewrite支持的flag标记
  • 其中flag标记说明包含以下
    • last:相当于Apache的以标记,表示完成rewrite
    • break 本条规则匹配完成即终止,不再匹配后面的任何规则
    • redirect 返回302 临时重定向,浏览器地址会显示跳转后的URL地址,爬虫不会更新url
    • permanent 返回301永久重定向,浏览器地址栏会显示跳转后的URL

ast和break比较

lastbreak
使用场景一般写在server和if中一般使用在location中
URL匹配不终止重写后的urI匹配终止重写后的url匹配

三、location分类

分类主要是为了匹配的优先级顺序

3.1、location分类

  • 精准匹配:location = / {…} 示例:location = patt {} PS: 精确匹配字符串
  • 一般匹配:location / {…} 示例:location patt {} PS:只要包含patt的字符串即可
  • 正则匹配: location ~ / {…} 示例:location~patt{}PS:按照正则表达式的方式匹配
    • ~:表达的意思首先是可以支持正则表达式,其次是区分大小写

3.2、location 优先级

  • =:精确匹配

  • ^~:前缀匹配

  • 和*:按文件中的顺序的正则匹配;这里区分匹配是文件还是目录

    • 文件:*优先级高于
    • 目录:优先级高于*
  • 普通匹配:以xxx路径为前缀的匹配

  • /:通用匹配

3.3、Rewrite和Location的小结

  • 相同点:都能实现跳转
  • 不同点:
    • rewrite是在同一域名内更改获取资源的路径
    • location是对一类路径做控制访问或反向代理,还可以 proxy_ pass到其他机器
  • rewrite会写在location里,执行顺序
    • 执行server块里面的rewrite指令
    • 执行location匹配
    • 执行选定的location中的rewrite指令

3.4、实际网站使用中,至少有三个匹配规则

-------------->第一个必选规则:直接匹配网站根,通过域名访问网站首页比较频繁(www.baidu.com/),使用这个会加速处理,比如说官网。
可以是一个静态首页,也可以直接转发给后端应用服务器.
location = / {
	root	html ;
	index index.html index.htm;
}
--------------->第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
有两种配置模式,目录匹配或后缀匹配,任选其--或搭配使用
location ^~ /static/ {
	root /webroot/static/ ;
}
location ~* \. (html|gif|jpg|jpeglpnglcssljslico)$ {
	root /webroot/res/ ;
} 
---------------->第三个规则就是通用规则,比如用来转发带.php、.jsp后缀的动态请求到后端应用服务器,非静态文件请求就默认是动态请求,即跳转或反向代理
upstream		tomcat_ server {
	192.168.226.128:80
	192.168.226.132:80
location / {
	proxy_ pass http: //tomcat_server;
}

四、跳转的优化

4.1、基于域名的跳转

vim /etc/hosts		#添加映射
192.168.35.40 www.zyt.com www.zw.com
mkdir -p /var/log/nginx/
vim /usr/local/nginx/conf/nginx.conf		##修改配置文件
server {
      	  listen       80;
      	  server_name  www.zyt.com;		##域名修改
#charset koi8-r;
 access_log  /var/log/nginx/www.zyt.com-access.log;		##开启并对日志保存路径进行修改
location / {						##在原有location位置插入
     		   if ($host = 'www.zyt.com'){	##$host为rewrite全局变量,代表请求主机头字段或主机名
           	     rewrite ^/(.*)$ http://www.zw.com/$1 permanent; ##$1为匹配的位置变量,即域名后面的字符串,同时永久跳转;(.*)
             	   }
        	    root   html;
         	   index  index.html index.htm;
     	   }
systemctl stop nginx
systemctl start nginx

image.png 需注意使用windows测试需要先映射
本机需要添加映射:c盘–windows–System32–drivers–etc–hosts–ctrl+s(保存)

image.png 测试访问:

image.png

image.png

4.2、基于客户端IP访问跳转

要求所有IP访问任何内容都显示一个固定维护页面,只有公司IP 192. 168.35.40访问正常

mkdir -p /var/log/nginx/
mkdir -p /var/www/html
echo '<h1>页面维护中...</h1>' > /var/www/html/weihu.html
vim /usr/local/nginx/conf/nginx.conf
server {
        listen       80;
        server_name  www.zyt.com
#charset koi8-r;
access_log  /var/log/nginx/www.zyt.com-access.log ;	##开启并对日志保存路径进行修改
    ----------------------------->设置是否是合法的IP标记<--------------------------------
 set $rewrite true;		  	                          #设置变量$rewrite,变量值为布尔值为true
  ----------------------------->设置是否是合法的IP标记<--------------------------------
 if ($remote_addr = '192.168.35.40') {		#当变量值为true时,进行重写
                set $rewrite false;
        }
  ----------------->除了合法IP,其它都是非法IP,进行重写跳转到维护页面<----------------------------
        if ($rewrite = true) {		  	##$remote_ addr:全局变量;当客户端IP为192.168.35.40时,将变量值设为flase,不进行重写
                rewrite (.+) /weihu.html;		##重写在访问IP后边插入/weihu. html,例如	192.168.35.40/weihu.html
        }
        location = /weihu.html {		##增加location
                root /var/www/html			##页面返回/var/www/html /weihu. html的内容
        }
        location / {
            root   html;
            index  index.html index.htm;
        }
systemctl stop nginx
systemctl start nginx

image.png

4.3、基于旧域名跳转到新域名后面加目录

当访问的是bbs.zyt.com/post/1.html…: //www.zw.com/bbs/post/1.…

mkdir -p /var/log/nginx/
mkdir -p /var/www/html
echo '<h1>页面维护中...</h1>' > /var/www/html/weihu.html
vim /usr/local/nginx/conf/nginx.conf
server {
        listen       80;
        server_name  www.zyt.com
#charset koi8-r;
access_log  /var/log/nginx/www.zyt.com-access.log ;	##开启并对日志保存路径进行修改
    ----------------------------->设置是否是合法的IP标记<--------------------------------
 set $rewrite true;		  	                          #设置变量$rewrite,变量值为布尔值为true
  ----------------------------->设置是否是合法的IP标记<--------------------------------
 if ($remote_addr = '192.168.35.40') {		#当变量值为true时,进行重写
                set $rewrite false;
        }
  ----------------->除了合法IP,其它都是非法IP,进行重写跳转到维护页面<----------------------------
        if ($rewrite = true) {		  	##$remote_ addr:全局变量;当客户端IP为192.168.35.40时,将变量值设为flase,不进行重写
                rewrite (.+) /weihu.html;		##重写在访问IP后边插入/weihu. html,例如	192.168.35.40/weihu.html
        }
        location = /weihu.html {		##增加location
                root /var/www/html			##页面返回/var/www/html /weihu. html的内容
        }
        location / {
            root   html;
            index  index.html index.htm;
        }
systemctl stop nginx
systemctl start nginx

image.png

4.4、基于旧域名跳转到新域名后面加目录

当访问的是bbs.zyt.com/post/1.html…: //www.zw.com/bbs/post/1.…

----------------->首先创建一个bbs目录下post的网页文件,并编辑网页文件,做一个映射<----------------
mkdir -p /usr/local/nginx/html/bbs/post		##创建指定目录
echo "<h1>this is 1.html </h1>" >> /usr/local/nginx/html/bbs/post/1.html
echo "192.168.35.40 bbs.zyt.com" >> /etc/hosts
vim /usr/local/nginx/conf/nginx.conf
server {
        listen       80;
        server_name  bbs.zyt.com;		##更改域名
 #charset koi8-r;
access_log  /var/log/nginx/www.zyt.com-access.log ;		##开启并对日志保存路径进行修改
location /post {			##添加location;以post开头匹配
                rewrite (.+) http://www.zw.com/bbs$1 permanent;		##$1为位置变量,代表/post
        }
        location / {
            root   html;
            index  index.html index.htm;
        }
systemctl stop nginx
systemctl start nginx

image.png 浏览器访问:bbs.zyt.com/post/1.html…

image.png

4.5、基于参数匹配(多余)的跳转

现在访问www.zyt.com/100-(100|20…

vim /usr/local/nginx/conf/nginx.conf
server {
        listen       80;
        server_name  www.zyt.com;		##更改域名
        #charset koi8-r;
     access_log  /var/log/nginx/www.zyt.com-access.log ;		##开启并对日志保存路径进行修改
        if ($request_uri ~ ^/100-(100|200)-(\d+)\.html$){ 	##$repuest_uri内置变量,表示URI
                rewrite (.*) http://www.zyt.com permanent;
        }
        location / {
            root   html;
            index  index.html index.htm;
        }
systemctl stop nginx
systemctl start nginx

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

要求访问www.zyt.com/upload/123.…

vim /usr/local/nginx/conf/nginx.conf
server {
        listen       80;
        server_name  www.zyt.com;
        #charset koi8-r;
        access_log  /var/log/nginx/www.zyt.com-access.log ;
        location ~* /upload/.*\.php$ {			##~*:正则匹配,不区分大小写;匹配/upload目录下所有以.php结尾的文件
                rewrite (.*) http://www.zyt.com permanent;
        }
        location / {
            root   html;
            index  index.html index.htm;
        }
systemctl stop nginx
systemctl start nginx

image.png

4.7、基于最普通一条url请求的跳转

要求访问一条url 请求的跳转

vim /usr/local/nginx/conf/nginx.conf
server {
        listen       80;
        server_name  www.zyt.com;
        #charset koi8-r;
        access_log  /var/log/nginx/www.zyt.com-access.log ;
        location ~* /abc/123.html {			##添加location
                rewrite (.+) http://www.zyt.com permanent;
        }
        location / {
            root   html;
            index  index.html index.htm;
        }
systemctl stop nginx
systemctl start nginx

image.png