跳转到主内容
极星编程网:以代码为星,赴技术山海!

网关层请求报文重构:在不改动后端代码情况下动态修改 POST 请求体内容

可在不改后端前提下,通过Spring Cloud Gateway过滤器动态重构POST请求体,核心是缓存原始body并重写getBody()以支持多次读取,同时同步更新Content-Type、移除Content-Length。 可以在不改后端的前提下,通过 Spring Cloud Gateway 的过滤器机制,在网关层动态重构 POST 请求体。核心是解决“请求体只能读一次”和“修改后需正确转发”两个关键问题。 为什么不能直接读取并修改 request.getBody()? Spring WebFlux 中的 ServerHttpRequest.getBody() 是一个 Flux 流,一旦被消费(比如解析 JSON),底层缓冲区就被释放,后续过滤器或路由转发时再调用就会返回空流 —— 这会导致下游服务收不到任何请求体,报 400 或空参数错误。 所以必须在首次读取后,将内容缓存并重新包装成可重复读取的请求对象。 标准做法:先缓存再重写 推荐使用两阶段全局过滤器配合官方 ModifyRequestBody : 第一阶段(缓存) :用最高优先级的
CacheBodyGlobalFilter
读取原始 body,转为 String 或 byte[],再用
ServerHttpRequestDecorator
重写
getBody()
方法,使其每次调用都返回缓存副本 第二阶段(重写) :在缓存就绪后,使用
ModifyRequestBodyGatewayFilterFactory
或自定义
GatewayFilter
对 body 做逻辑处理(如添加 tenantId、解密、字段增强等) 注意去掉
Content-Length
头,否则转发时长度与实际 body 不符,部分服务会拒绝请求 常见 POST 体重构场景与写法 假设原始请求是
application/json
,body 为:
{"userId":"123"}
,需注入
"tenantId":"t-888"
: 用
ModifyRequestBody
配置:指定 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
)保证解析一致性 不复杂但容易忽略。关键是缓存先行、装饰到位、头信息同步更新。

相关文章