Nginx gzip 过滤器不适用于我的自定义处理程序
Posted
技术标签:
【中文标题】Nginx gzip 过滤器不适用于我的自定义处理程序【英文标题】:Nginx gzip filter not work with my custom handler 【发布时间】: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);
【问题讨论】:
【参考方案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
下运行将允许您准确查看检查失败的时间和方式。 (如果你正在尝试这个,你可能应该从源代码编译......)
【讨论】:
以上是关于Nginx gzip 过滤器不适用于我的自定义处理程序的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的容器注册表适用于 gitlab 自动部署,但不适用于我的自定义管道?
<ReferenceArrayInput /> 不适用于我的自定义数据提供程序(棱镜)