11.6.2 ngx_http_core_rewrite_phase
ngx_http_core_rewrite_phase方法充当了用于重写URL的NGX_HTTP_SERVER_REWRITE_PHASE和NGX_HTTP_REWRITE_PHASE这两个阶段的checker方法。图11-9中描述了ngx_http_core_rewrite_phase方法的流程,可以看到,在调用了当前阶段的handler方法后,根据返回值的不同可能会导致3种结果。
图 11-9 ngx_http_core_rewrite_phase方法的执行流程
下面简要描述一下图11-9中所列的4个步骤。
1)首先调用HTTP模块实现的handler方法,根据它的返回值类型,将会有3种不同的结果:返回NGX_DECLINED时跳转到第2步执行;返回NGX_DONE时跳转到第3步执行;返回其他值时跳转到第4步执行。
2)如果handler方法返回NGX_DECLINED,将phase_handler加1表示将要执行下一个回调方法。注意,此时返回的是NGX_AGAIN,HTTP框架不会把进程控制权交还给epoll事件框架,而是继续立刻执行请求的下一个回调方法。
3)如果handler方法返回NGX_DONE,则意味着刚才的handler方法无法在这一次调度中处理完这一个阶段,它需要多次的调度才能完成。注意,此时返回NGX_OK,它会使得HTTP框架立刻把控制权交还给epoll等事件模块,不再处理当前请求,唯有这个请求上的事件再次被触发时才会继续执行。
4)如果handler方法返回除去NGX_DECLINED或者NGX_DONE以外的其他值,则调用ngx_http_finalize_request结束请求,其参数为handler方法的返回值。
可以注意到,ngx_http_core_rewrite_phase方法与ngx_http_core_generic_phase方法有一个显著的不同点:前者永远不会导致跨过同一个HTTP阶段的其他处理方法,就直接跳到下一个阶段来处理请求。原因其实很简单,可能有许多HTTP模块在NGX_HTTP_SERVER_REWRITE_PHASE和NGX_HTTP_REWRITE_PHASE阶段同时处理重写URL这样的业务,HTTP框架认为这两个阶段的HTTP模块是完全平等的,序号靠前的HTTP模块优先级并不会更高,它不能决定序号靠后的HTTP模块是否可以再次重写URL。因此,ngx_http_core_rewrite_phase方法绝对不会把phase_handler直接设置到下一个阶段处理方法的流程中,即不可能存在类似下面的代码。
ngx_int_t ngx_http_core_rewrite_phase(ngx_http_request_tr,ngx_http_phase_handler_tph)
{
……
r->phase_handler=ph->next;
……
}