Re: Возврат данных из подзапроса

Maxim Dounin mdounin на mdounin.ru
Вт Ноя 2 19:43:20 MSK 2010


Hello!

On Tue, Nov 02, 2010 at 06:10:02PM +0300, Igor A. Valcov wrote:

> Здравствуйте!
> 
> Вопрос знатокам внутренностей nginx. Хочу разобраться с сабжевым механизмом.
> 
> Пишу модуль, в котором есть такой обработчик запроса
> 
> ngx_int_t ngx_http_subrequest_handler(ngx_http_request_t *r)
> {
>     ...
> 
>     ngx_http_post_subrequest_t *sub_cb = ngx_pcalloc(r->pool,
> sizeof(ngx_http_post_subrequest_t));
>     if (sub_cb == NULL)
>         return NGX_HTTP_INTERNAL_SERVER_ERROR;
> 
>     sub_cb->handler = subrequest_completed;
>     sub_cb->data = NULL; /* FIXME */
> 
>     ngx_str_t uri;
>     ngx_str_set(&uri, "/fetch");
> 
>     ngx_http_request_t *req = NULL;
> 
>     rc = ngx_http_subrequest(r, &uri, NULL, &req, sub_cb,
> NGX_HTTP_SUBREQUEST_WAITED);
>     if (rc != NGX_OK)
>         return NGX_HTTP_INTERNAL_SERVER_ERROR;
> 
>     return NGX_AGAIN;
> }
> 
> Который назначается так:
> 
> ...
> clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
> clcf->handler = ngx_http_subrequest_handler;
> ...
> 
> Этот подзапрос отправляется на
> 
> location /fetch {
>     internal;
>     proxy_pass http://host.ru:port;
> }
> 
> После приёма данных proxy-модулём вызывается обработчик subrequest_completed
> 
> ngx_int_t subrequest_completed(ngx_http_request_t *r, void *data, ngx_int_t rc)
> {
>     ngx_buf_t *buf;
>     ngx_chain_t out;
> 
>     ngx_buf_t *resp = NULL;
>     if(r->out)
>         resp = r->out->buf;
>     if(r->upstream)
>         resp = &r->upstream->buffer;
> 
>     ....
> 
> //     ngx_http_request_t *pr = r->parent;
> //     pr->write_event_handler = write_event_handler;
> 
>     return NGX_OK;
> }
> 
> Вопрос такой: как идеологически правильным способом получить и
> обработать данные подзапроса на уровне родительского запроса? Откуда
> это делать? И как правильно завершить подзапрос и родитиельский
> запрос?
> 
> Кратко, задача такая: нужно изъять полученные mod_proxy данные (и
> заголовки), которые он пытается отправить в out, на основе этих данных
> сгенерировать совершенно другие данные (и заголовки) и отправиь в out
> уже их.

Если хочется простой способ - то читать ssi внимательно про 
NGX_HTTP_SUBREQUEST_IN_MEMORY.  Результат подзапроса доставать 
внутри post subrequest handler'а из r->upstream->buffer, см.  
пример в ngx_http_ssi_set_variable().  Будет работать с proxy_pass 
и memcached_pass.

Сложный способ - делать фильтры в нужных количествах, см. например 
image filter, xslt filter.

Maxim Dounin



Подробная информация о списке рассылки nginx-ru