You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Cloud Gateway自定义过滤器:请求体转请求头后控制器丢失请求体

问题分析与解决方案

问题根源

  • WebFlux中请求体是一次性消费的Flux<DataBuffer>,读取原请求体后若不重新生成请求体数据,后续链路(如控制器)将无法获取请求体
  • 原代码仅尝试修改请求头,但未将读取到的请求体重新封装回新请求中,导致后续请求体丢失
  • 直接释放原DataBuffer后,没有为后续流程提供可读取的请求体数据源

修正后的代码

@Component
@Slf4j
public class GetFormGatewayFilterFactory extends AbstractGatewayFilterFactory<GetFormGatewayFilterFactory.Config> {
    public GetFormGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            return DataBufferUtils.join(exchange.getRequest().getBody())
                    .flatMap(dataBuffer -> {
                        // 读取请求体字节数组
                        byte[] bytes = new byte[dataBuffer.readableByteCount()];
                        dataBuffer.read(bytes);
                        // 释放原DataBuffer资源
                        DataBufferUtils.release(dataBuffer);

                        String body = new String(bytes, StandardCharsets.UTF_8);
                        log.debug("读取到请求体内容: {}", body);

                        // 基于原请求体字节重新创建DataBuffer,供后续链路读取
                        DataBuffer newDataBuffer = exchange.getResponse().bufferFactory().wrap(bytes);
                        // 保留buffer引用,防止被提前释放
                        DataBufferUtils.retain(newDataBuffer);

                        // 构建新请求:添加自定义请求头,同时替换请求体为重新生成的DataBuffer
                        ServerHttpRequest newRequest = exchange.getRequest().mutate()
                                .header("headerName", body)
                                .body(Mono.just(newDataBuffer))
                                .build();

                        // 使用新的Exchange继续执行网关链路
                        return chain.filter(exchange.mutate().request(newRequest).build());
                    })
                    // 处理请求体为空的场景,避免链路中断
                    .switchIfEmpty(chain.filter(exchange));
        };
    }

    public static class Config {
        // 可在此添加过滤器配置属性
    }
}

关键说明

  • 重新生成请求体:读取原请求体后,必须通过bufferFactory().wrap(bytes)创建新的DataBuffer,并将其设置为新请求的body,确保后续链路能读取到请求体
  • 资源管理:使用DataBufferUtils.retain保证新创建的DataBuffer不会被提前释放,避免后续读取时出现资源已释放的错误
  • 空请求体处理:通过switchIfEmpty处理请求体为空的情况,确保链路能正常执行
  • 请求头设置:在新请求中添加自定义请求头,确保后续链路能获取到该头部信息

内容的提问来源于stack exchange,提问作者노민영

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 15:17:41