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.6.2 ngx_http_core_rewrite_phase - 图1

图 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;

……

}