十三、将请求的URL基于正则表达式进行rewrite重写
使用Tengine提供的全局变量或自定义变量,结合正则表达式和标志位实现URL重写以及重定向,通常可以实现http跳转至https、域名1跳转至域名2、URL1跳转至URL2等功能。
1、 Perl兼容正则表达式:
Ø .:匹配除换行符\n以外的任意单个字符
Ø ?:匹配之前的字符0次或1次
Ø +:匹配之前的字符至少1次
Ø *:匹配之前的字符任意次
Ø \d:匹配数字
Ø ^:匹配字符串的开始
Ø $:匹配字符串的结尾
Ø {m}:重复m次
Ø {m,}:重复至少m次
Ø {m,n}:重复至少m次,最多n次
Ø [a]:匹配单个字符a
Ø [a-z]:匹配a-z小写字母中的任意一个
Ø [^ ]:匹配任何不包括在指定字符集内的任意字符
Ø |:匹配 | 之前或之后的部分
Ø ():分组,组成一组用于匹配的实体,通常配合 | 使用。小括号()之间匹配的内容,可以在后面通过$1来引用,$2表示的是前面第二个()里的内容
2、 if:
if主要用来判断一些在rewrite语句中无法直接匹配的条件,比如检测文件存在与否
用法:if(条件) {…}
Ø 当if表达式中的条件为true时,执行if代码块中的语句
Ø 当表达式只是一个变量时,如果值为空或者任何以0开头的字符串都会当作false
Ø 直接比较内容时,使用=和!=
Ø 使用正则表达式匹配时,使用
² ~:区分大小写的模式匹配
² ~*:不区分大小写的模式匹配
² !~:区分大小写的模式不匹配
² !~*:不区分大小写的模式不匹配
Ø 使用-f、-d、-e、-x检测文件和目录
² -f和!-f用来判断文件是否存在
² -d和!-d用来判断目录是否存在
² -e和!-e用来判断文件和目录是否存在
² -x和!-x用来判断文件是否可执行
3、 return:用来直接设置http返回状态,比如403、404等。301、302不可用return返回,因为301和302不能简单的只返回状态码,还必须有重定向的URL
4、 break:用来立即停止rewrite检测
5、 rewrite:
四种flag标志位
Ø last:执行该rewrite规则后,停止处理后续的rewrite指令集,对于重写后的URL会重新匹配location
Ø break:执行该rewrite规则后,停止处理后续的rewrite指令集,不再进行location匹配
Ø redirect:重写完成之后会返回客户端302状态响应码(临时重定向),地址栏会显示跳转后的地址
Ø permanent:重写完成之后会返回客户端301(永久重定向),地址栏会显示跳转后的地址
示例1:
在server段中新增如下2个location(没有flag):
location /aaa.html {
rewrite "^/aaa.html$" /bbb.html;
rewrite "^/bbb.html$" /ddd.html;
}
location /bbb.html {
rewrite "^/bbb.html$" /ccc.html;
}
创建测试页:
# echo "aaa html" > /usr/local/tengine/html/aaa.html
# echo "bbb html" > /usr/local/tengine/html/bbb.html
# echo "ccc html" > /usr/local/tengine/html/ccc.html
# echo "ddd html" > /usr/local/tengine/html/ddd.html
# nginx -t # nginx -s reload
测试:# curl http://localhost/aaa.html
示例2:
在server段中新增如下2个location(flag为last):
location /aaa.html {
rewrite "^/aaa.html$" /bbb.html last;
rewrite "^/bbb.html$" /ddd.html;
}
location /bbb.html {
rewrite "^/bbb.html$" /ccc.html;
}
# nginx -t # nginx -s reload
测试:# curl http://localhost/aaa.html
解释:aaa.html --> bbb.html --> 由于flag为last,所以不会将bbb.html --> ddd.html --> 重新匹配bbb.html --> ccc.html
示例3:
在server段中新增如下2个location(flag为break):
location /aaa.html {
rewrite "^/aaa.html$" /bbb.html break;
rewrite "^/bbb.html$" /ddd.html;
}
location /bbb.html {
rewrite "^/bbb.html$" /ccc.html;
}
# nginx -t # nginx -s reload
测试:# curl http://localhost/aaa.html
解释:aaa.html --> bbb.html --> 由于flag为break,所以不再进行location匹配
示例4:
在server段中新增如下代码:
rewrite "^/aaa.html$" /bbb.html;
location /ccc.html {
rewrite "^/ccc.html$" /eee.html;
}
location /bbb.html {
rewrite "^/bbb.html$" /ccc.html;
rewrite "^/ccc.html$" /ddd.html;
}
# nginx -t # nginx -s reload
创建测试页:# echo "eee html" > /usr/local/tengine/html/eee.html
测试:# curl http://localhost/aaa.html
解释:首先执行server段内的rewrite指令,即aaa.html --> bbb.html --> ccc.html --> ddd.html
示例5:
在server段中新增如下代码:
rewrite "^/aaa.html$" /bbb.html;
rewrite "^/ccc.html$" /ddd.html;
location /bbb.html {
rewrite "^/bbb.html$" /ccc.html;
}
location /ddd.html {
rewrite "^/ddd.html$" /eee.html;
}
# nginx -t # nginx -s reload
测试:# curl http://localhost/aaa.html
解释:首先执行server段内的rewrite指令,即aaa.html --> bbb.html --> ccc.html,执行结果不受rewrite和location的位置顺序影响,即location匹配迭代总是先执行server段内的rewrite指令,再进行location匹配,执行location段内的rewrite指令
6、 全局变量:
$content_length:http请求头中的Content-length字段
$content_type:http请求头中的Content-Type字段
$document_root:当前请求在root指令中指定的值
$host:请求主机头字段,如果请求中没有Host行,则为服务器名称
$http_user_agent:客户端agent信息
$http_cookie:客户端cookie信息
$limit_rate:限制连接速率
$request_method:客户端请求方法,通常为GET或POST
$remote_addr:客户端IP地址
$remote_port:客户端端口
$remote_user:已经经过Auth Basic Module验证的用户名
$request_filename:当前请求的文件路径,由root或alias指令与URL请求生成
$scheme:请求使用的协议,比如http或者是https
$server_protocol:请求使用的协议版本,通常是HTTP/1.0或HTTP/1.1
$server_addr:服务器地址,在完成一次系统调用后可以确定这个值
$server_name:服务器名称
$server_port:请求到达服务器的端口号
$request_uri:包含请求参数的原始URL,不包含主机名,如:/foo/bar.php?arg=baz
$uri:不带请求参数的当前URL,$uri不包含主机名,如:/foo/bar.html
$document_uri:与$uri相同
7、 生产环境常见案例:
(1)禁止使用curl命令下载文件:
未配置前:# curl http://localhost/index.html
在server段中新增如下代码:
if ($http_user_agent ~ curl) {
return 403;
}
# nginx -t # nginx -s reload
测试:# curl http://localhost/index.html
(2)基于浏览器实现分离:
在server段中新增如下代码:
if ($http_user_agent ~ Firefox){
rewrite ^/(.*)$ /firefox/$1 break;
}
if ($http_user_agent ~ MSIE){
rewrite ^/(.*)$ /msie/$1 break;
}
if ($http_user_agent ~ Edge){
rewrite ^/(.*)$ /edge/$1 break;
}
if ($http_user_agent ~ Chrome){
rewrite ^/(.*)$ /chrome/$1 break;
}
创建测试页:
# mkdir -pv /usr/local/tengine/html/{firefox,msie,edge,chrome}
# echo "Firefox html" > /usr/local/tengine/html/firefox/index.html
# echo "MSIE html" > /usr/local/tengine/html/msie/index.html
# echo "Edge html" > /usr/local/tengine/html/edge/index.html
# echo "Chrome html" > /usr/local/tengine/html/chrome/index.html
# nginx -t # nginx -s reload
测试:
使用火狐浏览器访问:http://192.168.1.222/index.html
使用IE 9浏览器访问:http://192.168.1.222/index.html
使用Edge浏览器访问:http://192.168.1.222/index.html
备注:Windows 10中内置的浏览器为Microsoft Edge,之前为IE
使用谷歌浏览器访问:http://192.168.1.222/index.html
使用未做规则匹配的360浏览器访问:http://192.168.1.222/index.html
访问日志格式如下:
(3)实现访问http://blog.qiuyue.com时自动跳转到http://www.qiuyue.com/blog
server {
listen 80;
server_name blog.qiuyue.com;
rewrite ^/(.*)$ http://www.qiuyue.com/blog/$1 permanent;
location / {
root html/blog;
index index.html index.html;
}
}
server {
listen 80;
server_name www.qiuyue.com;
location / {
root html/www;
index index.html index.html;
}
}
创建测试页:
# mkdir -pv /usr/local/tengine/html/{blog,www/blog}
# echo "http://blog.qiuyue.com/index.html" > /usr/local/tengine/html/blog/index.html
# echo "http://www.qiuyue.com/blog/index.html" > /usr/local/tengine/html/www/blog/index.html
# nginx -t # nginx -s reload
修改本地Windows 10系统的hosts文件:
C:\Windows\System32\drivers\etc\hosts,末尾新增代码:
192.168.1.222 www.qiuyue.com blog.qiuyue.com
测试:
在浏览器中访问http://blog.qiuyue.com时自动跳转到http://www.qiuyue.com/blog
回车后自动跳转:
(4)实现访问http://www.qiuyue.com/bbs时自动跳转到http://bbs.qiuyue.com
server {
listen 80;
server_name www.qiuyue.com;
rewrite ^/bbs/(.*)$ http://bbs.qiuyue.com/$1 permanent;
location / {
root html/www;
index index.html index.html;
}
}
server {
listen 80;
server_name bbs.qiuyue.com;
location / {
root html/bbs;
index index.html index.html;
}
}
创建测试页:
# mkdir -pv /usr/local/tengine/html/{bbs,www/bbs}
# echo "http://bbs.qiuyue.com/index.html" > /usr/local/tengine/html/bbs/index.html
# echo "http://www.qiuyue.com/bbs/index.html" > /usr/local/tengine/html/www/bbs/index.html
# nginx -t # nginx -s reload
修改本地Windows 10系统的hosts文件:
C:\Windows\System32\drivers\etc\hosts,末尾新增代码:
192.168.1.222 www.qiuyue.com bbs.qiuyue.com
测试:
在浏览器中访问http://www.qiuyue.com/bbs时自动跳转到http://bbs.qiuyue.com
回车后自动跳转:
(5)实现访问qiuyue.com时自动跳转到www.qiuyue.com
server {
listen 80;
server_name qiuyue.com;
rewrite ^/(.*)$ http://www.qiuyue.com/$1 permanent;
location / {
root html;
index index.html index.html;
}
}
server {
listen 80;
server_name www.qiuyue.com;
location / {
root html;
index index.html index.html;
}
}
# nginx -t # nginx -s reload
修改本地Windows 10系统的hosts文件:
C:\Windows\System32\drivers\etc\hosts,末尾新增代码:
192.168.1.222 qiuyue.com www.qiuyue.com
测试:
在浏览器中访问qiuyue.com时自动跳转到www.qiuyue.com
回车后自动跳转:
(6)实现访问http://www.aaa.com时自动跳转到http://www.bbb.com
server {
listen 80;
server_name www.aaa.com;
rewrite ^/(.*)$ http://www.bbb.com/$1 permanent;
location / {
root html/aaa;
index index.html index.html;
}
}
server {
listen 80;
server_name www.bbb.com;
location / {
root html/bbb;
index index.html index.html;
}
}
创建测试页:
# mkdir -pv /usr/local/tengine/html/{aaa,bbb}
# echo "http://www.aaa.com/index.html" > /usr/local/tengine/html/aaa/index.html
# echo "http://www.bbb.com/index.html" > /usr/local/tengine/html/bbb/index.html
# nginx -t # nginx -s reload
修改本地Windows 10系统的hosts文件:
C:\Windows\System32\drivers\etc\hosts,末尾新增代码:
192.168.1.222 www.aaa.com www.bbb.com
测试:
在浏览器中访问http://www.aaa.com时自动跳转到http://www.bbb.com
回车后自动跳转: