rewrite详解

rewrite模块

        URI跟URL介绍
        什么是uri?统一标识符,拿www.abc.com/aw/wd/举例,那么rui就是/aw/wd/这部分数据(也有可能是图片,html网页,如果是伪静态的话,那就得看配置是啥玩意了
        什么是url?  统一定位符,还是拿www.abc.com/aw/wd/举例,那么整个www.abc.com/aw/wd/就是url        

        什么是rewrite?
        rewrite重写是由ngx_http_rewrite_module模块提供,主要是实现URI改写功能,并且此模块是Nginx默认安装的模块。通过rewrite,用户可以实现url重定向,根据regex规则来匹配内容跳转到replacement,结尾以flag标记。


        工作方式
        rewrite匹配默认是按照从上至下的顺序进行匹配,如果没有添加flag参数,直到把最后一个rewrite匹配完才终止,如果最后一个都没有匹配到内容则返回500,如果想要提前终止就得flag参数来帮忙实现。


       rewrite模块常见指令

if (条件) {} #设定条件,再进行重写
       set     #后面+值,可以给变量赋值
       return  #返回状态码信息,并且支持自定义信息
       rewrite #重写 (这个是重点)
       rewrite_log # rewrite日志

      语法
        rewrite regex(正则) replacement(替换)  flag(标识);中间以空格隔开

      常用正则

^     以什么开头                                          
$     以什么结尾 
*     匹配前面的字符0次或者多次               
+     匹配前面的字符1次或者多次 
?     匹配前面字符0次或者1次                     
.     匹配除“\n \t”之外的单个字符

(patten) 匹配括号内的patten(同时第一个() 就是$1 第二个是$2,$取值以()为分隔符)
[a-z0-9] 匹配里面的任意单个字符,区分大小写    
            
d      匹配任意数字
\S     匹配可见字符                                        
\s     匹配不可见字符
\w     匹配任意单词(可以是单个字符,字符串等等) ac bh ki js n r          
x|y    匹配x或则匹配y(任意一个) | 或 
\W     匹配任意符号(可以是单个,也可以是多个) ? \ + - == [ ] { } -- ()  

      flag参数
        last        结束当前所有rewrite指令,并且使用新的URI直接进行location匹配。
        break    结束当前所有rewrite指令,不参与任何匹配,并且把当前输出作为结果返回给用户,避免重复rewrite。
        注:在server模块匹配中使用last,而在location功能模块中使用break
        redirect(临时)   返回302临时重定向
        permanent(永久的)  永久返回301重定向 
       注:301跟302跳转输出结果是一样的,但是主要是针对搜索引擎的,搜索引擎看见你的数据是302跳转,默认是不抓取的,301是抓取的,具体原因的话,那就不清楚了,在生产环境中,一般是301用的多


    例子:      

        last   结束当前所有rewrite指令,并且使用新的RUI进行下轮location匹配(但是匹配是有范围的,只匹配location的内容,上限是10次,10次没有匹配到内容,则返回500 ,容易造成死循环)。如果新的RUI是资源地址,则直接返回资源地址。
        break    结束当前所有rewrite指令,不参与任何匹配(包括后续rewrite,其它location),并且把当前URI用来处理用户请求,可以避免重复rewrite。

示例1:last与break大致区别

server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;

   location ~ /break/ {
        rewrite /break/(.*) /test/$1 break; 
        return 200 jfnginx;
    }

    location ~ /last/ {
        rewrite /last/(.*) /test/$1 last;
        return 200  "last";
    }

    location ~ /test/ {
        rewrite /test/ /a.html;
    }

} 

注:根据break的特性,404是意料之中,return也是rewrite功能模块指令。

注:这个结果也是意料之中,根据last的特性,把/last 替换成 /test又开始了新一轮的location匹配,匹配到/test的内容取得具体资源地址,返回给用户

示例2:在server字段填写break,last与不填的区别

server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;

    rewrite /break /downlod/wget-log last;
    rewrite /break /downlod/wget-log.1;

    location ~ /break/ {
        rewrite /break/(.*) /downlod/jfnginx.txt break;
    }

}

注:经过反复测试在server字段的第一个rewrite重写规则只要指定具体RUI资源,那么就会返回当前资源,无论后面加不加参数都不会执行其他的rewrite指令及匹配location功能模块。

