如何在Spring Cloud Gateway的ModifyRequestBodyGatewayFilterFactory中增大缓冲区上限
解决自定义ModifyRequestBodyGatewayFilter的DataBufferLimitException问题
你遇到的问题是因为自定义的ModifyRequestBody过滤器在读取请求体时,使用的是默认256KB的缓冲区限制,而全局的spring.codec.max-in-memory-size和WebFluxConfigurer配置不会直接作用于这个过滤器的请求体读取逻辑。以下是适配ModifyRequestBody场景的解决方案:
步骤1:在过滤器配置类中添加缓冲区大小参数
首先,在自定义过滤器的内部配置类中新增maxInMemorySize属性,用于接收自定义的缓冲区上限:
public class CustomModifyRequestBodyGatewayFilterFactory extends ModifyRequestBodyGatewayFilterFactory { public CustomModifyRequestBodyGatewayFilterFactory() { super(Config.class); } public static class Config extends ModifyRequestBodyGatewayFilterFactory.Config { // 默认保持256KB,可通过配置修改 private int maxInMemorySize = 262144; public int getMaxInMemorySize() { return maxInMemorySize; } public void setMaxInMemorySize(int maxInMemorySize) { this.maxInMemorySize = maxInMemorySize; } } // 后续apply方法修改见步骤2 }
步骤2:修改请求体读取逻辑,指定缓冲区上限
在过滤器的apply方法中,替换原有的请求体读取代码,显式使用自定义的maxInMemorySize限制。这里提供两种实现方式:
方式一:使用DataBufferUtils.join指定限制
直接操作DataBuffer流,通过DataBufferUtils.join的重载方法指定缓冲区上限:
@Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { // 获取自定义的缓冲区大小 int maxSize = config.getMaxInMemorySize(); // 读取请求体时指定上限 return DataBufferUtils.join(exchange.getRequest().getBody(), maxSize) .flatMap(dataBuffer -> { // 将DataBuffer转换为字节数组(根据你的业务需求调整) byte[] requestBody = new byte[dataBuffer.readableByteCount()]; dataBuffer.read(requestBody); DataBufferUtils.release(dataBuffer); // 这里替换成你的请求体处理逻辑,比如修改body后重新构建请求 ModifiedServerHttpRequest modifiedRequest = new ModifiedServerHttpRequest( exchange.getRequest(), requestBody); return chain.filter(exchange.mutate().request(modifiedRequest).build()); }) .onErrorResume(DataBufferLimitException.class, ex -> { // 可选:自定义异常处理逻辑 return Mono.error(new IllegalArgumentException("请求体大小超过限制")); }); }; }
方式二:通过ServerRequest和BodyExtractors指定限制
利用Spring WebFlux的ServerRequest和BodyExtractors,显式设置读取上限:
// 需要注入ServerCodecConfigurer获取messageReaders private final ServerCodecConfigurer serverCodecConfigurer; public CustomModifyRequestBodyGatewayFilterFactory(ServerCodecConfigurer serverCodecConfigurer) { super(Config.class); this.serverCodecConfigurer = serverCodecConfigurer; } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { int maxSize = config.getMaxInMemorySize(); ServerRequest serverRequest = ServerRequest.create(exchange, serverCodecConfigurer.getReaders()); // 使用BodyExtractors指定maxInMemorySize return serverRequest.body(BodyExtractors.toMono(byte[].class).maxInMemorySize(maxSize)) .flatMap(requestBody -> { // 你的请求体处理逻辑,比如修改后构建新请求 ModifiedServerHttpRequest modifiedRequest = new ModifiedServerHttpRequest( exchange.getRequest(), requestBody); return chain.filter(exchange.mutate().request(modifiedRequest).build()); }); }; }
步骤3:配置过滤器的缓冲区大小
在网关配置文件(如application.yml)中,为自定义过滤器指定缓冲区上限:
spring: cloud: gateway: routes: - id: your_route_id uri: http://your_target_service filters: - name: CustomModifyRequestBody # 你的过滤器名称 args: maxInMemorySize: 5242880 # 5MB,根据需求调整
关键说明
全局的spring.codec.max-in-memory-size和WebFluxConfigurer的配置之所以无效,是因为ModifyRequestBodyGatewayFilterFactory的默认实现是直接操作原始DataBuffer流,并未复用全局配置的HttpMessageReader读取逻辑,因此必须在过滤器内部显式指定缓冲区上限。
内容的提问来源于stack exchange,提问作者programmer
相关产品推荐
相关产品推荐

