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