Nginx-ru mailing list archive (nginx-ru@sysoev.ru)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: фильтр
> > Задача очень проста: заменить на лету содержимое, допустим букву A на
> > 2 буквы AA. Мне нужно взять цепочку in и заменить ее на новую цепочку
> > out, которая содержит новые буфера с измененным содержимым (выходных
> > буферов будет скорее всего больше чем входных, так как объем данных
> > увеличится).
Если посмотреть на ngx_http_sub_filter_module.c (делает что-то
потипу), то не совсем ясно, в чем смысл
ngx_chain_t *in;
ngx_chain_t *out;
ngx_chain_t **last_out;
ngx_chain_t *busy;
ngx_chain_t *free;
Кто может объяснить что тут к чему?
2008/3/31 Sergey Bochenkov <bachan@xxxxxxxxx>:
> On Mon, 31 Mar 2008 13:08:10 +0300
> "Alexander Dolgarev"
>
> <a.dolgarev@xxxxxxxxx> 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@xxxxxxxxxx>:
> > > 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
> > >
> > >
>
>
>
>
|