handler 模塊真正的處理函數(shù)通過兩種方式掛載到處理過程中,一種方式就是按處理階段掛載;另外一種掛載方式就是按需掛載。
為了更精細(xì)地控制對于客戶端請求的處理過程,Nginx 把這個處理過程劃分成了 11 個階段。他們從前到后,依次列舉如下:
一般情況下,我們自定義的模塊,大多數(shù)是掛載在 NGX_HTTP_CONTENT_PHASE 階段的。掛載的動作一般是在模塊上下文調(diào)用的 postconfiguration 函數(shù)中。
注意:有幾個階段是特例,它不調(diào)用掛載地任何的handler,也就是你就不用掛載到這幾個階段了:
所以其實真正是有 7 個 phase 你可以去掛載 handler。
掛載的代碼如下(摘自 hello module):
static ngx_int_t
ngx_http_hello_init(ngx_conf_t *cf)
{
ngx_http_handler_pt *h;
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = ngx_http_hello_handler;
return NGX_OK;
}
使用這種方式掛載的 handler 也被稱為 content phase handlers。
以這種方式掛載的 handler 也被稱為 content handler。
當(dāng)一個請求進(jìn)來以后,Nginx 從 NGX_HTTP_POST_READ_PHASE 階段開始依次執(zhí)行每個階段中所有 handler。執(zhí)行到 NGX_HTTP_CONTENT_PHASE 階段的時候,如果這個 location 有一個對應(yīng)的 content handler 模塊,那么就去執(zhí)行這個 content handler 模塊真正的處理函數(shù)。否則繼續(xù)依次執(zhí)行 NGX_HTTP_CONTENT_PHASE 階段中所有 content phase handlers,直到某個函數(shù)處理返回 NGX_OK 或者 NGX_ERROR。
換句話說,當(dāng)某個 location 處理到 NGX_HTTP_CONTENT_PHASE 階段時,如果有 content handler 模塊,那么 NGX_HTTP_CONTENT_PHASE 掛載的所有 content phase handlers 都不會被執(zhí)行了。
但是使用這個方法掛載上去的 handler 有一個特點是必須在 NGX_HTTP_CONTENT_PHASE 階段才能執(zhí)行到。如果你想自己的 handler 在更早的階段執(zhí)行,那就不要使用這種掛載方式。
那么在什么情況會使用這種方式來掛載呢?一般情況下,某個模塊對某個 location 進(jìn)行了處理以后,發(fā)現(xiàn)符合自己處理的邏輯,而且也沒有必要再調(diào)用 NGX_HTTP_CONTENT_PHASE 階段的其它 handler 進(jìn)行處理的時候,就動態(tài)掛載上這個 handler。
下面來看一下使用這種掛載方式的具體例子(摘自 Emiller's Guide To Nginx Module Development)。
static char *
ngx_http_circle_gif(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_http_circle_gif_handler;
return NGX_CONF_OK;
}
更多建議: