GZIP-фильтр Nginx не работает с моим пользовательским обработчиком - PullRequest
6 голосов
/ 08 декабря 2011

Я написал очень простой обработчик nginx, просто вывел текст (размером от 100B до 10KB).

код работает правильно с nginx (версия 1.0.6)

но я обнаружил, что фильтр gzip не может работать с обработчиком.

когда я включаю gzip в nginx.conf (в разделе http), файл gzip работает со статическими html-файлами.

но ответ обработчика не сжимается с помощью gzip.

после долгих поисков работы я до сих пор не могу найти ответ.

есть комментарии? большое спасибо. : -)

//my code :
static ngx_int_t ngx_http_test_handler(ngx_http_request_t *r){

    ngx_chain_t out;
    ngx_buf_t *b;

    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));

    ......
    //writing text to buffer
    ......
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = len;
    r->headers_out.content_type.len = sizeof("text/html")-1;
    r->headers_out.content_type.data = (u_char *) "text/html";

    out.buf = b;
    out.next = NULL;
    return ngx_http_output_filter(r, &out);
}

Ответы [ 3 ]

1 голос
/ 24 февраля 2012

Если еще не слишком поздно, у меня возникла такая же проблема с моим модулем фильтра.

Проблема связана с тем, что вы меняете тип содержимого ответа.Gzip проверяет Content-Type для content_type_len и content_type_lowcase, чтобы решить, должен ли ответ быть Gziped.Этот код должен работать:

r->headers_out.content_type_len = strlen("text/html");
r->headers_out.content_type.len = strlen("text/html");
r->headers_out.content_type.data = (u_char *) "text/html";
r->headers_out.content_type_lowcase = NULL;

Чтобы понять, почему этот код работает, вы должны учитывать, что фильтр Gzip сначала вызывает метод ngx_http_test_content_type, чтобы включить gzip для ответа.Вы можете увидеть источник здесь: http://lxr.evanmiller.org/http/source/http/ngx_http_core_module.c#L1659

0 голосов
/ 02 марта 2015

Приведенный выше ответ кажется ... неточным.

Код, который проверяет это, находится в строке 250 или около нее в src/http/modules/ngx_http_gzip_filter_module.c и гласит:

if (!conf->enable
    || (r->headers_out.status != NGX_HTTP_OK
        && r->headers_out.status != NGX_HTTP_FORBIDDEN
        && r->headers_out.status != 207
        && r->headers_out.status != NGX_HTTP_NOT_FOUND)
    || (r->headers_out.content_encoding
        && r->headers_out.content_encoding->value.len)
    || (r->headers_out.content_length_n != -1
        && r->headers_out.content_length_n < conf->min_length)
    || ngx_http_test_content_type(r, &conf->types) == NULL
    || r->header_only)
{
    return ngx_http_next_header_filter(r); <-- this is the line you want to breakpoint!
}

Если япри правильном чтении условия:

  • HTTP-статус должен быть 200, 403 или 404.
  • должно быть установлено content_encoding (что имеет смысл: gzipping setsкодировка содержимого в "gzip")
  • content_length_n, если установлена, должна быть больше минимальной длины (по умолчанию 20).Нельзя указывать длину содержимого.
  • content_type должен быть в допустимом списке.По умолчанию принимается только «text / html», но другие типы могут быть установлены с помощью опции конфигурации gzip_types.Если в списке есть «*», то с любым типом содержимого, в том числе и без него, все в порядке.
  • Должно быть тело для сжатия

Начиная с версии 1.7.10,return выше находится в строке 257. Установка «daemon off», работающая под GDB и b ngx_http_gzip_filter_module.c:257, позволит вам точно увидеть, когда и как проверки не пройдены.(Вы, вероятно, должны скомпилировать из исходного кода, если вы пытаетесь это ...)

0 голосов
/ 18 февраля 2012

Во-первых, где вы звоните ngx_http_send_header(r);?

Инициализируете ли вы членов ngx_buf_t *b?

Кодируется ли ваш контент для набора запросов?

Ваш обработчик выдает ошибку?Если это так, фильтры не будут вызываться?

Другие ограничения, которые необходимо соблюдать, чтобы гарантировать, что фильтр gzip работает (а не обходится) при вызове вашим обработчиком, включают

  • Gzip mustбыть включенным в файле конфигурации nginx, см. здесь
  • Состояние отправленного заголовка должно быть NGX_HTTP_OK, NGX_HTTP_FORBIDDEN или NGX_HTTP_NOT_FOUND
  • Кодировка содержимого должна быть установлена ​​(ngx_table_elt_)существует, и значение в должно иметь ненулевую длину
  • Значение content_length_n должно быть допустимым (не -1) и должно быть больше или равно значению gzip_min_length, указанному в файле конфигурации
  • ngx_http_test_content_type должен возвращать ненулевое значение, например, допустимый тип контекста
  • Запрос должен иметь заголовок и тело

См. здесь для получения дополнительной информации о модуле Nginx., Fillter и Handler Developmennt.

...