標籤:
關於Nginx Http模組開發的文章非常少,只有Emiler的那篇關於Http模組的文章,但是那篇文章裡面,並沒有說到事件型的模組如何進行開發。而且文章裡面提到的內容實在是讓人有點意猶未盡。因此,對於Http事件型模組的開發進行了一些總結,與大家分享。但是,無論如何,要進行Nginx模組開發,最好的方法還是找到相似性較大的模組的代碼進行參考,多試多看。
通常,一個Http模組均是有以下的幾個部分組成: 1.模組配置結構體:(configure structure) 負責儲存配置項的內容,每一條配置項,均會產生一個配置結構體,可以方便模組進行配置的預先處理,儲存相應的結構休內容,大致結構如下:
typedef struct {
/**
* your configuration struct members */} ngx_http_<your module>_conf_t; 2.模組指令( Module Directives )
static ngx_command_t ngx_<your module>_commands[] = {
{ ngx_string("test"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
<your read conf function>,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
...
ngx_null_command
};
結構體如下:
struct ngx_command_t {
ngx_str_t name; /* 配置中指令的文字 */
ngx_uint_t type; /* 指明該指令可以使用的場合 */
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); /* 讀取配置回呼函數,通常對參數進行處理,並且寫入到配置結構體中 */
ngx_uint_t conf;
ngx_uint_t offset;
void *post;
};
3.模組上下文(The Module Context)
這個結構體主要定義了一系列的回呼函數,在不同的時期進行回調
typedef struct {
ngx_int_t (*preconfiguration)(ngx_conf_t *cf);
ngx_int_t (*postconfiguration)(ngx_conf_t *cf);
void *(*create_main_conf)(ngx_conf_t *cf);
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);
void *(*create_srv_conf)(ngx_conf_t *cf);
char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);
void *(*create_loc_conf)(ngx_conf_t *cf);
char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;
進行階段handler的開發,則需要在postconfiguration的時期將handler插入相應的階段。 4.定義模組結構體 ngx_module_t ngx_http_<module name>_module = { NGX_MODULE_V1, &ngx_http_<module name>_module_ctx, /* module context */ ngx_http_<module name>_commands, /*module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING };完成這一步之後,基本上一個模組的基礎已經形成。 5.插入階段回呼函數 為了在Http處理的階段中加入相應的處理函數,需要在postconfigure的回呼函數中進行相應的handler插入。 以下是在http_access的模組中的代碼:
static ngx_int_t
ngx_http_access_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_ACCESS_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = ngx_http_access_handler;
return NGX_OK;
} 而ngx_http_access_handler就是在NGX_HTTP_ACCESS_PHASE中插入的handler。 HTTP在處理的過程中,總共有如下若干個階段: typedef enum {
NGX_HTTP_POST_READ_PHASE = 0,
NGX_HTTP_SERVER_REWRITE_PHASE,
NGX_HTTP_FIND_CONFIG_PHASE,
NGX_HTTP_REWRITE_PHASE,
NGX_HTTP_POST_REWRITE_PHASE,
NGX_HTTP_PREACCESS_PHASE,
NGX_HTTP_ACCESS_PHASE,
NGX_HTTP_POST_ACCESS_PHASE,
NGX_HTTP_TRY_FILES_PHASE,
NGX_HTTP_CONTENT_PHASE,
NGX_HTTP_LOG_PHASE
} ngx_http_phases; 如果覺得phases不夠用,可以在nginx的代碼中進行加入自己的階段。 這種處理方法,可以在Nginx作為proxy轉寄之前,加入自己的handler進行一些處理,相當的實用。 不同階段的處理方法不同,具體的方法可以參考ngx_http_core_module.c中的相應checker函數。
Nginx Http模組開發