Re: фильтр

Alexander Dolgarev a.dolgarev at gmail.com
Mon Mar 31 18:12:56 MSD 2008


>  > Задача очень проста: заменить на лету содержимое, допустим букву 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 at j3qq4.org>:
> 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