mod_proxy本身不处理响应体清洗,真正起作用的是mod_substitute,需与mod_filter协同工作,并严格依赖mime类型匹配和正则语法规范;必须启用mod_filter和mod_substitute模块,用addoutputfilterbytype显式声明目标类型,规则置于块内并正确转义,验证时需检查响应体而非仅响应头。
在虚拟主机层级用 mod_proxy 实现响应内容脱敏,本质是“代理 + 响应体改写”,但必须明确:mod_proxy 本身不处理响应体清洗,真正起作用的是 mod_substitute,它需与 mod_filter 协同工作,并严格依赖 mime 类型匹配和正则语法规范。
必须启用并协同的模块
仅开启 mod_proxy 不够,还需显式加载:
- mod_filter(提供输出过滤链基础)
- mod_substitute(唯一能对响应正文做正则替换的模块)
在虚拟主机配置开头添加:
LoadModule filter_module modules/mod_filter.so<br>LoadModule substitute_module modules/mod_substitute.so
Debian/Ubuntu 系统可运行 a2enmod filter substitute 启用。
精准匹配响应类型才能生效
mod_substitute 默认跳过 application/json、text/plain 等常见业务类型,必须用 AddOutputFilterByType 显式声明:
<virtualhost><br> # ... SSL 和 Proxy 配置<br> AddOutputFilterByType SUBSTITUTE text/html application/json text/plain<br></virtualhost>
注意:
• 若后端返回 Content-Type: application/json; charset=utf-8,Apache 2.4 默认不识别带参数的类型,application/json 就足够匹配;
• 不要写成 application/json;charset=utf-8,会失效。
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
脱敏规则写法与避坑要点
规则必须放在 <location></location> 或 <locationmatch></locationmatch> 块内,且需确保该路径实际返回目标内容类型:
<location><br> Substitute "s#\"idCard\":\"[0-9]{17}[0-9X]\"#\"idCard\":\"*************X\"#g"<br></location>
关键细节:
- 分隔符用
#替代默认/,避免与 JSON 内容冲突 - 双引号必须用
\"转义(Apache 中双引号是 Substitute 指令的分隔符) - 不能用
\d,只支持[0-9] - 若响应含换行(如美化 JSON),需加
i标志并禁用压缩:SetEnv no-gzip 1
验证是否真正生效
别只看 curl -I ——它只显示响应头。实操验证步骤:
- 用
curl -s https://yoursite.com/api/v1/user | python3 -m json.tool查看原始响应体 - 检查 Apache error.log,开启
LogLevel substitute:trace4可看到每条 Substitute 是否被触发、匹配了几处 - 确认后端未启用 Gzip 压缩(mod_substitute 对压缩内容无效)
不复杂但容易忽略。










