Nginx “邪恶” rewrite
概述
本文主要针对nginx rewrite指令困惑的地方进行讲解,中间会涉及部分原理部分,我尽量用通俗易懂的语言来形容
功能讲解
大致流程
The ngx_http_rewrite_module
module directives are processed in the following order:
the directives of this module specified on the server level are executed sequentially;
repeatedly:
a location is searched based on a request URI;
the directives of this module specified inside the found location are executed sequentially;
the loop is repeated if a request URI was rewritten, but not more than 10 times.
涉及phase
NGX_HTTP_SERVER_REWRITE_PHASE,
NGX_HTTP_FIND_CONFIG_PHASE,
NGX_HTTP_REWRITE_PHASE,
NGX_HTTP_POST_REWRITE_PHASE,
环境:
/aaa内容aaa
/bbb内容bbb
Example 1:
server {
listen 80 ;
location /aaa {
if ($http_user_agent ~ Mozilla) {
rewrite /aaa /bbb;
}
return 403 ;
}
location /bbb {
return 402 ;
}
}
|
在上述nginx.conf情况下,使用firefox浏览器访问nginx,if匹配成功,执行rewrite重写r->uri(/aaa转换为/bbb),
然后继续执行rewrite模块其他指令,执行到return 403后,该request在nginx中的处理完毕,返回403;
因此浏览器收到应答码为403
Example 2:
server {
listen 80 ;
location /aaa {
if ($http_user_agent ~ Mozilla) {
rewrite /aaa /bbb;
}
# return 403 ;
}
location /bbb {
return 402 ;
}
}
|
在上述nginx.conf情况下,使用firefox浏览器访问nginx,if匹配成功,执行rewrite重写r->uri(/aaa转换为/bbb)
rewrite模块执行完毕。因为所有rewrite模块的指令都执行完毕,进入POST_REWRITE_PHASE所在的checker函数ngx_http_core_post_rewrite_phase
中,由于执行了rewrite指令,在函数ngx_http_script_regex_start_code中
if (code->uri) {
r->internal = 1 ;
r->valid_unparsed_uri = 0 ;
if (code->break_cycle) { //rewrite ....break 指令分支
r->valid_location = 0 ;
r->uri_changed = 0 ;
} else {
r->uri_changed = 1 ;
}
}
|
可以得知r->uri_changed=1,于是在函数ngx_http_core_post_rewrite_phase中执行如下流程
r->uri_changes--;
if (r->uri_changes == 0 ) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0 ,
"rewrite or internal redirection cycle "
"while processing \"%V\"" , &r->uri);
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return NGX_OK;
}
r->phase_handler = ph->next; //ph->next为find_config_index,在ngx_http_init_phase_handlers中可见
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
r->loc_conf = cscf->ctx->loc_conf;
|
由于重新进行server和location匹配,因此在上述例子中,浏览器收到的应答状态吗为402
Example 3:
server {
listen 80 ;
location /aaa {
if ($http_user_agent ~ Mozilla) {
rewrite /aaa /bbb break ;
}
return 403 ;
}
location /bbb {
return 402 ;
}
}
|
在上述nginx.conf情况下,使用firefox浏览器访问nginx,if匹配成功,执行rewrite重写r->uri(/aaa转换为/bbb),
由于rewrite break标记符存在,从rewrite指令的配置解析函数ngx_http_rewrite和rewrite模块的handler函数ngx_http_rewrite_handler中
如下部分可以得知,将停止执行rewrite模块的其他一切指令;
ngx_http_rewrite {
....
....
if (cf->args->nelts == 4 ) {
if (ngx_strcmp(value[ 3 ].data, "last" ) == 0 ) {
last = 1 ;
} else if (ngx_strcmp(value[ 3 ].data, "break" ) == 0 ) {
regex->break_cycle = 1 ;
last = 1 ;
} else if (ngx_strcmp(value[ 3 ].data, "redirect" ) == 0 ) {
regex->status = NGX_HTTP_MOVED_TEMPORARILY;
regex->redirect = 1 ;
last = 1 ;
} else if (ngx_strcmp(value[ 3 ].data, "permanent" ) == 0 ) {
regex->status = NGX_HTTP_MOVED_PERMANENTLY;
regex->redirect = 1 ;
last = 1 ;
} else {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0 ,
"invalid parameter \"%V\"" , &value[ 3 ]);
return NGX_CONF_ERROR;
}
.....
.....
.....
if (last) {
code = ngx_http_script_add_code(lcf->codes, sizeof(uintptr_t), ®ex);
if (code == NULL) {
return NGX_CONF_ERROR;
}
*code = NULL;
}
}
ngx_http_rewrite_handler
{
.....
.....
while (*(uintptr_t *) e->ip) {
code = *(ngx_http_script_code_pt *) e->ip;
code(e);
}
if (e->status < NGX_HTTP_BAD_REQUEST) { //如果rewrite指令后不是break和last标记,而是其他两个重定向标记,则从此处直接结束该request处理流程
return e->status;
}
if (r->err_status == 0 ) {
return e->status;
}
return r->err_status;
.....
.....
}
|
进入到POST_REWRITE_PHASE所在的checker函数ngx_http_core_post_rewrite_phase中,由example 2 可知r->uri_changed = 0;
在ngx_http_core_post_rewrite_phase中会执行如下流程,因此会继续执行当前server 和 location 上下文中后续的handler,因此浏览器收到内容为bbb
if (!r->uri_changed) {
r->phase_handler++;
return NGX_AGAIN;
}
|
Example 4:
server {
listen 80 ;
location /aaa {
if ($http_user_agent ~ Mozilla) {
rewrite /aaa /bbb last;
}
return 403 ;
}
location /bbb {
return 402 ;
}
}
|
在上述nginx.conf情况下,使用firefox浏览器访问nginx,if匹配成功,执行rewrite重写r->uri(/aaa转换为/bbb),
由于rewrite last标记符存在,停止执行rewrite模块的其他一切指令,参考example 3。
进入到rewrite模块所在的checker函数ngx_http_core_post_rewrite_phase中,由example 2可知r->uri_changed = 1;
于是重新进行server和location匹配,因此在上述例子中,浏览器收到的内容的状态码为402
转载于:https://www.cnblogs.com/scottieyuyang/p/5722604.html
Nginx “邪恶” rewrite相关推荐
- Nginx的rewrite应用
Rewrite主要的功能是实现URL重写,Nginx 的 Rewrite 规则采用 PCRE Perl 兼容正则表达式的语法进行规则匹配,如相使用 Nginx 的 Rewrite 功能,在编译 Ngi ...
- index.php?s=$1,thinkphp nginx配置rewrite,地址会多出个.php
thinkphp nginx配置rewrite,地址会多出个.php ,http://localhost:7080/.php?m=... nginx配置文件 server { listen 80; # ...
- php ci nginx 伪静态rewrite配置方法
php ci nginx 伪静态rewrite配置方法 location / {if (!-e $request_filename) {rewrite ^(.*)$ /index.php?s=/$1 ...
- nginx的rewrite 参数和例子
nginx的rewrite 参数和例子 正则表达式匹配,其中: * ~ 为区分大小写匹配 * ~* 为不区分大小写匹配 * !~和!~*分别为区分大小写不匹配及不区分大小写不匹配 文件及目录匹配,其中 ...
- 第七章:nginx的rewrite规则详解
模块ngx_http_rewrite_module 该ngx_http_rewrite_module模块用于使用PCRE正则表达式更改请求URI,返回重定向,并有条件地选择配置. 句法: break; ...
- Nginx之rewrite配置
Rewtrite : 其主要目的是为了进行URL 重写,进行URL重定向.主要采用PCRE: Perl Compatible Regular Expressions(Perl兼容正则表达式语法)进行规 ...
- php选择nginx还是apache,浅谈apache和nginx的rewrite的区别
1. Nginx Rewrite规则相关指令 Nginx Rewrite规则相关指令有if.rewrite.set.return.break等,其中rewrite是最关键的指令.一个简单的Nginx ...
- Nginx的rewrite模块疑问排查
标题索引 追溯原因 实验分析 原理总结 追踪原因 最近心态"一步一印,有印为证",在Nginx的rewrite模块在工作过程中,客户端发起包到服务器解包整体过程浏览器做了什么?服务 ...
- 实例演示Nginx重写(Rewrite)类型last、break、redirect和permanent的区别
本文使用之前制作的Docker容器<<Docker案例:搭建nginx服务>>演示Nginx四种重写类型的区别和效果,如果尚未构建Docker服务可参考之前的文章,或者自建Ng ...
最新文章
- python分治算法_python算法实现-分治法
- 2018-11-02 在代码中进行中文命名实践的短期目标
- Struts2之文件下载
- python子进程进行kinit认证_使用kafka-python客户端进行kafka kerberos认证
- (62)FPGA一维数组(reg)
- HDU 3082 HDOJ 3082 Simplify The Circuit ACM 3082 IN HDU
- HTML5期末大作业:直播网站设计——仿在线媒体歪秀直播官网模板html源码(11个页面) HTML+CSS+JavaScript 期末作业HTML代码...
- 毕业生 - 哈尔滨工业大学社会计算与信息检索研究中心 - 理解语言,认知社会...
- 高等数学-函数在线绘图工具推荐(精选好用)
- Word文档字间距怎么调?
- 笔记本计算机摄像头怎么打开,手把手教你笔记本内置摄像头打不开解决方法
- 04-Groovy-运算符
- [含lw+源码等]S2SH+mysql的报刊订阅系统[包运行成功]Java毕业设计计算机毕设
- Linux各个文件夹的作用
- matlab 矩阵 对称,如何使用Matlab产生对称矩阵
- JS实现当前日期是第几周
- 深入探究宽字节注入漏洞与修补原理
- 易基因项目文章 | 90天见刊,易基因m6A RNA甲基化(MeRIP)+转录组组学研究
- VB6 简单实现 支付宝二维码扫马支付
- 安卓UTC与时间日期互转方法