目录
引言
一、Nginx Rewrite概述
1、Rewrite跳转场景
2、Rewrite跳转实现
3、Rewrite实际场景
4、Nginx正则表达式
5、Rewrite命令
6、location分类
7、location优先级
8、比较rewrite和location
9、loaction示例说明
10、实际网站使用者,至少有三个匹配规则
二、Rewrite使用场景实验
1、基于域名的跳转
2、基于客户端 IP 访问跳转
3、基于旧域名跳转到新域名后面加目录
4、基于参数匹配(多余的)的跳转
5、基于目录下所有 php 结尾的文件跳转
6、基于最普通一条 url 请求的跳转
总结
现在Nginx已经成为很多公司作为前端反向代理(proxy_pass)服务器的首选,在实际工作中往往会遇到很多跳转(重写URL)的需求。比如:更换域名后需要保持旧的域名能跳转到新的域名上、某网页发生改变需要跳转到新的页面、网站防盗链等等需求。如果在后端使用的Apache服务器,虽然也能做跳转,规则库也很强大,但是用Nginx跳转效率会更高(正则精确匹配)。
(1)URL看起来更规范、合理
(2)企业会将动态URL地址伪装成静态地址提供服务
(3)网址换新域名后,让旧的访问跳转到新的域名上
(4)服务端某些业务调整
(1)Nginx:通过ngx_http_rewrite_module 模块支持URL重写、支持if条件判断,但不支持else。
(2)跳转:从一个location跳转到另一个location, 循环最多可以执行10次,超过后nginx将返回500错误。
(3)PCRE支持:perl兼容正则表达式的语法规则匹配。
(4)重写模块set指令:创建新的变量并设其值。
(1)Nginx跳转需求的实现方式
①使用rewrite进行匹配跳转
②使用if匹配全局变量后跳转
③使用location匹配再跳转
(2)rewrite放在server{}、if{}、location{}段中
location只对域名后边的除去传递参数外的字符串起作用
(3)对域名或参数字符串
①使用if全局变量匹配
②使用proxy_pass反向代理
(1)apache与nginx之间区别之一,正则表达式:可以更精确的匹配需求的字符串/参数/位置等等。
(2)常用的正则表达式元字符
字符 |
说明 |
^ |
匹配输入字符串的起始位置 |
$ |
匹配输入字符串的结束位置 |
* |
匹配前面的字符零次或多次 |
+ |
匹配前面的字符一次或多次 |
? |
匹配前面的字符零次或一次 |
. |
匹配除“\n”之外的任何单个字符(使用诸如“[.\n]”之类的模式,可匹配包括“\n”在内的任意字符) |
\ |
将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用 |
\d |
匹配纯数字 |
{n} |
重复n次 |
{n,} |
重复n次或更多次 |
[c] |
匹配单个字符c |
[a-z] |
匹配a-z小写字母的任意一个 |
[a-zA-Z] |
匹配a-z小写字母或A-Z大写字母的任意一个 |
(1)Rewrite命令语法:rewrite
[flag]:rewrite支持的flag标记
(2)flag标记说明
标记 |
说明 |
last |
相当于Apache的[L]标记,表示完成rewrite |
break |
本条规则匹配完成即终止,不再匹配后面的任何规则 |
redirect |
返回302临时重定向,浏览器地址会显示跳转后的URL地址,爬虫不会更新URL |
permanent |
返回301永久重定向,浏览器地址栏会显示跳转后的URL地址,爬虫更新URL |
(3)last和break比较
last |
break |
|
使用场景 |
一般写在server和if中 |
一般使用再location中 |
URL匹配 |
不终止重写后的URL匹配 |
终止重写后的URL匹配 |
(1)分类
location = patt {} [精确匹配]
location patt {} [一般匹配]
location ~ patt {} [正则匹配]
(2)正则匹配的常用表达式
标记 |
说明 |
~ |
执行一个正则匹配,区分大小写 |
~* |
执行一个正则匹配,不区分大小写 |
!~ |
执行一个正则匹配,区分大小写不匹配 |
!~* |
执行一个正则匹配,不区分大小写不匹配 |
^~ |
普通字符匹配;使用前缀匹配。如果匹配成功,则不再匹配其他loaction |
= |
普通字符精确匹配,也就是完全匹配 |
@ |
定义一个命名的location,使用再内部定向时 |
(1)相同类型的表达式,字符串长的会优先匹配
(2)按优先级排列
① = 类型
② ^~ 类型表达式
③正则表达式(~和~*)类型
④常规字符串匹配类型,按前缀匹配
⑤通用匹配(/),如果没有其它匹配,任何请求都会匹配到
(1)相同点
都能实现跳转
(2)不同点
①rewrite是在同一域名内更改获取资源的路径
②location是对一类路径做控制访问或反向代理,还可以proxy_padd到其他机器
(3)rewrite会写在loaction里,执行顺序
①执行server块里面的rewrite指令
②执行loaction匹配
③执行选定的loaction中的rewrite指令
(1)location = / { }
= 为精确匹配 /,主机名后面不能带任何字符串,比如访问 / 和 /data,则 / 匹配,/data 不匹配,再比如location = /abc,则只匹配 /abc,/abc/ 或 /abcd 不匹配。若 location /abc ,则即匹配 /abc、/abcd/ 同时也匹配 /abc/。
(2)location / { } www .kgc.com/路径
因为所有的地址都以/开头,所以这条规则将匹配到所有请求比如访问 / 和 /data,则 / 匹配,/data 也匹配,但若后面是正则表达式会和最长字符串优先匹配(最长匹配)。
(3)location / documents/ { }
匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索其它location只有其它location后面的正则表达式没有匹配到时,才会采用这一条。
(4)location /documents/abc { }
匹配任何以 /documents/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 文件,如果和正则 location ~ /images/abc/1.html 相比,正则优先级更高。
(1)直接匹配网站根,通过域名访问网站首页比较频繁(www.baidu.com/),使用这个会加速处理,比如说官网。可以是一个静态首页,也可以直接转发给后端应用服务器。
location = / {
root html
index index.html index.htm;
}
(2)第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项(静态请求处理的能力+高并发处理能力+资源消耗较低)有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用。
location ^~ /static/ {
root /webroot/static/;
}
location ~* \. (html|gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}
(3)第三个规则就是通用规则,比如用来转发带.php、.jsp后缀的动态请求到后端应用服务器非静态文件请求就默认是动态请求(跳转/反向代理)
upstream tomcat_server {
192.168.32.128:80
192.168.32.130:80
}
location / {
proxy_pass http://tomcat_server;
}
目前公司旧的域名:www.qaz.com,有业务上的变更,需要使用新的域名:www.plm.com,但是旧的域名不能废除,但需要跳转到新的域名上,而且后面的参数保持不变。
第①步骤:添加映射
[root@localhost ~]# vim /etc/hosts
192.168.32.128 www.plm.com www.qaz.com
第②步骤:创建日志目录
[root@localhost ~]# mkdir -p /var/log/nginx/
第③步骤:修改配置文件
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.qaz.com; #修改域名
charset utf-8; #网页内显示中文
access_log /var/log/nginx/www.qaz.com.access.log; #开启并对日志保存路径进行修改
#在原有loaction位置插入
location / {
if ($host = 'www.qaz.com'){ #$host为rewrite全局变量,代表请求主机头字段或主机名
rewrite ^/(.*)$ http://www.plm.com/$1 permanent; #为$1为匹配的位置变量,即域名后边的字符串,同时永久跳转
}
root html;
index index.html index.htm;
}
第④步骤:重启、测试
[root@localhost ~]# systemctl restart nginx.service
此时访问www.qaz.com时会自动跳转到www.plm.com上进行访问
由于公司新版本业务上线,要求所有的IP访问任何内容都显示一个固定的维护页面,只有公司的192.168.32.128能正常访问。
第①步骤:添加映射
[root@localhost ~]# vim /etc/hosts
192.168.32.128 www.qaz.com
第②步骤:创建维护页面
[root@loaction ~]# mkdir -p /var/www/html
[root@loaction ~]# echo '网页维护中,暂时无法访问,给您带来不便,请稍后再登录!
' > /var/www/html/weihu.html
第③步骤:修改配置文件
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.qaz.com;
charset utf-8;
access_log /var/log/nginx/www.qaz.com.access.log;
#设置是否是合法的IP标记
set $rewrite true; #设置变量$rewrite,变量形成为布尔值为true
#判断是否为合法IP
if ($remote_addr = “192.168.32.128”) { #当客户端IP为192.168.32.128时,将变量值设为flase,不进行重写
set $rewrite false;
}
#除了合法IP,其它都是非法IP,进行重写跳转到维护页面
if ($rewrite = true) { #布尔值表达式在不满足false情况下,会匹配满足true的location
rewrite (.+) /weihu.html; #重写在访问IP后边插入/weihu.html,如192.168.32.128/weihu.html
}
location = /weihu.html {
root /var/www/html; #页面返回/var/www/html/weihu.html的内容
}
location / {
root html;
index index.html index.htm;
}
第④步骤:重启、测试
[root@loaction ~]# systemctl restart nginx.service
此时用宁外一台机子访问192.168.32.128时,会跳转到weihu.html界面,而只有IP为192.168.32.128的机子才可以正常进行访问。
当访问的时http://bbs.qaz.com/post/1.html会自动跳转到http://www.qaz.com/bbs/post/1.html
第①步骤:创建指定目录
[root@localhost log]# mkdir -p /var/log/nginx
[root@localhost ~]# mkdir -p /usr/local/nginx/html/bbs/post
[root@localhost ~]# echo " 您访问的是新的页面!
" >> /usr/local/nginx/html/bbs/post/1.html
第②步骤:添加映射
[root@localhost ~]# vim /etc/hosts
192.168.32.128 bbs.qaz.com www.plm.com
第③步骤:修改配置文件
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name bbs.qaz.com; #修改域名
charset utf-8;
access_log /var/log/nginx/www.plm.com-access.log; #修改日志名
location /post {
rewrite (.+) http://www.plm.com/bbs$1 permanent; #这里$1为位置变量,代表/post
}
location / {
root html;
index index.html index.htm;
}
第④步骤:重启、验证
[root@localhost ~]# systemctl stop nginx.service
[root@localhost ~]# systemctl start nginx.service
此时用浏览器访问 http://bbs.qaz.com/post/1.html 会自动跳转到 http://www.plm.com/bbs/post/1.html
第①步骤:添加映射
[root@localhost ~]# vim /etc/hosts
192.168.32.128 www.qaz.com
第②步骤:修改配置文件
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.qaz.com;
charset utf-8;
access_log /var/log/nginx/www.qaz.com-access.log;
if ($request_uri ~ ^/100-(100|200)-(\d+)\.html$) {
rewrite (.*) http://www.qaz.com permanent;
}
location / {
root html;
index index.html index.htm;
}
第③步骤:重启、测试
[root@loaction ~]# systemctl restart nginx.service
使用浏览器访问 http://www.qaz.com/100-100-100.html 或 http://www.qaz.com/100-200-100.html会自动跳转到 http://www.qaz.com页面。
第①步骤:添加映射
[root@localhost ~]# vim /etc/hosts
192.168.32.128 www.qaz.com
第②步骤:修改配置文件
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.qaz.com;
charset utf-8;
access_log /var/log/nginx/www.qaz.com-access.log;
location ~* /upload/.*\.php$ {
rewrite (.*) http://www.qaz.com permanent;
}
location / {
root html;
index index.html index.htm;
}
第③步骤:重启、测试
[root@loaction ~]# systemctl restart nginx.service
浏览器访问 http://www.qaz.com/upload/12345.php 跳转到 http://www.qaz.com 首页
第①步骤:添加映射
[root@localhost ~]# vim /etc/hosts
192.168.32.128 www.qaz.com
第②步骤:修改配置文件
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
server {
listen 80;
server_name www.qaz.com;
charset utf-8;
access_log /var/log/nginx/www.qaz.com-access.log;
location ~* /admin/159.html {
rewrite (.+) http://www.qaz.com permanent;
}
location / {
root html;
index index.html index.htm;
}
第③步骤:重启、测试
[root@loaction ~]# systemctl restart nginx.service
浏览器访问 http://www.qaz.com/admin/159.php 跳转到 http://www.qaz.com 首页。
1、Rewrite实际场景
(1)Nginx跳转需求的实现方式
①使用rewrite进行匹配跳转
②使用if匹配全局变量后跳转
③使用location匹配再跳转
(2)rewrite放在server{}、if{}、location{}段中
location只对域名后边的除去传递参数外的字符串起作用
(3)对域名或参数字符串
①使用if全局变量匹配
②使用proxy_pass反向代理
2、优先级总结
(1)匹配某个具体文件:(location = 完整路径) > (location ^~ 完整路径) > (location ~* 完整路径) > (location ~ 完整路径) > (location 完整路径) > (location /)
(2)用目录做匹配访问某个文件:(location = 目录) > (location ^~ 目录/) > (location ~ 目录) > (location ~*目录) > (location 目录) > (location /)
(3)正则表达式:目的是为了尽量精确的匹配
(4)文件:尽量精确匹配,区分大小写精确、不区分更为精确
(5)目录:尽量精确匹配,区分大小写精确优先级更高,不区分大小写的
3、场景实验:基于域名的跳转;基于客户端 IP 访问跳转;基于旧域名跳转到新域名后面加目录;基于参数匹配(多余的)的跳转;基于目录下所有 php 结尾的文件跳转;基于最普通一条 url 请求的跳转。