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