Nginx handler 模塊的掛載

2022-03-23 15:42 更新

handler 模塊的掛載

handler 模塊真正的處理函數(shù)通過兩種方式掛載到處理過程中,一種方式就是按處理階段掛載;另外一種掛載方式就是按需掛載。

按處理階段掛載

為了更精細(xì)地控制對于客戶端請求的處理過程,Nginx 把這個處理過程劃分成了 11 個階段。他們從前到后,依次列舉如下:

  • NGX_HTTP_POST_READ_PHASE: 讀取請求內(nèi)容階段
  • NGX_HTTP_SERVER_REWRITE_PHASE: Server 請求地址重寫階段
  • NGX_HTTP_FIND_CONFIG_PHASE: 配置查找階段:
  • NGX_HTTP_REWRITE_PHASE: Location 請求地址重寫階段
  • NGX_HTTP_POST_REWRITE_PHASE: 請求地址重寫提交階段
  • NGX_HTTP_PREACCESS_PHASE: 訪問權(quán)限檢查準(zhǔn)備階段
  • NGX_HTTP_ACCESS_PHASE: 訪問權(quán)限檢查階段
  • NGX_HTTP_POST_ACCESS_PHASE: 訪問權(quán)限檢查提交階段
  • NGX_HTTP_TRY_FILES_PHASE: 配置項 try_files 處理階段
  • NGX_HTTP_CONTENT_PHASE: 內(nèi)容產(chǎn)生階段
  • NGX_HTTP_LOG_PHASE: 日志模塊處理階段

一般情況下,我們自定義的模塊,大多數(shù)是掛載在 NGX_HTTP_CONTENT_PHASE 階段的。掛載的動作一般是在模塊上下文調(diào)用的 postconfiguration 函數(shù)中。

注意:有幾個階段是特例,它不調(diào)用掛載地任何的handler,也就是你就不用掛載到這幾個階段了:

  • NGX_HTTP_FIND_CONFIG_PHASE
  • NGX_HTTP_POST_ACCESS_PHASE
  • NGX_HTTP_POST_REWRITE_PHASE
  • NGX_HTTP_TRY_FILES_PHASE

所以其實真正是有 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;
    }
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號