最常用且推荐的方式是使用 output filter 模块在 header_filter 阶段修改 upstream 响应头,通过注册 ngx_http_output_header_filter_pt 类型函数到 ngx_http_top_header_filter 链表,安全读写 r->headers_out.* 中的 header 链表。

开发一个 Nginx 模块来修改后端返回的响应头(即 upstream 响应头),最常用且推荐的方式是使用 output filter 模块,在 HTTP 响应体发送给客户端前拦截并修改 header。Nginx 官方不提供直接“编辑响应头”的高级 API,需通过底层 filter 链机制实现。
理解关键时机:header_filter_handler
Nginx 的响应处理分为两个主要过滤阶段:header_filter 和 body_filter。要修改响应头(如 Set-Cookie、Location、X-Backend-Version 等),必须在 header_filter 阶段介入 —— 此时响应状态行和 headers 已由 upstream 生成完毕,但尚未发送给客户端。
- 该阶段回调函数类型为
ngx_http_output_header_filter_pt - 模块需注册到
ngx_http_top_header_filter链表头部,确保最早执行(或按需控制顺序) - 可安全读写
r->headers_out.*中的 header 链表(如headers_out.server、headers_out.set_cookie) - 注意:不能在此阶段调用
ngx_http_send_header()或触发发送;仅做修改,Nginx 后续自动序列化发送
核心步骤:编写最小可运行模块
以修改 Server 头为例,展示精简结构(C 语言):
- 定义配置结构(即使无配置项,也建议保留)
- 实现
ngx_http_foo_header_filter函数:检查r->headers_out.server是否存在,替换其值 - 实现
ngx_http_foo_body_filter(可为空,但需声明,否则可能跳过 header_filter) - 注册 handler:
ngx_http_next_header_filter = ngx_http_top_header_filter; ngx_http_top_header_filter = ngx_http_foo_header_filter; - 在
ngx_http_foo_module_ctx中挂载这两个 filter,并在postconfiguration回调中完成链表注入
修改特定 Header 的实用技巧
不同 header 的操作方式略有差异,因 Nginx 内部存储结构不同:
-
简单字符串 header(如 Server、X-Powered-By):
r->headers_out.server->value是ngx_str_t,可用ngx_str_set()或ngx_copy赋新值,再调用ngx_http_clear_content_length(r)(若影响长度) -
多值 header(如 Set-Cookie):
r->headers_out.set_cookie是单链表指针,需遍历r->headers_out.set_cookie->next,对每个节点的value做原地修改或替换整个节点(用ngx_list_push+ngx_http_clear_last_modified等辅助) -
删除 header:设对应字段为
NULL(如r->headers_out.server = NULL),或调用ngx_table_elt_t *h = ...; h->hash = 0;标记忽略 -
添加新 header:用
ngx_list_push(&r->headers_out.headers)创建新ngx_table_elt_t,填充key、value、hash,并确保hash != 0
编译与验证要点
模块需作为动态模块(.so)或静态编入 Nginx:
- 动态模块:Nginx ≥ 1.9.11,编译时加
--add-dynamic-module=/path/to/module,配置中用load_module modules/ngx_http_foo_filter_module.so; - 配置启用:在
http、server或location块中添加指令(如有),例如foo_header_filter on; - 调试建议:开启
error_log /path/error.log debug;,在 filter 函数中用ngx_log_debug打印r->headers_out.*结构,确认修改生效 - 验证方法:用
curl -I http://your.site查看响应头变化;注意浏览器可能缓存 header,优先用 curl 或清除缓存测试

















