【问题标题】:Nginx gzip filter not work with my custom handlerNginx gzip 过滤器不适用于我的自定义处理程序
【发布时间】:2011-12-08 07:19:01
【问题描述】:

我写了一个非常简单的 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);
}

【问题讨论】:

    标签: module nginx gzip handler


    【解决方案1】:

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

    问题与您更改响应内容类型有关。 Gzip 检查 content_type_len 和 content_type_lowcase 上的 Content-Type 以确定是否必须对响应进行 Gzip 压缩。这段代码应该可以工作:

    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

    【讨论】:

      【解决方案2】:

      首先你在哪里给ngx_http_send_header(r);打电话?

      你在初始化ngx_buf_t *b的成员吗?

      您的请求集的内容编码是否?

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

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

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

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

      【讨论】:

        【解决方案3】:

        上面的答案似乎……不准确。

        检查这一点的代码位于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 将内容编码设置为“gzip”)
        • content_length_n,如果设置,必须大于最小长度(默认 20)。不设置内容长度是可以接受的。
        • content_type 必须在有效列表中。默认情况下,只接受“text/html”,但可以使用gzip_types 配置选项设置其他类型。如果列表中包含“*”,则任何内容类型(包括完全没有)都可以。
        • 一定要压缩一些实体

        从 1.7.10 版开始,上面的 return 位于第 257 行。设置“关闭守护程序”,在 gdb 和 b ngx_http_gzip_filter_module.c:257 下运行将允许您准确查看检查失败的时间和方式。 (如果你正在尝试这个,你可能应该从源代码编译......)

        【讨论】:

          猜你喜欢
          • 2020-09-13
          • 1970-01-01
          • 2017-08-21
          • 2016-09-16
          • 2019-10-03
          • 1970-01-01
          • 2013-04-22
          • 2020-12-09
          • 1970-01-01
          相关资源
          最近更新 更多