Nginx入門之兩種handler函數的掛載方式

請在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。html

接着上次的文章,今天研究《深刻理解Nginx模塊開發與架構解析》一書中給出的mytest的例子,發現和 /tengine.taobao.org/book/ 一書中的例子不甚相同,尤爲是在handler函數的掛在方面。nginx

函數的掛載分爲兩種方式:架構

一種方式就是按處理階段掛載;另一種掛載方式就是按需掛載。tengine.taobao.org 中使用的掛載方式是按處理階段掛載,而深刻理解一書中的掛載方式是按需求掛載。函數

首先看/tengine.taobao.org/book/中的例子:post

由我以前 Nginx_handler模塊發開(hello模塊結構解析)一文,handler_init就是handler函數的掛載函數,該函數在上下文結構中的postconfiguration字段被調用,決定handler函數在哪裏被掛載。url

複製代碼
 1 static ngx_http_module_t ngx_http_hello_module_ctx = {  2 NULL, /* preconfiguration */  3 ngx_http_hello_init, /* postconfiguration */  4  5 NULL, /* create main configuration */  6 NULL, /* init main configuration */  7  8 NULL, /* create server configuration */  9 NULL, /* merge server configuration */ 10 11 ngx_http_hello_create_loc_conf, /* create location configuration */ 12 NUL
複製代碼

 

複製代碼
 1 static ngx_int_t  2 ngx_http_hello_init(ngx_conf_t *cf)  3 {  4 ngx_http_handler_pt *h;  5 ngx_http_core_main_conf_t *cmcf;  6  7 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); //取得core_module的cf  8  9 h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers); // 掛載函數到對應處理階段 10 if (h == NULL) { 11 return NGX_ERROR; 12  } 13 14 *h = ngx_http_hello_handler; //將函數指針指向handler函數 15 16 return NGX_OK; 17 }
複製代碼

使用這種方式掛載的handler也被稱爲 content phase handlersspa

 

 

而在《深刻理解Nginx模塊開發與架構解析》一書中給出的mytest的例子中,則是按需求掛載:指針

以這種方式掛載的handler也被稱爲 content handlercode

當一個請求進來之後,nginx從NGX_HTTP_POST_READ_PHASE階段開始依次執行每一個階段中全部handler。執行到 NGX_HTTP_CONTENT_PHASE階段的時候,若是這個location有一個對應的content handler模塊,那麼就去執行這個content handler模塊真正的處理函數。不然繼續依次執行NGX_HTTP_CONTENT_PHASE階段中全部content phase handlers,直到某個函數處理返回NGX_OK或者NGX_ERROR。server

換句話說,當某個location處理到NGX_HTTP_CONTENT_PHASE階段時,若是有content handler模塊,那麼NGX_HTTP_CONTENT_PHASE掛載的全部content phase handlers都不會被執行了。

可是使用這個方法掛載上去的handler有一個特色是必須在NGX_HTTP_CONTENT_PHASE階段才能執行到。若是你想本身的handler在更早的階段執行,那就不要使用這種掛載方式。

那麼在什麼狀況會使用這種方式來掛載呢?通常狀況下,某個模塊對某個location進行了處理之後,發現符合本身處理的邏輯,並且也沒有必要再調用NGX_HTTP_CONTENT_PHASE階段的其它handler進行處理的時候,就動態掛載上這個handler。

mytest這個例子在配置結構中,直接調用了content handler函數,名爲ngx_http_mytest,該函數直接實現了真正的handler函數的掛載執行:

複製代碼
 1 static ngx_command_t ngx_http_mytest_commands[] = {  2  {  3 ngx_string("mytest"),  4 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_NOARGS,  5  ngx_http_mytest,  6  NGX_HTTP_LOC_CONF_OFFSET,  7 0,  8  NULL  9  }, 10  ngx_null_command 11 };
複製代碼

content handler函數 ngx_http_mytest的定義以下:

複製代碼
 1 static char *  2 ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)  3 {  4 ngx_http_core_loc_conf_t *clcf;  5  6 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);  7  8 clcf->handler = ngx_http_mytest_handler;  9 10 return NGX_CONF_OK; 11 }
複製代碼

定義十分簡單,主要就是一個ngx_http_conf_get_module_loc_conf函數的調用,以及一個函數指針的賦值。函數指針的賦值實現了真正的handler函數的掛載。

那麼,咱們來看看被調用的ngx_http_conf_get_module_loc_con函數的定義:

#define ngx_http_conf_get_module_loc_conf(cf, module)                         \ ((ngx_http_conf_ctx_t *) cf->ctx)->loc_conf[module.ctx_index]

只是一個宏定義,主要做用是將以前存儲起來的conf內容調出,賦值給clcf。

聯繫方式:rwhsysu@163.com。

我的理解,歡迎指正。

相關文章
相關標籤/搜索