在虚拟主机层级用mod_filter构建响应处理流水线,需严格对齐声明、触发与启用三要素,先加载依赖模块(如substitute、deflate),再按序声明FilterDeclare、FilterProvider、FilterChain和SetOutputFilter,注意MIME类型匹配、二进制资源需禁用sendfile/mmap,外部程序须规范读写与超时。
在虚拟主机层级用 mod_filter 构建响应处理流水线,核心是把过滤逻辑声明、触发条件、启用开关三者严格对齐到同一作用域,并确保底层执行模块(如 mod_substitute、mod_deflate)已就位。它不是写个命令就生效的“插件”,而是一套需顺序严谨、上下文一致的声明式流水线。
必须先完成模块加载与基础声明
mod_filter 本身不干活,只做路由;真正处理响应的是它调度的其他模块。所以第一步不是写 FilterProvider,而是确认依赖模块已启用:
- 运行 httpd -M | grep -E "(filter|substitute|deflate|ext_filter)",确保输出含 filter_module、substitute_module(或其他要用的模块)
- 若缺失,Debian/Ubuntu 执行 a2enmod filter substitute,RHEL/CentOS 编辑 /etc/httpd/conf.modules.d/00-base.conf 取消对应 LoadModule 行注释
- FilterDeclare 必须出现在任何 FilterProvider 之前,且名称要和后续 FilterProvider 的第二个参数完全一致,例如:
FilterDeclare json_prettify
用 FilterProvider 绑定内容类型与执行器
FilterProvider 是实际“接单”的环节,它决定什么响应走哪条路。匹配条件必须精确反映真实响应头,大小写敏感,且支持正则锚点:
- 匹配 JSON 响应:FilterProvider json_prettify resp=Content-Type $application/json($ 表示“以…开头”,不是美元符)
- 想同时限定环境变量(如仅开发环境启用):FilterProvider json_prettify resp=Content-Type $application/json && env=DEBUG
- 若用 mod_substitute 处理非 text/* 类型(如 application/json),必须加 FilterProtocol substitute change=,否则默认被跳过
在 VirtualHost 内统一启用并控制执行顺序
FilterChain 和 SetOutputFilter 必须放在同一个
- 错误写法:FilterDeclare 在全局,SetOutputFilter 在 VirtualHost 里——报错 Invalid filter name
- 正确写法(全部放在 VirtualHost 内):
FilterDeclare json_prettify
FilterProvider json_prettify resp=Content-Type $application/json
FilterChain json_prettify
SetOutputFilter json_prettify - 要叠加多个处理(如先压缩再美化):FilterChain deflate json_prettify,执行顺序按列出顺序
注意静态资源绕过问题(尤其图片水印等场景)
如果目标是处理 .jpg/.png 等二进制响应,mod_ext_filter 很可能静默失效——因为 Apache 默认启用 sendfile 和 mmap,直接由内核发文件,根本不经过 filter 流水线:
- 必须在 VirtualHost 内显式关闭:EnableSendfile Off 和 EnableMMAP Off
- 确保 AddOutputFilter(或 SetOutputFilter)绑定的是实际响应头中的 MIME 类型,比如 image/jpeg,而不是扩展名
- 外部程序(如水印脚本)必须严格读完 stdin、立即退出,且设 timeout(如 timeout=5),避免阻塞 worker










