当前位置: 首页 > 工具软件 > ngx_php > 使用案例 >

nginx ngx_http_rewrite_module 模块填坑小记

太叔飞翰
2023-12-01

在使用rewrite模块进行uri重写时,得先补充几个知识点

nginx常用的变量

推荐给nginx安装一个Echo Module,能够非常方便的将我们的请求产生的变量打印出来,nginx选用nginx/1.11.10版本最好,再高一点的版本编译Echo模块会报错。nginx编译成功后添加如下配置。

 server { 
        root /usr/local/nginx/html/;
        listen 80;
        server_name test.com;
        access_log  logs/test.com.access.log  main;
        error_log  logs/test.error.log;
        location /path/ {
            echo "args:" $args;
            echo "query_string:" $query_string;
            echo "uri:" $uri;
            echo "host:" $host;
            echo "request_filename:" $request_filename;
            echo "request_uri:" $request_uri;
        } 
 }

curl http://test.com/path/file.php?a=1&b=2
args: a=1&b=2
query_string: a=1&b=2
uri: /path/file.php
host: test.com
request_filename: /usr/local/nginx/html/path/file.php
request_uri: /path/file.php?a=1&b=2

rewrite 指令

语法: rewrite regex replacement [flag]
1,第一个注意的地方就是 regex正则表达是的匹配对象是上文的$uri变量,即不带host和参数的。

rewrite  /index.html\?(a=1)  index.php?$1 last; 
curl test.com/index.html?a=1 是匹配不到不会跳转的

2,默认的情况下请求的参数会跟在replacement的后面,如果重定向后的地址想省略原始请求参数在替换的replacement 后面加上?即可

#请求 test.com/post-21.html?a=1&b=2 会被重定向为 test.com/post.php?page=21&a=1&b=2
rewrite  /post-(\d+).html /post.php?page=&1 permanent;
#如果想去掉重定向后的a=1&b=2参数,在replacement加上?
rewrite  /post-(\d+).html /post.php?page=&1? permanent;

3,flag:确定重定向的动作
last:停止下面的执行下面的ngx_http_rewrite_module 指令集(包括rewrite,if,return,set这些指令),并开始用重写后新的uri去匹配location。
break:停止下面的执行下面的ngx_http_rewrite_module 指令集。
redirect:服务器发起302临时重定向请求重写的地址
permanent:服务器发起301永久重定向请求重写的地址

last 和 break 当出现在location 之外时,两者的作用是一致的没有任何差异。当出现在location 内部时,两者就存在了差异。
last: 使用了last 指令,rewrite 后会跳出location 作用域,重新开始再走一次刚刚的行为
break: 使用了break 指令,rewrite后不会跳出location 作用域。它的生命也在这个location中终结。
非ngx_http_rewrite_module 任然可以执行,比如proxy_pass ,fastcgi_pass

对用户使用浏览器访问的url来说,last,break都不会改变地址栏的地址。并且不执行后续的rewrite指令,但是last会开始用重写后新的uri去匹配location,如何理解?下面这个例子可以帮助理解。

rewrite /test/.* /index.html break;
location /test/ {
    return 508;
}  
location /break/ {  
    rewrite ^/break/(.*) /test/$1 break;
    return 402;
}
location /last/ {  
    rewrite ^/last/(.*) /test/$1 last;
    return 403;
}

请求: http://test.com/break/*
返回:404
请求: http://test.com/last/*
返回:508
请求: http://test.com/test/*
返回:200 (返回index.html)
原因:根据上述内容,break与last都停止处理后续rewrite指令集,不同之处在与last会重新发起新的请求,而break不会。当请求break时,如匹配内容存在的话,可以直接请求成功,返回200;而如果请求内容不存在,则返回404。当请求为last的时候,会对重写的新uri重新发起请求,只是重新查找location匹配,如上例则返回508。
4,location与rewrite一些想法

4.1 $uri 与 $request_filename在last,break改变uri后重新查找匹配是变化,但是$request_uri不会变。接着
上例,在请求: http://test.com/last/* 变成新的uri后重新查找时:
uri: /test/*
request_filename: /usr/local/nginx/html/test/*
request_uri: /last/* (不变)
4.2 location 匹配的是$uri,但是rewrite匹配的是request_uri
4.3 rewrite 匹配的优先级高于location
 类似资料: