Nginx Rewrite
常用的Nginx正则表达式及rewrite和location的区别
表达式 | 说明 |
---|---|
^ | 匹配输入字符串的起始位置 |
$ | 匹配输入字符串的结束位置 |
* | 匹配前面的字符零次或多次 例如"ab*“能匹配"a”、“ab"或者"abb” |
+ | 匹配前面的字符一次或多次 例如:“ab+“能匹配"ab"及"abb”、“abbb”,但不能匹配成"a” |
? | 匹配前面的字符零次或一次 例如:“ta(ke)?“能匹配"ta"或者"take”,”?“相当于”{0,1}" |
. | 匹配除了"\n"之外的任何单个字符 若要匹配包括"\n"在内的任意字符,可以使用类似"[.\n]"之类的模式 |
\ | 将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用 例如:"\n"匹配一个换行符,但是"\$“则匹配”$" |
\d | 匹配纯数字 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
[ ] | 定义匹配的字符范围 |
[c] | 匹配单个字符c |
[a-z] | 匹配a-z小写字母的任意一个 |
[a-zA-Z0-9] | 匹配所有大小写字母或数字 |
( ) | 表达式的开始和结束位置 |
| | “或”运算符 |
rewrite和location区别
- rewrite和location在功能上有些相似,都能实现跳转。
- rewrite和location主要的区别在于rewrite是在同一域名内更改获取资源的路径,而location是对一类路径做控制访问或反向代理,还可以proxy_pass到其他设备
location
- location就是用来匹配相关的访问路径,但是有优先级之分
location分类
- location可以分成三类
- 精准匹配:location = / {…}
- 一般匹配:location / {…}
- 正则匹配:location ~ / {…}
location匹配规则
规则 | 说明 |
---|---|
= | 进行普通字符精确匹配 相当于完全匹配 |
^~ | 表示普通字符匹配 使用前缀匹配,如果匹配成功,则不再匹配其他location |
~ | 区分大小写的匹配 |
~* | 不区分大小写的匹配 |
!~ | 区分大小写的匹配取非 |
!~* | 不区分大小写的匹配取非 |
location匹配优先级
精确匹配 =
高于
前缀匹配 ^~
高于
按文件中顺序的正则匹配 ~或~*
高于
不带任何修饰的前缀匹配
高于
/ 通用匹配
- location示例说明
- location = / { }
=为精确匹配 / ,主机名后面不能带任何字符串
例如:访问 / 和 /data ,则 / 匹配, /data不会匹配;location = /qwe,则只匹配/qwe,/qwe/或/qwer不匹配。若location /abc,则匹配/abc 、 /abcd/同时也匹配/abc/
- location = / { }
- location / { }
- 因为所有的地址都以 / 开头,所以此条规则将匹配到所有请求
例如:访问 / 和 /data,则 / 匹配, /data 也匹配。但后面若是正则表达式,则会和最长字符串优先匹配(最长匹配)
- 因为所有的地址都以 / 开头,所以此条规则将匹配到所有请求
- location /documentis/ { }
- 匹配任何以 /documentis/开头的地址,匹配符合以后,还会继续往下搜索其他location,只有其他location后面的正则表达式没有匹配到时,才会采用这一条
- location ^~ /images/ { }
- 匹配任何以 /images/开头的地址,匹配符合以后,停止往下搜索正则,采用这一条
- location ~* \.(gif|jpg|jpeg)$ { }
- 匹配所有以gif、jpg或jpeg结尾的请求
- location /images/abc { }
- 最长字符匹配到 /images/abc,优先级最低,继续往下搜索其他location,会发现^~ 和 ~存在
- location ~ /images/abc { }
- 匹配以/images/abc开头的,优先级次之,只有去掉location ^~ /images/ 才会采用这一条
- location /images/abc/2.html { }
- 匹配/images/abc/2.html文件,如果和正则location ~ /images/abc/2.html相比,正则优先级更高
- 优先级总结
- (location = 完整路径)>(location ^~ 路径)>(location ~,~* 正则顺序)>(location部分起始路径)>(location /)
网站使用中三个匹配规则定义
-
1.第一个必选规则
- 直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,例如官网
- 可以是一个静态首页,也可直接转发给后端应用服务器
-
2.第二个必选规则
- 处理静态文件请求,这也是Nginx作为http服务器的强项
- 共两种模式,目录匹配或后缀匹配,任选其一或搭配使用
-
3.第三个规则是通用规则
- 例如用来转发带.php、.jsp后缀的动态请求到后端应用服务器
- 非静态的文件请求默认是动态请求
rewrite
- rewrite功能:使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记位实现URL重写以及重定向
例如:更改域名后需要保持旧的域名能跳转到新的域名上、某网页发生改变需要跳转到新的页面、网站防盗链等等需求 - rewrite只能放在server{ },location{ },if{ }中,并且默认只能对域名后面除去传递的参数以外的字符串起作用
例如:http://www.qz.com/q/qz/index.php?id=1&u=str只对/q/qz/index.php,也就是"?“之前,”.com/"之后的字符串起到重写作用
rewrite跳转实现
- Nginx
- 通过ngx_http_rewrite_modul模块支持URL重写、支持if条件判断,但不支持else条件判断
- 跳转
- 从一个location跳转到另一个location,循环最多可以执行10次,超过后nginx将会返回500错误
- PCRE支持
- perl兼容正则表达式的语法规则匹配
- 重写模块set指令
- 创建新的变量并设定其值
- 创建新的变量并设定其值
rewrite执行顺序及语法格式
- rewrite执行顺序如下
- 1.执行server块里面的rewrite指令
- 2.执行location匹配
- 3.执行选定的location中的rewrite指令
- rewrite语法格式
- rewrite <regex> <replacement> <flag>;
- regex:表示正则匹配规则
- replacement:表示跳转后的内容
- flag:表示rewrite支持的flag标记
rewrite支持的flag标记
- last
- 本条规则匹配完成后,继续向下匹配新的location URL规则。通常用在server和if中
- break
- 本条规则匹配完成即终止,不再匹配后面的任何规则。一般用在location中
- redirect
- 返回302临时重定向,浏览器地址会显示跳转后的URL地址
- permanent
- 返回301永久重定向,浏览器地址栏会显示跳转后的URL地址
基于域名的跳转
- 实验环境
- 现在公司旧域名http://www.qz.com/有业务需求变更,需要使用新域名http://www.qzqz.com/代替,但是旧域名不能废除,需要跳转到新域名上,而且后面的参数保持不变
- http://www.qz.com/ceshi/1.html → http://www.qzqz.com/ceshi/1.html
37 server_name www.qz.com; 【域名修改】
39 charset utf-8;
41 access_log /var/log/nginx/www.qz.com-access.log; 【日志修改】
【添加域名重定向】
43 location / {
44 if ($host = 'www.qz.com') {
【$host为rewrite全局变量,表示请求主机头字段或主机名】
45 rewrite ^/(.*)$ http://www.qzqz.com/$1 permanent;
【$1是正则匹配的内容,表示域名后面的字符串】
46 }
[root@localhost conf]# mkdir /var/log/nginx/
[root@localhost conf]# echo "192.168.131.14 www.qz.com www.qzqz.com" >> /etc/hosts
[root@localhost conf]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.131.14 www.qz.com www.qzqz.com
[root@localhost conf]# systemctl restart nginx.service
浏览器验证
- 浏览器输入模拟访问http://www.qz.com/ceshi/1.html(即使此请求的内容是不存在)会跳转到http://www.qzqz.com/ceshi/1.html,查看元素即可看到返回301,并实现了永久重新打跳转,而且域名后面的参数也正常跳转
基于客户端IP访问跳转
- 实验环境
- 公司业务新版本上线,要求所有IP访问任何内容都显示一个固定维护页面,只有公司IP:192.168.131.15访问正常
[root@localhost /]# vim /usr/local/nginx/conf/nginx.conf
36 listen 80;
37 server_name www.qz.com;
38
39 charset utf-8;
40
41 access_log /var/log/nginx/www.qz.com-access.log;
【设置是否合法的IP标记】
42 set $rewrite true; 【设置变量$rewrite,变量值为布尔值(boole)true】
【判断是否为合法IP】
43 if ($remote_addr = "192.168.131.13"){ 【当客户端IP为192,168.131.13时,将变量值设为false,不进行重写】
44 set $rewrite false;
45 }
【除了合法IP,其他都是非法IP,进行重写跳转到升级页面】
46 if ($rewrite = tree) { 【当变量值为true时,进行重写】
47 rewrite (.+) /shengji.html; 【重写在方位IP后面插入/shengji.html;例如192.168.131.14/shengji.html】
48 }
49 location = /shengji.html {
50 root /var/www/html; 【网页返回/var/www/html/shengji.html的内容】
51 }
52 location / {
53 root html;
54 index index.html index.htm;
55 }
[root@localhost html]# mkdir -p /var/www/html/
[root@localhost html]# echo "升级中!" > /var/www/html/shengji.html
[root@localhost html]# cat /var/www/html/shengji.html
升级中!
[root@localhost html]# systemctl restart nginx.service
- 如果rewrite (.+) /shengji.html; 改成rewrite (.+) /shengji.html permanent;的话,如果是非192.168.80.13的主机访问会使浏览器修改请求访问的URL成http://www.qz.com/shengji.html再请求访问,这样就会进入一种一直在rewrite的死循环,访问请求一直被重写http://www.qz.com/shengji.html再请求访问
浏览器验证
- 只有IP为192.168.131.13的客户端能够正常访问,其他IP地址访问都是跳转后的维护页面
- 192.168.131.13的客户端需要域名指定
[root@localhost ~]# vim /etc/resolv.conf
ted by NetworkManager
nameserver 192.168.131.14
基于旧域名跳转到新域名后面加目录
- 现在访问的是http://www.qz.com ,现在需要将这个域名下面的访问都跳转到http://www.qzqz.com/bbs
35 server {
36 listen 80;
37 server_name www.qz.com; 【域名修改】
38
39 charset utf-8;
40 access_log /var/log/nginx/www.qz.com-access.log;
41 location /post {
42 rewrite (.+) http://www.qzqz.com/bbs$1 permanent; 【这里的$1是位置变量,代表/post】
43 }
44 location / {
45 root html;
46 index index.html index.htm;
47 }
[root@localhost /]# mkdir -p /usr/local/nginx/html/bbs/post
[root@localhost /]# echo "this is 1.html" >> /usr/local/nginx/html/bbs/post/1.html
[root@localhost /]# echo "192.168.131.14 www.qz.com" >> /etc/hosts
[root@localhost /]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.131.14 www.qz.com www.qzqz.com
192.168.131.14 www.qz.com
[root@localhost /]# systemctl restart nginx.service
浏览器验证
- 浏览器访问http://www.qz.com/post/1.html则跳转到了http://www.qzqz.com/bbs/post/1.html
基于参数匹配的跳转
- 当访问http://www.qz.com/50-(50|100)-50.html则会跳转到http://www.qz.com页面
35 server {
36 listen 80;
37 server_name www.qz.com;
38
39 charset utf-8;
40 access_log /var/log/nginx/www.qz.com-access.log;
41
42 if ($request_uri ~ ^/50-(50|100)-(\d+).html$){
43 rewrite (.*) http://www.qz.com permanent;
44 }
45 location / {
46 root html;
47 index index.html index.htm;
48 }
[root@localhost /]# systemctl restart nginx.service
浏览器验证
- 使用浏览器访问http://www.qz.com/50-50-50.html或者http://www.qz.com/50-100-50.html则会跳转到http://www.qz.com页面
基于目录下所有php结尾的文件跳转
- 要求访问hhtp://www.qz.com/upload/5514.php时跳转到首页
[root@localhost /]# vim /usr/local/nginx/conf/nginx.conf
35 server {
36 listen 80;
37 server_name www.qz.com;
38
39 charset utf-8;
40 access_log /var/log/nginx/www.qz.com-access.log;
41
42 location ~* /upload/.*\.php$ {
43 rewrite (.+) http://www.qz.com permanent;
44 }
45 location / {
46 root html;
47 index index.html index.htm;
48 }
[root@localhost /]# systemctl restart nginx.service
浏览器验证
- 使用浏览器访问hhtp://www.qz.com/upload/5514.php时跳转到http://www.qz.com页面
基于一条最普通的url请求的跳转
- 要求访问一个具体的页面,例如:http://www.qz.com/qwe/5514.html时跳转到首页
[root@localhost /]# vim /usr/local/nginx/conf/nginx.conf
35 server {
36 listen 80;
37 server_name www.qz.com;
38
39 charset utf-8;
40 access_log /var/log/nginx/www.qz.com-access.log;
41
42 location ~* /qwe/5514.html {
43 rewrite (.+) http://www.qz.com permanent;
44 }
45 location / {
46 root html;
47 index index.html index.htm;
48 }
[root@localhost /]# systemctl restart nginx.service
浏览器验证
- 使用浏览器访问hhtp://www.qz.com/qwe/5514.html时跳转到http://www.qz.com页面