handler 模塊真正的處理函數(shù)通過兩種方式掛載到處理過程中,一種方式就是按處理階段掛載;另外一種掛載方式就是按需掛載。
為了更精細(xì)地控制對于客戶端請求的處理過程,Nginx 把這個(gè)處理過程劃分成了 11 個(gè)階段。他們從前到后,依次列舉如下:
一般情況下,我們自定義的模塊,大多數(shù)是掛載在 NGX_HTTP_CONTENT_PHASE 階段的。掛載的動(dòng)作一般是在模塊上下文調(diào)用的 postconfiguration 函數(shù)中。
注意:有幾個(gè)階段是特例,它不調(diào)用掛載地任何的handler,也就是你就不用掛載到這幾個(gè)階段了:
所以其實(shí)真正是有 7 個(gè) 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)一個(gè)請求進(jìn)來以后,Nginx 從 NGX_HTTP_POST_READ_PHASE 階段開始依次執(zhí)行每個(gè)階段中所有 handler。執(zhí)行到 NGX_HTTP_CONTENT_PHASE 階段的時(shí)候,如果這個(gè) location 有一個(gè)對應(yīng)的 content handler 模塊,那么就去執(zhí)行這個(gè) content handler 模塊真正的處理函數(shù)。否則繼續(xù)依次執(zhí)行 NGX_HTTP_CONTENT_PHASE 階段中所有 content phase handlers,直到某個(gè)函數(shù)處理返回 NGX_OK 或者 NGX_ERROR。
換句話說,當(dāng)某個(gè) location 處理到 NGX_HTTP_CONTENT_PHASE 階段時(shí),如果有 content handler 模塊,那么 NGX_HTTP_CONTENT_PHASE 掛載的所有 content phase handlers 都不會(huì)被執(zhí)行了。
但是使用這個(gè)方法掛載上去的 handler 有一個(gè)特點(diǎn)是必須在 NGX_HTTP_CONTENT_PHASE 階段才能執(zhí)行到。如果你想自己的 handler 在更早的階段執(zhí)行,那就不要使用這種掛載方式。
那么在什么情況會(huì)使用這種方式來掛載呢?一般情況下,某個(gè)模塊對某個(gè) location 進(jìn)行了處理以后,發(fā)現(xiàn)符合自己處理的邏輯,而且也沒有必要再調(diào)用 NGX_HTTP_CONTENT_PHASE 階段的其它 handler 進(jìn)行處理的時(shí)候,就動(dòng)態(tài)掛載上這個(gè) 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;
}
更多建議: