ngx_http_request_t是在编写nginx模块中经常用到的结构体,大多的模块的工作都是基于该结构体的,该结构中的request_body是记录请求的数据主体,大部分情况在POST状态时有数据。实际情况下,如果需要HOOK上行的数据,即在提交给后端的SERVER前基于request_body进行处理,那么nginx现有提供的几个模块的注册位置都读取不到request_body,估计可能很多同学都碰到这个问题,我觉得很有必要加上一个阶段,呵呵。

当然nginx给我们提供了相应的函数来做这个事情,这个函数就是ngx_http_read_client_request_body。可采用如下方式进行调用:

static ngx_int_t
ngx_http_x_up_handler(ngx_http_request_t *r)
{
	ngx_int_t rc;
 
	if (r->method == NGX_HTTP_POST)
	{
		ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "post:%V", &r->uri);
		rc = ngx_http_read_client_request_body(r, ngx_http_x_up_body_handler);
 
		if (rc >= NGX_HTTP_SPECIAL_RESPONSE) 
			return rc;
		else
			return NGX_DECLINED;
	}
	else
		ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "get:%V", &r->uri);
 
	return NGX_DECLINED;
}
 
 
static void
ngx_http_x_up_body_handler(ngx_http_request_t *r)
{
	if (r->request_body) 
	{
		ngx_chain_t	*cl;
		for (cl = r->request_body->bufs; cl; cl = cl->next) 
		{
			ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "post request body:%s", cl->buf->pos);
		}
	}
 
}
 
 
static ngx_int_t
ngx_http_x_up_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_x_up_handler;
 
	return NGX_OK;
}

至此,包括header/request_uri/request_body这些HTTP请求中的数据段都能获取了,基于POST的数据写个LB如何? :)

您可能还喜欢

7 Responses to “在nginx的模块中读取request body”

  1. kangzj Says:

    嗯,顶了;你是做什么工作呀,要改nginx的源码?

  2. libing Says:

    WEB相关的工作,呵呵!

  3. Bunker Says:

    Valuable thoughts and advices. I read your topic with great interest.

  4. Kouba Says:

    I added your blog to bookmarks. And i’ll read your articles more often!

  5. kucongzhi Says:

    need to learn this knownledge

  6. jiajun Says:

    555,内存又出问题了,我来看这篇文章然后再改

  7. 淘宝网女装 Says:

    学习了~~

Leave a Reply