BUG - Gateway: Exceeded limit on max bytes to buffer : 262144
总结
0. 配置最大限制
首先实现 WebFluxConfigurer 接口, 并重写 configureHttpMessageCodecs 方法
设置 ServerCodecConfigurer 中 defaultCodecs 的 maxInMemorySize, 这相当于解开最大限制
根据不同的使用情况有不同的处理方式
1. 默认 CacheRequestBodyGatewayFilterFactory
如果使用的是默认 CacheRequestBodyGatewayFilterFactory, 配置好就应该就可以了(没有测试过)
2. 自定义 Filter
如果使用的是自定义的 filter
检查是否使用了 HandlerStrategies.withDefaults().messageReaders() 语句
2.1 如果使用了该语句
将配置的 ServerCodecConfigurer 进行注入 (@Resource, @Autowired) 都可以
然后将 HandlerStrategies.withDefaults().messageReaders() 替换为 serverCodecConfigurer.getReaders() 即可
2.2 如果没有使用
我也不知道怎么办了, 求大神指教, (TwT)
代码
配置
package cn.moquan.gateway.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.config.WebFluxConfigurer;
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.defaultCodecs().maxInMemorySize(10 * 1024 * 1024);
}
}
使用
package cn.moquan.gateway.filter.global;
import cn.moquan.gateway.tool.RequestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage;
import org.springframework.cloud.gateway.support.BodyInserterContext;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
import java.util.function.Function;
public class CopyRequestBodyGlobalFilter implements GlobalFilter, Ordered {
@Resource
private ServerCodecConfigurer serverCodecConfigurer;
private static final Logger log = LoggerFactory.getLogger(CopyRequestBodyGlobalFilter.class);
/**
* 参考实现:
* org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory
*
* @param exchange the current server exchange
* @param chain provides a way to delegate to the next filter
*/
@Override
@SuppressWarnings("unchecked")
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.debug("go through copy request body global filter.");
if (RequestUtil.isGetRequest(exchange) || !RequestUtil.contextTypeIsJson(exchange)) {
// 非 json 请求直接放行
return chain.filter(exchange);
}
///////////////////////////////////////////////////////////// 就这里 ↓
ServerRequest serverRequest = ServerRequest.create(exchange, serverCodecConfigurer.getReaders());
Mono<String> requestBodyStrMono = serverRequest.bodyToMono(String.class)
.flatMap(Mono::just);
BodyInserter bodyInserter = BodyInserters.fromPublisher(requestBodyStrMono, String.class);
HttpHeaders headers = new HttpHeaders();
headers.putAll(exchange.getRequest().getHeaders());
headers.remove(HttpHeaders.CONTENT_LENGTH);
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
return bodyInserter.insert(outputMessage, new BodyInserterContext())
.then(Mono.defer(() -> {
ServerHttpRequest decorator = RequestUtil.decorateServerWebExchange(exchange, headers, outputMessage);
return chain.filter(exchange.mutate().request(decorator).build());
})).onErrorResume((Function<Throwable, Mono<Void>>) throwable ->
RequestUtil.releaseOutputMessageBodyDataBuffer(exchange, outputMessage, throwable)
);
}
@Override
public int getOrder() {
return 0;
}
}