nginx中ngx_http_rewrite_module管理着配置文件中的set、if、rewrite、break、return等指令,其中if会和location指令一样在server下创建location并push到server->locations队列里,有个noname属性区分这两种情况,用于在find_config_phase时只查找真实的location。location指令详情参见[location指令]。(http://blog.csdn.net/mqfcu8/article/details/55001139)
if指令
可以出现在server、location下,调用nginx_http_rewrite_if()
解析配置中的if行
ngx_http_add_location()
,生成一个location push到server的locations队列里ngx_http_rewrite_if_condition()
,根据if语句里的变量、判断运算符压入脚本函数,此时指令集在server的ngx_http_rewrite_module.ctx_index索引处,比如if ($uri ~* ^hello$)
ngx_http_rewrite_variable()
向指令集里增加ngx_http_script_var_code,用于运行态获取变量uri的值- 因为是判定符是~*,故向指令集里增加ngx_http_script_regex_start_code,运行态进行正则匹配
- 向指令集里增加ngx_http_script_if_code,运行态完成跳转(跳进{}里还是{}外)
- 指令集里下一条指令是if条件成立的{}里的语句,ngx_http_script_regex_start_code()里判断成立后会置标志e->sp->data = (u_char*)”1”
- 指令集里该指令->next指向了{}外的那条指令地址
- 设置if的location的ngx_http_rewrite_module.ctx_index的指令集指针指向当前指令集(有点绕),意思:if块里的指令集和if上层共用一个
- 递归解析if块内的配置信息
运行时期,rewrite_phase会执行该server的ngx_http_rewrite_module.ctx_index索引的指令集,以配置文件中的顺序执行。
rewrite指令
官方说明:http://nginx.org/en/docs/http/ngx_http_rewrite_module.html
- last,不执行后续指令集,如果是server块,则跳到find_location_phase,如果是location块,则跳到post_rewrite_phase中因检查到有uri跳转便重新回到find_location_phase再次匹配location,继续后续的执行;
- break,不执行后续指令集,如果在server块和last一样,如果是location块,则跳到post_rewrite_phase后不再回到find_location_phase;
- redirect,不执行后续指令集,在http_header里埋location,执行302跳转,rewrite_phase得到status 302状态便
ngx_http_finalize_request()
- permanent,不执行后续指令集,在http_header里埋location,执行301跳转,rewrite_phase得到status 301状态便
ngx_http_finalize_request()
如果replacement是以http://或https://开始,则默认按redirect处理
该指令在ngx_http_rewrite()
进行解析,比如rewrite ^/(.*) /search last;
- 在指令集中添加ngx_http_script_regex_start_code指令,运行时态执行正则表达式
ngx_http_script_compile()
函数负责在指令集中添加ngx_http_script_copy_code指令,运行时态获取/search- 在指令集中增加ngx_http_script_regex_end_code指令,运行时态如果是redirect将在http_header里填location字段
- 很重要的一步:在指令集中添加一个空指令,用于运行时态跳出指令执行的循环,从而实现不再执行本阶段的后续所有指令
运行时态
hander执行顺序为:
- server层级的rewrite_phase,负责执行server下的set、if、rewrite等指令
- find_config_phase,负责uri匹配location,故server层级的rewrite last/break更改uri后,能匹配location
- location层级的rewrite_phase,负责执行location下的set、if、rewrite等指令
- post_rewrite_phase,检测如果uri发现了变化(last)且变更次数少于10,会将phase重新指回到find_config_phase,注意rewrite break不会标记uri变化,故直接进入下一phase