фильтр

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