фильтр
Sergey Bochenkov
bachan at j3qq4.org
Mon Mar 31 16:19:25 MSD 2008
On Mon, 31 Mar 2008 13:08:10 +0300
"Alexander Dolgarev"
<a.dolgarev at gmail.com> wrote:
> Задача очень проста: заменить на лету содержимое, допустим букву A на
> 2 буквы AA. Мне нужно взять цепочку in и заменить ее на новую цепочку
> out, которая содержит новые буфера с измененным содержимым (выходных
> буферов будет скорее всего больше чем входных, так как объем данных
> увеличится).
>
> Отсюда вытекает пара вопросов.
>
> 1. Могу ли я создавать свои цепочки путем
> out = ngx_pcalloc(r->pool, sizeof(ngx_chain_t));
> и далее вызывать
> return ngx_http_next_body_filter(r, out);
> или мне обязательно передавать в ngx_http_next_body_filter цепочку in,
> заменив в ней буфер на свой?
Цепочки можно менять. Если нужно вставлять звенья в цепочку in, их
можно выделять с помощью ngx_alloc_chain_link(ngx_pool_t *pool), либо
полностью копировать цепочку in в новую.
Если нужно заменить всю цепочку, новую ngx_chain_t out можно выделить
на стеке, насколько я понимаю.
> 2. Буфер создается путем
> b = ngx_create_temp_buf(r->pool, BUFLEN);
> Какие еще флаги надо в нем выставлять кроме тех, что выставляются
> функцией ngx_create_temp_buf()?
Флаги нужно выставлять в зависимости от отсылаемого буфера.
Те, что помню, описал ниже (поправьте, если где-то ошибаюсь):
temporary : содержимое буфера может быть изменено
memory : буфер находится в read-only памяти
mmap : буфер находится в за-mmap-ленной памяти
last_buf : последний буфер в цепочке
last_in_chain : хинт для лучшего использования памяти при отдаче
sync : пустой буфер
in_file : часть буфера находится в файле
recycled : буфер используется повторно
В модулях, которые заменяют буферы ответа, часто используется
конструкция: ngx_cpymem(new_buf, old_buf, sizeof(ngx_buf_t));
> 3. Что нужно делать с буферами в цепочке in? Ниже высказывалось
> мнение, что пометить его как отправленный (in->buf->pos =
> in->buf->last), что-то еще нужно?
>
> 2008/3/30 Maxim Dounin <mdounin at mdounin.ru>:
> > Hello!
> >
> >
> >
> > On Sun, Mar 30, 2008 at 03:03:29AM +0200, Alexander Dolgarev wrote:
> >
> > >В чем принципиальная неправильность следующего фрагмента кода (если
> > >допустить что in != NULL и in->next == NULL)? Клиент просто ждет и
> > >ничего не получает в ответ.
> > >
> > >
> > >static ngx_int_t
> > >ngx_http_*_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
> > >{
> > > ngx_chain_t *out;
> > > ngx_buf_t *b;
> > >
> > > out = ngx_pcalloc(r->pool, sizeof(ngx_chain_t));
> > > b = ngx_create_temp_buf(r->pool, in->buf->last - in->buf->pos);
> > > memcpy (b->pos, in->buf->pos, in->buf->last - in->buf->pos);
> > > b->last_buf = in->buf->last_buf;
> > > out->buf = b;
> > >
> > > return ngx_http_next_body_filter(r, out);
> > >}
> >
> > Старый буфер помечен как отправленный, соответственно если ответ
> > будет более чем output_buffers - его не отошлют. Как минимум надо
> > ещё сделать:
> >
> > in->buf->pos = in->buf->last;
> >
> > Плюс к тому - никто не обещал, что буфер будет в памяти. Чтобы он
> > таки там был - об этом надо специально попросить, поставив в
> > ngx_http_*_header_filter()
> >
> > r->filter_need_in_memory = 1;
> >
> > Maxim Dounin
> >
> >
More information about the nginx-ru
mailing list