Nginx的gzipfilter不能与我的自定义处理程序一起工作

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

代码与nginx(版本1.0.6)正常工作

但我发现gzipfilter不能与处理程序一起工作。

当我在nginx.conf中打开gzip(在http部分下)时,gzip使用静态html文件工作。

但是,处理程序的响应不是用gzip压缩的。

经过大量的search工作,我仍然找不到答案。

任何意见 ? 非常感谢。 🙂

//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); } 

如果还不算太晚,我的滤镜模块也有同样的问题。

问题与您更改响应Content-type有关。 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

首先你在哪里调用ngx_http_send_header(r);

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

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

你的处理程序是否产生错误? 如果没有过滤器将被称为?

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

  • 必须在nginx配置文件中启用Gzip才能看到这里
  • 发送的标题状态应该是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需要返回非null,例如一个有效的上下文类型
  • 该请求需要有一个标题和正文

有关Nginx模块,Fillter和Handler开发者的更多信息,请参阅这里 。

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

检查它的代码位于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 不能设置(这是有道理的:gzip将内容编码设置为“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下运行,可以让你精确地看到检查失败的时间和方式。 (你可能应该从源代码编译,如果你正在尝试这个…)