server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;

    rewrite /break /downlod/ break;
    rewrite /break /user/;

    location ~ /downlod/ {
        rewrite /downlod/(.*) /downlod/jfnginx.txt break;
    }

    location ~ /user/ {
        rewrite /user/(.*) /user/706342.html break;
    }

}

# curl ab.text.com/break/9289897df.html
jfnginx

注:经过3次测试(分别flag位置的参数设置为last,break,空),当server字段的rewrite的RUI指定是一个目录的时候,无论是后面有没有flag参数,都会根据RUI跳转,去匹配location功能模块,返回固定值。(一般在server字段需要强制跳转大部分是用permanent去处理)

示例3:在location功能模块测试breakt填写位置不同的结果展示

server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;

    location ~ /break/ {
        rewrite /break/(.*) /downlod/ brake;
    }

    location ~ /downlod/ {
        rewrite /downlod/(.*) /user/706342.html break;
    }

}

# curl ab.text.com/break/923us2u.html
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>
##################################################################
server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;

    location ~ /break/ {
        rewrite /break/(.*) /downlod/;
        break;
    }

    location ~ /downlod/ {
        rewrite /downlod/(.*) /user/706342.html break;
    }

}

# curl ab.text.com/break/9222ee2u.html
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

###################################################################
server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;

    location ~ /break/ {
        rewrite /break/(.*) /downlod/ break;
        return 200 "jfnginx \n";
    }

    location ~ /downlod/ {
        rewrite /downlod/(.*) /user/706342.html break;
    }

}

# curl ab.text.com/break/9222ee22wewu.html
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

注:根据上面的测试结果 break 是结束当前rewrite重写,无论后面还有没有rewrite或者是其它location模块都不匹配。last就不测试了,在示例1里面就有展示。

        redirect(临时)   返回302临时重定向

server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;

    location ~ / {
        rewrite ^/bc http://ab.text.com/b.html redirect;
    }


    permanent(永久的)  永久返回301重定向 

示例:
server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;

    location ~ / {
        rewrite ^/ac http://ab.text.com/a.html permanent;
    }

#跳转成功,但是做301或者302跳转的时候后面的内容一定要加协议,不然会把你跳转的内容当成一个文件去处理。301及301跳转是跳转至全新的内容,对访问方式以及就行了修改。

server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;
    rewrite_log on;

    location ~ ^/downlod/ {
        rewrite ^/downlod /downlod/jfnginx.txt;
        return 200 "jfnginx \n";
    }

return  #用于返回状态码信息,并且支持自定义信息了,并且return还有终止rewrite的作用

语法:
    return code [描述信息]; 示例:return 403;
    return code URL;    示例:return 301 https://ab.test.com/s/;
    return URL;         示例:return  https://ab.test.com/s/;


返回常见状态码:
403 
404
444    #比较特殊的状态码,返回这个的话,客户端是看不到状态码的。
301
302
及其他自定义状态码


示例:
    server {
        listen 80;
        server_name ab.text.com;
        index index1.html;
        root /data/www;

        location ~ /break/ {
            rewrite /break/(.*) /downlod/;
            return 200 "jfnginx \n";
        }

        location ~ /downlod/ {
            rewrite /downlod/(.*) /user/706342.html break;
        }

    }


    # curl ab.text.com/break/9222ee22wewu.html
    jfnginx 

注:根据上述结果测试,return跟break功能是差不多的,但是return可以接返回码及描述信息(此码与http协议码还是有区别的,这个码是属于自定义的)

error_page 返回错误

error_page指令是一个错误处理指令,核心功能就是多错误进行处理.
语法:error_page code ..[=[response]] uri;

示例:
    error_page 404 /404.html;    #只要是产生404就调整到 404.html,同时会继承404的状态码
    error_page 500 502 503 504 /50x.html;    #只要是 500,502,503,504报错就调整到 50x.html
    error_page 404 = /test/;    #只要是404就跳转到 /test/,此时返回状态码会修改为 200
    error_page 404 = /404.php   #只要是404就调转到 404.php,此时返回的状态为 200
    error_page 403 http://example.com/forbideen.html;    #只要是403就调整到固定页面
    error_page 404 = 301 http://example.com/example.html    #只要是404就跳转到后面地址,状态码为301

    注:有个说明就是 error_page 后面加不加等号区别就是:加等会,返回的状态码自动改为 200,不加就继承上次的状态,比如403,404等状态都会被继承

