Web架构之Nginx重定向Rewrite
1、Rewrite 简介
和Apache等Web服务软件一样,Nginx Rewrite的主要功能是实现URL的地址重写,以及重定向Nginx的Rewrite规则需要PCRE软件的支持,通过Perl兼容正则表达式语法进行规则的匹配
Rewrite使用场景:
1.URL访问跳转:支持开发设计,页面跳转,兼容性支持,展示效果
2.SER优化:依赖于url路径,以便支持搜索引擎录入
3.维护:后台维护,流量转发等
4.安全:伪静态,真是动态页面进行伪装
Rewrite 语法
Syntax:rewrite regex replacement {flag};
default:none
Context:server、location、if
// 所有的请求转发至/pages/maintain.html
rewrite ^(.*)$ /pages/maintain.html break;
正则表达式:
表达式 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
? | 重复0次或1次 |
+ | 重复1次或更多次 |
* | 匹配所有 |
\d | 匹配数字 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结尾 |
重复n次 | |
重复n次或更多次 | |
[c] | 匹配单个字符c |
[a-z] | 匹配a-z小写字母的任意一个 |
正则表达式中特殊字符
// \ 转义字符
rewrite index\.php$ /pages/maintain.html break;
// ()用于匹配括号之间的内容, 通过$1,$2调用
if ($http_user_agent ~ Chrome){
rewrite ^(.*)$ /chrome/$1 break;
}
正则表达式终端测试工具
$ yum install -y pcre-tools
$ pcretest
PCRE version 8.32 2012-11-30
re> /(\d+)\.(\d+)\.(\d+)\.(\d+)/
data> 10.0.0.7
0: 10.0.0.7
1: 10
2: 0
3: 0
4: 7
Rewrite标记Flag:
flag | 说明 |
---|---|
last | 停止rewrite检测 |
break | 停止rewrite检测 |
redirect | 返回302临时重定向,地址栏会显示跳转后的地址 |
permanent | 返回301永久重定向,地址栏会显示跳转后的地址 |
对比flag中break和last:
$ vim /etc/nginx/conf.d/rewrite.conf
server {
listen 80;
server_name localhost;
root /soft/code;
location ~ ^/break {
rewrite ^/break /test break;
}
location ~ ^/last {
rewrite ^/last /test last;
}
location /test {
default_type application/json;
return 200 '{"status":"success"}';
}
}
测试break
$ curl 127.0.0.1/break/xx.html
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.16.1</center>
</body>
</html>
测试last
$ curl 127.0.0.1/last
{"status":"success"}
last 与 break 对比总结:
1.last:会新建立一个请求, 所以会重新进行匹配
2.break:跳出rewrite阶段,不会在匹配。
对比flag中redirect和permanent:
[root@lb01 /]# cat /application/nginx/conf/extra/rewrite.conf
server {
listen 80;
server_name localhost;
root /soft/code;
location ~ ^/jason {
rewrite ^/jason http://www.baidu.com redirect; # 临时重定向
# rewrite ^/jason http:// www.baidu.com permanent; # 永久重定向
}
}
2、Rewrite 应用场景
可以调整用户浏览的URL
为了让搜索引擎收录网站内容及用户体验更好
网站换新域名后,让旧的域名的访问跳转到新的域名上
2.1、基于uri做rewrite
正常访问: 127.0.0.1/course-11-22-33.html
改写后: 127.0.0.1/course/11/22/course_33.html
1.环境准备
$ mkdir /soft/code/course/11/22/ -p
$ echo "<h1>Nginx</h1>" > /soft/code/course/11/22/course_33.html
2.修改nginx配置文件
$ vim /etc/nginx/conf.d/rewrite.conf
server {
listen 80;
root /soft/code;
index index.html;
location / {
rewrite_log on;
error_log /var/log/nginx/rewrite.log notice;
rewrite ^/course-(\d+)-(\d+)-(\d+).html /course/$1/$2/course_$3.html break;
}
}
3.测试结果
$ curl 127.0.0.1/course-11-22-33.html
<h1>Nginx</h1>
// 截一段rewrite日志
2020/03/14 14:21:24 [notice] 2432#2432: *53 rewritten data: "/course/11/22/course_33.html", args: "", client: 127.0.0.1, server: , request: "GET /course-11-22-33.html HTTP/1.1", host: "127.0.0.1"
2.2、基于http请求头做rewrite
可以根据http请求头的变量来匹配做rewrite
if ($http_user_agent ~* "Chrome") {
rewrite ^/nginx http://www.baidu.com/index.html redirect;
}
别名和Rewrite的区别:
1)用别名效率高,但是看不到改过的域名
2)用Rewrite 301跳转的话,能看到新的域名,但是需要再次发送HTTP请求
3、Rewrite 案例
3.1、案例一
输入:127.0.0.1/jason-2018-11-15_book/index.html
跳转:127.0.0.1/jason/2018/11/15_book/index.html
1.环境准备
$ mkdir /soft/code/jason/2018/11/15_book/ -p
$ echo "book" > /soft/code/jason/2018/11/15_book/index.html
2.修改nginx配置文件
$ cat /etc/nginx/conf.d/rewrite.conf
server {
listen 80;
root /soft/code;
index index.html;
location / {
index index.html;
rewrite_log on;
error_log /var/log/nginx/rewrite.log notice;
rewrite ^/jason-(\d+)-(\d+)-(\d+)_book/index.html /jason/$1/$2/$3_book/index.html break;
}
}
3.测试结果
$ curl 127.0.0.1/jason-2018-11-15_book/index.html
book
// 截一段rewrite日志
2020/03/14 14:29:01 [notice] 3371#3371: *58 "^/jason-(\d+)-(\d+)-(\d+)_book/index.html" matches "/jason-2018-11-15_book/index.html", client: 127.0.0.1, server: , request: "GET /jason-2018-11-15_book/index.html HTTP/1.1", host: "127.0.0.1"
2020/03/14 14:29:01 [notice] 3371#3371: *58 rewritten data: "/jason/2018/11/15_book/index.html", args: "", client: 127.0.0.1, server: , request: "GET /jason-2018-11-15_book/index.html HTTP/1.1", host: "127.0.0.1"
3.2、案例二
输入:127.0.0.1/jason-2018-12-29_word/xxx.html
跳转:127.0.0.1/jason/2018/12/29_word/xxx.html
1.环境准备
$ mkdir /soft/code/jason/2018/12/29_word/ -p
$ echo "word1" > /soft/code/jason/2018/12/29_word/1.html
$ echo "word2" > /soft/code/jason/2018/12/29_word/2.html
$ echo "word3" > /soft/code/jason/2018/12/29_word/3.html
2.修改nginx配置文件
$ cat /etc/nginx/conf.d/rewrite.conf
server {
listen 80;
root /soft/code;
index index.html;
location / {
index index.html;
rewrite_log on;
error_log /var/log/nginx/rewrite.log notice;
rewrite ^/jason-(\d+)-(\d+)-(\d+)_word/(.*)$ /jason/$1/$2/$3_word/$4 break;
}
}
3.测试结果
$ curl 127.0.0.1/jason-2018-12-29_word/1.html
word1
$ curl 127.0.0.1/jason-2018-12-29_word/2.html
word2
$ curl 127.0.0.1/jason-2018-12-29_word/3.html
word3
// 截一段rewrite日志
2020/03/14 14:32:14 [notice] 3385#3385: *65 "^/jason-(\d+)-(\d+)-(\d+)_word/(.*)$" matches "/jason-2018-12-29_word/1.html", client: 127.0.0.1, server: , request: "GET /jason-2018-12-29_word/1.html HTTP/1.1", host: "127.0.0.1"
2020/03/14 14:32:14 [notice] 3385#3385: *65 rewritten data: "/jason/2018/12/29_word/1.html", args: "", client: 127.0.0.1, server: , request: "GET /jason-2018-12-29_word/1.html HTTP/1.1", host: "127.0.0.1"
2020/03/14 14:32:15 [notice] 3385#3385: *66 "^/jason-(\d+)-(\d+)-(\d+)_word/(.*)$" matches "/jason-2018-12-29_word/2.html", client: 127.0.0.1, server: , request: "GET /jason-2018-12-29_word/2.html HTTP/1.1", host: "127.0.0.1"
2020/03/14 14:32:15 [notice] 3385#3385: *66 rewritten data: "/jason/2018/12/29_word/2.html", args: "", client: 127.0.0.1, server: , request: "GET /jason-2018-12-29_word/2.html HTTP/1.1", host: "127.0.0.1"
2020/03/14 14:32:16 [notice] 3385#3385: *67 "^/jason-(\d+)-(\d+)-(\d+)_word/(.*)$" matches "/jason-2018-12-29_word/3.html", client: 127.0.0.1, server: , request: "GET /jason-2018-12-29_word/3.html HTTP/1.1", host: "127.0.0.1"
2020/03/14 14:32:16 [notice] 3385#3385: *67 rewritten data: "/jason/2018/12/29_word/3.html", args: "", client: 127.0.0.1, server: , request: "GET /jason-2018-12-29_word/3.html HTTP/1.1", host: "127.0.0.1"
4、Rewrite额外补充
Rewrite 匹配优先级:
1.执行server块的rewrite指令
2.执行location匹配
3.执行选定的location中的rewrite
Rewrite 优雅书写:
server {
listen 80;
server_name www.bgx.com bgx.com;
if ($http_host = nginx.org){
rewrite (.*) http://www.bgx.com$1;
}
}
# 改良版
server {
listen 80;
server_name bgx.com;
rewrite ^ http://www.bgx.com$request_uri?;
}
server {
listen 80;
server_name www.bgx.com;
}