4.5.2 如何使用HTTP上下文

ngx_http_get_module_ctx和ngx_http_set_ctx这两个宏可以完成HTTP上下文的设置和使用。先看看这两个宏的定义,如下所示。


define ngx_http_get_module_ctx(r,module)(r)->ctx[module.ctx_index]

define ngx_http_set_ctx(r,c,module)r->ctx[module.ctx_index]=c;


ngx_http_get_module_ctx接受两个参数,其中第1个参数是ngx_http_request_t指针,第2个参数则是当前的HTTP模块对象。例如,在mytest模块中使用的就是在3.5节中定义的ngx_module_t类型的ngx_http_mytest_module结构体。ngx_http_get_module_ctx返回值就是某个HTTP模块的上下文结构体指针,如果这个HTTP模块没有设置过上下文,那么将会返回NULL空指针。因此,在任何一个HTTP模块中,都可以使用ngx_http_get_module_ctx获取所有HTTP模块为该请求创建的上下文结构体。

ngx_http_set_ctx接受3个参数,其中第1个参数是ngx_http_request_t指针,第2个参数是准备设置的上下文结构体的指针,第3个参数则是HTTP模块对象。

举个简单的例子来说明如何使用ngx_http_get_module_ctx宏和ngx_http_set_ctx宏。首先建立mytest模块的上下文结构体,如ngx_http_mytest_ctx_t。


typedef struct{

ngx_uint_t my_step;

}ngx_http_mytest_ctx_t;


当请求第1次进入mytest模块处理时,创建ngx_http_mytest_ctx_t结构体,并设置到这个请求的上下文中。


static ngx_int_t

ngx_http_mytest_handler(ngx_http_request_t*r)

{

//首先调用ngx_http_get_module_ctx宏来获取上下文结构体

ngx_http_mytest_ctx_t*myctx=ngx_http_get_module_ctx(r,ngx_http_mytest_module);

//如果之前没有设置过上下文,那么应当返回NULL

if(myctx==NULL)

{

/必须在当前请求的内存池r->pool中分配上下文结构体,这样请求结束时结构体占用的内存才会释放/

myctx=ngx_palloc(r->pool,sizeof(ngx_http_mytest_ctx_t));

if(myctx==NULL)

{

return NGX_ERROR;

}

//将刚分配的结构体设置到当前请求的上下文中

ngx_http_set_ctx(r,myctx,ngx_http_mytest_module);

}

//之后可以任意使用myctx这个上下文结构体

……

}


如果Nginx多次回调mytest模块的相应方法,那么每次用ngx_http_get_module_ctx宏取到上下文,ngx_http_mytest_ctx_t都可以正常使用,HTTP框架可以对一个请求保证,无论调用多少次ngx_http_get_module_ctx宏都只取到同一个上下文结构。