rewrite语法
| Syntax: | rewrite regex replacement [flag]; |
| -------- | --------------------------------- |
| Default: | — |
| Context: | server, location, if |
//所有请求转发到/pages/maintain.html
rewrite ^(.*)$ /pages/maintain.html break;
正则表达式
字符 | 描述 |
---|---|
将后面接着的字符标记为一个特殊字符或者一个原义字符或一个向后引用 | |
^ | 匹配输入字符串的起始位置 |
$ | 匹配输入字符串的结束位置 |
* | 匹配前面的字符0次或者多次 |
+ | 匹配前面字符串1次或者多次 |
? | 匹配前面字符串的0次或者1次 |
. | 匹配除“ ”之外的所有单个字符 |
d | 匹配数字 |
{n} | 重复n次 |
{n,} | 重复n次或者更多次 |
[c] | 匹配单个字符c |
[a-z] | 匹配a到z小写字母的任意一个 |
(pattern) | 匹配括号内的pattern |
正则表达式中特殊字符
转义字符
rewrite index.PHP$ /pages/maintain.html break;
()用于匹配括号之间的内容 通过$1$2调用
if ($http_user_agent ~ Chrome) {
rewrite ^(.*)$ /chrome/$1 break;
}
正则表达式终端测试工具
[root@RainGod ~]# yum install pcre-tools
[root@RainGod ~]# pcretest
PCRE version 8.32 2012-11-30
re> /(d+).(d+).(d+).(d+)/
data> 192.168.1.1
0: 192.168.1.1
1: 192
2: 168
3: 1
4: 1
data> 222.173.94.214
0: 222.173.94.214
1: 222
2: 173
3: 94
4: 214
data>
rewrite 最后一项flag参数:
标记符号 | 说明 |
---|---|
last | 本条规则匹配完成后继续向下匹配新的location URI规则 |
break | 本条规则匹配完成后终止,不在匹配任何规则 |
redirect | 返回302临时重定向 |
permanent | 返回301永久重定向 |
break last 对比
nginx配置last
server {
listen 80;
server_name wqy.test.com;
access_log logs/wqy-test-com/access.log;
location ^~ /aaa {
rewrite ^/aaa/(.*) /bbb/$1 last;
root /opt/tmp/wqy/test;
}
location ^~ /bbb {
return 200 "hello world
";
}
}
测试结果
#curl -s http://wqy.test.com/aaa/index.html -x 127.0.0.1:80
hello world
#curl -s http://wqy.test.com/bbb/index.html -x 127.0.0.1:80
hello world
url由重写前的http://wqy.test.com/aaa/index.html变为http://wqy.test.com/bbb/index.html,重新进行location匹配后,匹配到第二个location条件,所以请求url得到的响应是hello wold
测试结论
配置rewrite last时,请求跳出当前location,进入server块,重新进行location匹配,超过10次匹配不到报500错误。客户端的url不变
配置rewrite break时
nginx配置
server {
listen 80;
server_name wqy.test.com;
access_log logs/wqy-test-com/access.log;
location ^~ /aaa {
rewrite ^/aaa/(.*) /bbb/$1 break;
root /opt/tmp/wqy/test;
}
location ^~ /bbb {
return 200 "hello world
";
}
}
测试结果
#curl -s http://wqy.test.com/aaa/index.html -x 127.0.0.1:80
bbb
#curl -s http://wqy.test.com/bbb/index.html -x 127.0.0.1:80
hello world
url由重写前的http://wqy.test.com/aaa/index.html变为http://wqy.test.com/bbb/index.html,nginx按照重写后的url进行资源匹配,匹配到的资源文件是/opt/tmp/wqy/test/bbb/index.html,所以请求url得到的响应就是/opt/tmp/wqy/test/bbb/index.html文件中的内容:bbb。
测试结论
配置rewrite break时,请求不会跳出当前location,但资源匹配会按照重写后的url进行,如果location里面配置的是proxy_pass到后端,后端服务器收到的请求url也会是重写后的url。客户端的url不变。
redirect permanent
rewrite ^(.*)$ https://${server_name}$1 permanent; 永久跳转 京东 浏览器缓存后不会向服务器发送数据确认请求
rewrite ^(.*)$ https://${server_name}$1 redirect; 临时跳转 浏览器每次请求后都会向服务器发送数据确认请求
常见跳转示例情况测试说明
练习1):用户访问/abc/1.html实际上真实访问是/ccc/bbb/2.html
#http://www.oldboy.com/abc/1.html ==> http://www.oldboy.com/ccc/bbb/2.html
第一里程:准备真实的访问路径
[root@web03 ~]# mkdir /code/ccc/bbb -p
[root@web03 ~]# echo "ccc_bbb_2" > /code/ccc/bbb/2.html
第二个里程:Nginx跳转配置
[root@web03 conf.d]# cat ccbb.conf
server {
listen 80;
location / {
root /html/www;
index index.html;
}
location /abc/ {
rewrite (.*) /ccc/bbb/2.html redirect;
#return 302 /ccc/bbb/2.html;
}
}
第三个里程:重启Nginx服务
[root@web03 ~]# systemctl restart nginx
练习2):用户访问/2018/ccc/bbb/2.html实际上真实访问是/2014/ccc/bbb/2.html
#http://www.oldboy.com/2018/ccc/bbb/2.html ==> http://www.oldboy.com/2019/ccc/bbb/2.html
第一次访问网站:
http://www.oldboy.com/2018/ccc/bbb/2.html --> 跳转
第二次访问网站:
http://www.oldboy.com/2019/ccc/bbb/2.html
第一个里程:准备真实的访问路径
[root@web03 ~]# mkdir /html/www/2019/ccc/bbb -p
[root@web03 ~]# echo "2019_ccc_bbb_2" > /html/www/2019/ccc/bbb/2.html
第二个里程:Nginx跳转配置
[root@web03 conf.d]# cat www.conf
server {
listen 80;
server_name www.oldboy.com;
location / {
root /html/www;
index index.html;
}
location /2018 {
rewrite ^/2018/(.*)$ /2019/$1 redirect;
}
}
第三个里程:重启Nginx服务
[root@web03 ~]# systemctl restart nginx
练习3):用户访问/test目录下任何内容, 实际上真实访问是http://www.oldboy.com
location /test {
rewrite (.*) http://www.oldboy.com redirect;
}
练习4):用户访问course-11-22-33.html实际上真实访问是/course/11/22/33/course_33.html
#http://www.oldboy.com/course-11-22-33.html ==> http://www.oldboy.com/course/11/22/33/course_33.html
第一个里程 准备真实的访问路径
[root@web03 ~]# mkdir /html/www/course/11/22/33/ -p
[root@web03 ~]# echo "docs.etiantian.org" > /html/www/course/11/22/33/course_33.html
第二个里程 Nginx跳转配置
[root@web03 conf.d]# cat www.conf
server {
listen 80;
server_name www.oldboy.com;
root /html/www;
index index.html;
location / {
#灵活rewrite ^/course-(.*)-(.*)-(.*).html$ /course/$1/$2/$3/course_$3.html redirect;
#固定rewrite ^/course-(.*) /course/11/22/33/course_33.html redirect;
}
第三个里程 重启Nginx服务
[root@web03 ~]# systemctl restart nginx
例5:将http请求,跳转至https ???
server {
listen 80;
server_name oldboy.com;
rewrite ^(.*) https://$server_name$1 redirect;
#return 302 https://$server_name$request_uri; ???
}
server {
listen 443;
server_name oldboy.com;
ssl on;
}
终极测验:
a 访问oldboy.com/oldboy.jpg ---> www.oldboy.com/oldboy.jpg 临时
第一个历程:准备环境
将oldboy.jpg --- 站点目录
第二个历程:编写配置文件:
server {
listen 80;
server_name www.oldboy.com;
root /html/www;
index index.html;
rewrite ^/(.*) http://www.oldboy.com/$1 redirect;
}
打破循环问题:
第一种方式:多个server配置
server {
listen 80;
server_name oldboy.com;
rewrite ^/(.*) http://www.oldboy.com/$1 redirect;
}
server {
listen 80;
server_name www.oldboy.com;
root /html/www;
index index.html;
}
第二种方式:打破循环 if 内置变量
server {
listen 80;
server_name www.oldboy.com;
root /html/www;
index index.html;
if ($host ~ ^oldboy.com) {
rewrite ^/(.*) http://www.oldboy.com/$1 redirect;
}
}
nginx常用内置变量:
$host 记录请求报文请求主体的host信息
$server_name 当前用户配置server_name的域名信息
$request_filename 当前请求的文件路径名(带网站的主目录/html/www/images/test.jpg)
$request_uri 当前请求的文件路径名(不带网站的主目录/images/test.jpg)
$scheme 用的协议,比如http或者https
第三个历程:配置DNS解析
10.0.0.7 oldboy.com www.oldboy.com
b 访问www.etiantian.org ---> www.oldboy.com 永久
第一个历程:准备环境
将oldboy.jpg --- 站点目录
第二个历程:编写配置文件:
server {
listen 80;
server_name www.oldboy.com;
root /html/www;
index index.html;
if ($host ~ www.etiantian.org) {
rewrite ^/(.*) http://www.oldboy.com/$1 redirect;
}
}
第三个历程:主配置文件编写
include /etc/nginx/conf.d/www.conf
include /etc/nginx/conf.d/*.conf;
第四个历程:配置DNS解析
10.0.0.7 oldboy.com www.oldboy.com www.etiantian.org