1、什么是Rewrite
Rewrite对称URL Rewrite,即URL重写,就是把传入Web的请求重定向到其他URL的过程。
-
URL Rewrite最常见的应用是URL伪静态化,是将动态页面显示为静态页面方式的一种技术。理论上,搜索引擎更喜欢静态页面形式的网页,搜索引擎对静态页面的评分一般要高于动态页面。所以,UrlRewrite可以让我们网站的网页更容易被搜索引擎所收录。
-
从安全角度上讲,如果在URL中暴露太多的参数,无疑会造成一定量的信息泄漏,可能会被一些黑客利用,对你的系统造成一定的破坏,所以静态化的URL地址可以给我们带来更高的安全性。
-
实现网站地址跳转,例如用户访问360buy.com,将其跳转到jd.com。例如当用户访问tianyun.com的80端口时,将其跳转到443端口。
2、Rewrite 相关指令
-
Nginx Rewrite 相关指令有 if 、rewrite、set、return
2.1、if 语句
-
应用环境:server,location
语法:
if (condition) { … }
if 可以支持如下条件判断匹配符号
~ 正则匹配 (区分大小写)
~* 正则匹配 (不区分大小写)
!~ 正则不匹配 (区分大小写)
!~* 正则不匹配 (不区分大小写)
-f 和!-f 用来判断是否存在文件
-d 和!-d 用来判断是否存在目录
-e 和!-e 用来判断是否存在文件或目录
-x 和!-x 用来判断文件是否可执行
在匹配过程中可以引用一些Nginx的全局变量----nginx中配置文件里面的参数都只能用“_”来连接和书写,不能用"-"连接,会报错。
$args 请求中的参数;
$document_root 针对当前请求的根路径设置值;
$host 请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名;
$limit_rate 对连接速率的限制;
$request_method 请求的方法,比如"GET"、"POST"等;
$remote_addr 客户端地址;
$remote_port 客户端端口号;
$remote_user 客户端用户名,认证用;
$request_filename 当前请求的文件路径名(带网站的主目录/usr/local/nginx/html/images/a.jpg)
$request_uri 当前请求的文件路径名(不带网站的主目录/images/a.jpg)
$query_string 与$args相同;
$scheme 用的协议,比如http或者是https
$server_protocol 请求的协议版本,"HTTP/1.0"或"HTTP/1.1";
$server_addr 服务器地址,如果没有用listen指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费);
$server_name 请求到达的服务器名;
$document_uri 与$uri一样,URI地址;
$server_port 请求到达的服务器端口号;
2.2、Rewrite flag
rewrite 指令根据表达式来重定向URI,或者修改字符串。可以应用于server,location, if 环境下,每行rewrite指令最后跟一个flag标记。
3、rewrite练习实例:
# 案例1:测试重写功能
server {
listen 80;
location /host {
if ($arg_url ~ "baidu") {
rewrite .* https://www.baidu.com break;
}
if ($arg_url ~ "taobao") {
rewrite .* https://www.taobao.com break;
}
}
}
#案例2本地解析host文件:http://www.testpm.com/a/1.html ==> http://www.testpm.com/b/2.html
server {
listen 80;
location /a/1.html {
rewrite /a/(.*) /b/2.html;
}
location /b {
root /usr/share/nginx/html/;
}
}
# 案例3 :http://www.testpm.com/2019/a/1.html ==> http://www.testpm.com/2018/a/1.html 访问2019网页将会定向到2018目录
server {
listen 80;
location /2019 {
rewrite /2019(.*)$ /2018$1;
}
location /2018 {
root /usr/share/nginx/html;
}
}
# 案例4: http://www.qf.com/a/1.html ==> http://jd.com
server {
listen 80;
location /a/1.html {
rewrite .* http://jd.com;
}
}
# 案例5:http://www.qf.com/a/1.html ==> http://jd.com/a/1.html
server {
listen 80;
location /a/1.html {
rewrite (/a/.*)$ http://jd.com/$1;
}
}
#案例6:http://www.tianyun.com/a/b/c ==> http://www.tianyun.com/a/b/c/
# $1: /a/b
# $2: c
# http://$host$1$2$3/ 在访问目录后添加/ (如果目录后已有/,则不加/)
server {
listen 80;
location /a {
if ( -d $request_filename ) {
rewrite ^(.*)([^/])$ http://$host$request_uri/ permanent;
}
root /usr/share/nginx/html;
}
}
#案例7: http://www.tianyun.com/login/tianyun.html ==> http://www.tianyun.com/reg/login.html?user=tianyun
server {
listen 80;
location /login {
rewrite ^/login/(.*).html /reg/login.html?user=$1;
}
location /reg {
root /usr/share/nginx/html;
}
}
#案例8:http://www.tianyun.com/qf/11-22-33/1.html ==> http://www.tianyun.com/qf/11/22/33/1.html
server {
listen 80;
location /qf {
root /usr/share/nginx/html;
rewrite ^/qf/(.*)-(.*)-(.*)/(.*)$ /qf/$1/$2/$3/$4 break;
}
}
# break 练习
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/last.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /break/ {
root /usr/share/nginx/html;
rewrite .* /test/break.html break;
}
location /last/ {
root /usr/share/nginx/html;
rewrite .* /test/last.html break;
}
location /test/ {
root /usr/share/nginx/html;
rewrite .* /test/test.html break;
}
}
#匹配不同的搜索方式:
server {
listen 80;
location /abc {
return 302 https://www.baidu.com;
}
location ~ /abc {
return 302 https://www.taobao.com;
}
location ^~ /abc/ {
return 302 https://www.jd.com;
}
location ~* /ABC {
return 302 https://www.pingduoduo.com;
}
location = /abc {
return 302 https://www.vip.com;
}
}
# return用法,直接跳转到给的最终页面,前面加状态码,可以观察是否跳转成功。
server {
listen 80;
location / {
return 200 www.baidu.com;
}
}
#案例9:#http://alice.testpm.com ==> http://www.testpm.com/alice
#http://jack.testpm.com ==> http://www.testpm.com/jack
server {
listen 80;
location / {
if ($host ~ www.testpm.com) {
break;
}
if ($host ~ ^(.*).testpm.com) {
set $user $1;
rewrite .* http://www.testpm.com/$user;
}
rewrite .* http://www.testpm.com/$1;
}
location /alice {
root /opt/web;
index index.html;
}
location /jack {
root /opt/web;
index index.html;
}
}
4、set 指令是用于定义一个变量,并且赋值
编辑配置文件:
server {
listen 80;
server_name www.testpm.com;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
if ( $host ~* ^www.testpm.com$) { #如果是www开头,那么直接跳出本次if.
break;
}
if ( $host ~* "^(.*)\.testpm\.com$" ) { #如果网址行匹配的是其他内容开头,则使用set赋值,$user=$1,输入的第一个参数。
set $user $1;
rewrite .* http://www.testpm.com/$user permanent(永久跳转302);
}
}
location /jack {
root /usr/share/nginx/html;
index index.html index.hml;
}
location /alice {
root /usr/share/nginx/html;
index index.html index.hml;
}
}
5、return 指令用于返回状态码给客户端
例10:80 ======> 443 :80转443端口
server {
listen 80;
server_name www.chaosaigc.com;
access_log /var/log/nginx/http_access.log main;
return 443 https://www.chaosaigc.com$request_uri;
}
6、last、break 练习
[root@localhost test]# cat /etc/nginx/conf.d/last_break.conf
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/last.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /break/ {
root /usr/share/nginx/html;
rewrite .* /test/break.html break;
}
location /last/ {
root /usr/share/nginx/html;
rewrite .* /test/last.html break;
}
location /test/ {
root /usr/share/nginx/html;
rewrite .* /test/test.html break;
}
}
注意:
-
last 标记在本条 rewrite 规则执行完后,会对其所在的 server { … } 标签重新发起请求;
-
break 标记则在本条规则匹配完成后,停止匹配,不再做后续的匹配;
-
使用 alias 指令时,必须使用 last;
-
使用 proxy_pass 指令时,则必须使用break。