可在不改后端前提下,通过Spring Cloud Gateway过滤器动态重构POST请求体,核心是缓存原始body并重写getBody()以支持多次读取,同时同步更新Content-Type、移除Content-Length。

可以在不改后端的前提下,通过 Spring Cloud Gateway 的过滤器机制,在网关层动态重构 POST 请求体。核心是解决“请求体只能读一次”和“修改后需正确转发”两个关键问题。
为什么不能直接读取并修改 request.getBody()?
Spring WebFlux 中的 ServerHttpRequest.getBody() 是一个 Flux
所以必须在首次读取后,将内容缓存并重新包装成可重复读取的请求对象。
标准做法:先缓存再重写
推荐使用两阶段全局过滤器配合官方 ModifyRequestBody:
-
第一阶段(缓存):用最高优先级的
CacheBodyGlobalFilter读取原始 body,转为 String 或 byte[],再用ServerHttpRequestDecorator重写getBody()方法,使其每次调用都返回缓存副本 -
第二阶段(重写):在缓存就绪后,使用
ModifyRequestBodyGatewayFilterFactory或自定义GatewayFilter对 body 做逻辑处理(如添加 tenantId、解密、字段增强等) - 注意去掉
Content-Length头,否则转发时长度与实际 body 不符,部分服务会拒绝请求
常见 POST 体重构场景与写法
假设原始请求是 application/json,body 为:{"userId":"123"},需注入 "tenantId":"t-888":
- 用
ModifyRequestBody<string string></string>配置:指定 inClass=String.class,outClass=String.class - 在
rewriteFunction中解析原始 JSON,put 新字段,再序列化回字符串 - 设置新
contentType为MediaType.APPLICATION_JSON,确保下游能正确识别 - 若原始是
application/x-www-form-urlencoded,需先解析为 Map,修改后再拼成key1=val1&key2=val2格式
绕过限制的替代方案
当 ModifyRequestBody 不适用(如需兼容 multipart 或二进制流),可手动装饰:
- 继承
ServerHttpRequestDecorator,重写getBody()返回自定义 Flux - 重写
getHeaders()动态更新Content-Type和移除Content-Length - 对非 JSON 类型(如 Protobuf、XML),需配套使用对应的消息读写器(
HttpMessageReader)保证解析一致性
不复杂但容易忽略。关键是缓存先行、装饰到位、头信息同步更新。

















