mod_filter仅调度过滤器,不处理内容;filterdeclare与filterprovider必须成对且顺序正确,缺一不可,且须在setoutputfilter前声明,名称大小写敏感,匹配条件需与响应头完全一致。

mod_filter 本身不干活,只负责按条件把响应分发给真正干活的模块(比如 mod_substitute、mod_deflate、mod_ext_filter);漏掉 FilterDeclare 或 FilterProvider,或者顺序写反,整个流水线就静默失效。
FilterDeclare 和 FilterProvider 必须成对出现且顺序不能颠倒
FilterDeclare 只是注册一个名字,没逻辑也没副作用;FilterProvider 才真正绑定过滤器模块和触发条件。两者缺一不可,且必须在 SetOutputFilter 之前完成声明。
-
FilterDeclare后面的名字(如json_prettify)要和FilterProvider的第二个参数完全一致,大小写敏感 -
FilterProvider的第三个参数是匹配表达式,用 Perl 兼容正则:例如resp=Content-Type $application/json中的$表示“以…开头”,不是字面美元符 - 若想用环境变量控制(比如只在 DEBUG 模式下启用),写成
env=DEBUG,再配合RewriteRule [E]或SetEnvIf设置该变量 - 多个条件可用布尔运算符连接:
resp=Content-Type $application/json && env=DEBUG
FilterChain 和 SetOutputFilter 的作用域必须严格匹配
FilterChain 是启用某组已声明 provider 的开关,它只影响当前配置块(<virtualhost></virtualhost>、<directory></directory> 或 <location></location>)。SetOutputFilter 则是把具体 filter 名挂进输出链——但它不会自动识别未在当前作用域声明的名称。
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 如果在
<virtualhost></virtualhost>里写了FilterDeclare mysub和FilterProvider mysub,但在<directory></directory>里只写SetOutputFilter mysub,Apache 启动会报错:Invalid filter name 'mysub' - 常见稳妥写法:把
FilterDeclare、FilterProvider、FilterChain和SetOutputFilter全部放在同一块配置里 -
FilterChain支持叠加:FilterChain mysub json_prettify表示按顺序执行两个 provider
被调度的底层过滤器(如 mod_substitute / mod_ext_filter)自己负责数据边界和编码
mod_filter 不碰响应体,只是转发;真正解析、修改内容的是它调用的 provider。这意味着 MIME 类型是否匹配、字符编码是否一致、输入流是否完整,全由 provider 自己扛。
-
mod_substitute默认只处理text/*类型;若要处理application/json,得加FilterProtocol substitute change=,且FilterProvider的匹配条件必须包含该 MIME 类型 -
mod_ext_filter要求外部程序从stdin读完整响应体、写到stdout,且不能残留未读输入或阻塞等待——否则 Apache worker 会卡死 - 对二进制内容(如图片水印),必须关掉
EnableSendfile Off和EnableMMAP Off,否则数据直接绕过 filter
调试时最容易忽略的是模块加载状态和匹配条件大小写
哪怕配置全对,只要 mod_filter 或下游 provider 模块(如 mod_substitute、mod_ext_filter)没真正加载,整个链路就静默失效——没有错误日志,也没有任何输出变化。
- 检查模块是否加载:
httpd -M | grep filter(Linux/macOS)或apache2ctl -M | grep filter(Debian/Ubuntu) -
FilterProvider的匹配值(如resp=Content-Type $application/json)必须与响应头中实际值**完全一致**:大小写敏感,且含完整 MIME 字符串(application/json≠application/json; charset=utf-8) - 用
curl -I看响应头,确认Content-Type实际值;再用curl -v看响应体是否被修改,比只查配置更可靠
真正难的不是写几行配置,而是理解 mod_filter 只是“调度员”——它不解析内容、不校验编码、不处理超时、不保证 provider 存活。所有这些责任,都落在你选的 provider 和它的运行环境上。










