ngx_http_gzip_header_filter 1 定义ngx_http_gzip_header_filter 函数 定义在 src/http/modules/ngx_http_gzip_filter_module.cstaticngx_int_tngx_http_gzip_header_filter(ngx_http_request_t*r){ngx_table_elt_t*h;ngx_http_gzip_ctx_t*ctx;ngx_http_gzip_conf_t*conf;confngx_http_get_module_loc_conf(r,ngx_http_gzip_filter_module);if(!conf-enable||(r-headers_out.status!NGX_HTTP_OKr-headers_out.status!NGX_HTTP_FORBIDDENr-headers_out.status!NGX_HTTP_NOT_FOUND)||(r-headers_out.content_encodingr-headers_out.content_encoding-value.len)||(r-headers_out.content_length_n!-1r-headers_out.content_length_nconf-min_length)||ngx_http_test_content_type(r,conf-types)NULL||r-header_only){returnngx_http_next_header_filter(r);}r-gzip_vary1;#if(NGX_HTTP_DEGRADATION){ngx_http_core_loc_conf_t*clcf;clcfngx_http_get_module_loc_conf(r,ngx_http_core_module);if(clcf-gzip_disable_degradationngx_http_degraded(r)){returnngx_http_next_header_filter(r);}}#endifif(!r-gzip_tested){if(ngx_http_gzip_ok(r)!NGX_OK){returnngx_http_next_header_filter(r);}}elseif(!r-gzip_ok){returnngx_http_next_header_filter(r);}ctxngx_pcalloc(r-pool,sizeof(ngx_http_gzip_ctx_t));if(ctxNULL){returnNGX_ERROR;}ngx_http_set_ctx(r,ctx,ngx_http_gzip_filter_module);ctx-requestr;ctx-buffering(conf-postpone_gzipping!0);ngx_http_gzip_filter_memory(r,ctx);hngx_list_push(r-headers_out.headers);if(hNULL){returnNGX_ERROR;}h-hash1;h-nextNULL;ngx_str_set(h-key,Content-Encoding);ngx_str_set(h-value,gzip);r-headers_out.content_encodingh;r-main_filter_need_in_memory1;ngx_http_clear_content_length(r);ngx_http_clear_accept_ranges(r);ngx_http_weak_etag(r);returnngx_http_next_header_filter(r);}2 目的ngx_http_gzip_header_filter是 Nginx Gzip 压缩模块的头部过滤器。它的设计目的和必要性紧密围绕 HTTP 内容压缩这一核心功能。这个函数的核心任务是在响应头发送之前决定是否对当前响应启用 Gzip 压缩。如果启用则做好所有的初始化和响应头修改工作为后续的响应体压缩由ngx_http_gzip_body_filter完成准备好运行环境。3 详解1 函数签名staticngx_int_tngx_http_gzip_header_filter(ngx_http_request_t*r)1 返回值类型ngx_int_t返回一个整数状态码表示执行结果NGX_OK 成功NGX_ERROR 出错。2ngx_http_gzip_header_filter函数名表示 HTTP Gzip 模块的头部过滤器。3ngx_http_request_t *r参数r是指向当前 HTTP 请求结构体的指针包含请求的所有信息。2 逻辑流程1 条件过滤 筛选掉不需要 gzip 压缩的请求 2 处理需要 gzip 压缩的请求{ngx_table_elt_t*h;ngx_http_gzip_ctx_t*ctx;ngx_http_gzip_conf_t*conf;局部变量声明confngx_http_get_module_loc_conf(r,ngx_http_gzip_filter_module);获取 location 配置1 条件过滤if(!conf-enable||(r-headers_out.status!NGX_HTTP_OKr-headers_out.status!NGX_HTTP_FORBIDDENr-headers_out.status!NGX_HTTP_NOT_FOUND)||(r-headers_out.content_encodingr-headers_out.content_encoding-value.len)||(r-headers_out.content_length_n!-1r-headers_out.content_length_nconf-min_length)||ngx_http_test_content_type(r,conf-types)NULL||r-header_only){returnngx_http_next_header_filter(r);}快速退出条件检查只要任何一个条件为真就不进行Gzip压缩直接调用下一个头部过滤器并返回。各条件详解!conf-enable配置中gzip未开启值为 off 或 0。(r-headers_out.status ! NGX_HTTP_OK ...)响应状态码不是 200、403、404 之一。Gzip只对少数成功或部分错误状态的响应体进行压缩避免浪费资源于无意义的响应如 301 重定向没有响应体。(r-headers_out.content_encoding r-headers_out.content_encoding-value.len)响应头中已经存在Content-Encoding例如上游已经压缩过不能再压缩否则会损坏数据。(r-headers_out.content_length_n ! -1 r-headers_out.content_length_n conf-min_length)如果 Content-Length 已知不是 -1且其值小于 min_length 配置默认 20 字节压缩没有意义还可能增大体积跳过。ngx_http_test_content_type(r, conf-types) NULL响应的 Content-Type 不在 gzip_types 指定的类型列表中默认只有 text/html。r-header_only这是一个 HEAD 请求只要求返回响应头没有响应体无需压缩。这些检查在头部过滤器执行此时响应状态码、内容长度、内容类型等均已确定因此能够准确判断。任何条件不满足都会导致函数直接放行开销极低。2 处理需要 gzip 压缩的请求r-gzip_vary1;#if(NGX_HTTP_DEGRADATION){ngx_http_core_loc_conf_t*clcf;clcfngx_http_get_module_loc_conf(r,ngx_http_core_module);if(clcf-gzip_disable_degradationngx_http_degraded(r)){returnngx_http_next_header_filter(r);}}#endifif(!r-gzip_tested){if(ngx_http_gzip_ok(r)!NGX_OK){returnngx_http_next_header_filter(r);}}elseif(!r-gzip_ok){returnngx_http_next_header_filter(r);}ctxngx_pcalloc(r-pool,sizeof(ngx_http_gzip_ctx_t));if(ctxNULL){returnNGX_ERROR;}ngx_http_set_ctx(r,ctx,ngx_http_gzip_filter_module);ctx-requestr;ctx-buffering(conf-postpone_gzipping!0);ngx_http_gzip_filter_memory(r,ctx);hngx_list_push(r-headers_out.headers);if(hNULL){returnNGX_ERROR;}h-hash1;h-nextNULL;ngx_str_set(h-key,Content-Encoding);ngx_str_set(h-value,gzip);r-headers_out.content_encodingh;r-main_filter_need_in_memory1;ngx_http_clear_content_length(r);ngx_http_clear_accept_ranges(r);ngx_http_weak_etag(r);returnngx_http_next_header_filter(r);}