小干货:
在有的生产环境,你通过error_page做了404或者500等跳转,结果发现没有跳转,你不仿在当前server块开启如下指令:
    proxy_intercept_errors on;  #它会主动获取错误信息,使你的error_page跳转生效

if (条件) {}   #设定条件,再进行重写

语法:if (condition){...} 如果condition为真,则执行{...}的内容,condition有以下3种情况:

当条件为变量(自定义变量或系统变量)时,值为空或者任何以0开头的字符串都被当做flase.
直接比较变量值的时候用 = 或 !=
~ 为正则匹配 ~*不区分大小写匹配 !~区分大小写的不匹配
-e -f -d -x 跟正则的里面的是一个意思 加 ! 非的意思 也就是 不等于


# $request_filename指的是请问资源路劲, !-e 代表不存在
server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;

   if ( !-e $request_filename ) {
       rewrite (.*) /a.html;
   }
}
注:当请求的资源不存在的时候,全部转到a页面

# curl ab.text.com/break/9222ee22wewu.html
#这是a页面
是不是很意外?是不是很惊喜?这就是我的a页面。
    <!--引入b.html-->
    <!--# include file="b.html" -->

其它例子:
    #做防盗链,如果referer为空就禁止访问,注意if不支持逻辑或与逻辑与,需要多个逻辑判断得多个if组合一起
    if ($http_referer "") {
        return 403;    
    }

try-files 主要对没有匹配到的数据进行处理

语法:
try_files file ... uri;
try_files file ... =code;
适用字段:server, location
注:try_files 最后面是可以接uri或者源码的。

示例:
try_files $uri $rui/ =403;  
try_files $uri $rui/ /a.html;
try_files $uri $rui/ @user;    
#对进行域名访问的请求进行匹配,如果server没有数据则强制返回404。
#其中前2个$uri是匹配内部数据,只有最后那个参数才起到重定向的功能

#综合配置
server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;

    try_files $uri @user;

    location  @user{
        rewrite ^(.*) /a.html break;
    }
}

示例1:ssd.html文件并不存在
# curl ab.text.com/ssd.html            #访问结果直接跳转到a页面
#这是a页面
是不是很意外?是不是很惊喜?这就是我的a页面。
    <!--引入b.html-->
    <!--# include file="b.html" -->

示例2:ssdj.html 存在在根目录之下
# echo ssdj > ssdj.html
# ls
404.html  a.html  b.html  downlod  index1.html  ssdj.html  user
# curl ab.text.com/ssdj.html        #返回是当前页面的值
ssd

set指令 定义一个变量,并给变量赋值。变量的值可以为文本、变量或者变量的组合。set $var "hello world"  

使用环境:server,location,if 

server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;

   if ( !-e $request_filename ) {
       rewrite (.*) /downlod;
       set $ac "2200 \n";
       return 200 $ac;
   }
}


# curl ab.text.com/ssdsd
2200 

比如我需要做防盗链,只要ua(user-agent)为"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36"及referer为空的请求禁止访问。

server {
    listen 80;
    server_name ab.text.com;
    index index1.html;
    root /data/www;

    set $p 0;    #设置变量p,值为0
    if ($http_user_agent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36"){
        set ${p}1;    #如果上面的if执行成功,则再次设置变量p值为01,因为${p}是继承了上面那个$p的值。
    }

    if ($http_referer = ""){
        set ${p}2;    #如果上面的if执行成功,就再次赋值,此时p的值为012,${p}继承的是01,然后组合起来是012
    }

    if ($p = 012 ){
        return 403;    #最终判断,如果p的值为012,在代表上面的条件都匹配,我们就返回403
    }
       
}

#因为Nginx的if不支持逻辑或跟逻辑与,我们只能通过对变量赋值的方式,对用户的请求进行判断,如果符合要求则赋值,最终根据值进行判断是否返回403。
#当然上面的只是示例,比如还有做各种挑战的,rewrite啥的

常用变量:

$args:这个变量等于请求行中的参数,同$query_string
$request_filename:请求资源路劲 
$uri:不带请求参数的当前URI,$uri不包含主机名,如”/html/abc.html”
$host:请求主机头字段,否则为服务器名称。

Nginx大部分支持的变量:http://nginx.org/en/docs/varindex.html
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值