Nginx gzip过滤器无法使用我的自定义处理程序

时间:2011-12-08 07:19:02

标签: module nginx gzip handler

我写了一个非常简单的nginx处理程序,只输出一些文本(大小100B到10KB)。

代码可以正常使用nginx(ver 1.0.6)

但我发现gzip过滤器无法与处理程序一起使用。

当我在nginx.conf(在http部分下)打开gzip时,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 个答案:

答案 0 :(得分:1)

如果还不晚,我的滤镜模块也遇到了同样的问题。

问题与您更改响应内容类型的事实有关。 Gzip检查content_type_len和content_type_lowcase上的Content-Type以确定响应是否必须是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

答案 1 :(得分:0)

首先,您致电ngx_http_send_header(r);

您是否正在初始化ngx_buf_t *b的成员?

您的内容编码是否设置了请求?

你的处理程序是否会产生错误?如果是这样,将不会调用过滤器?

在处理程序调用时,需要满足以确保gzip过滤器运行(而不是被绕过)的其他约束包括

  • 必须在nginx配置文件中启用Gzip,请参阅here
  • 发送的标头状态应为NGX_HTTP_OK,NGX_HTTP_FORBIDDEN或NGX_HTTP_NOT_FOUND
  • 应设置内容编码(ngx_table_elt_t *必须存在且值in应为非零长度
  • content_length_n应该有效(不是-1)并且应该大于或等于配置文件中指定的gzip_min_length值
  • ngx_http_test_content_type需要返回非null,例如,有效的上下文类型
  • 请求需要有标题和正文

有关Nginx模块,Fillter和Handler开发的更多信息,请参阅here

答案 2 :(得分:0)

上述答案似乎......不准确。

检查此代码的代码位于src/http/modules/ngx_http_gzip_filter_module.c的第250行或附近,并显示为:

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将内容编码设置为&#34; gzip&#34;)
  • content_length_n(如果设置)必须大于最小长度(默认为20)。不设置内容长度是可以接受的。
  • content_type必须位于有效列表中。默认情况下,只有&#34; text / html&#34;已接受,但可以使用gzip_types配置选项设置其他类型。如果列表包含&#34; *&#34;,则任何内容类型(包括根本没有)都可以。
  • 必须有一些身体压缩

从版本1.7.10开始,上面的return位于第257行。设置&#34;守护程序关闭&#34;,在gdb和b ngx_http_gzip_filter_module.c:257下运行将允许您准确查看何时和支票如何失败。 (如果你正在尝试这个,你应该从源代码编译......)