我正在使用Spring Cloud Gateway将请求转发到后端服务。由于我们的某些后端服务以gzip格式发送其结果,因此定义一个全局过滤器以便在处理路由之前解压缩,然后再将gzip发送给客户端之前似乎是个好主意。这样,就不必为每条路线都这样做。使用关于Stack Overflow的各种想法得出以下定义,以gzip处理步骤的结果。
@Component
public class GlobalGZipFilter implements GlobalFilter, Ordered {
private static final Logger log = LoggerFactory.getLogger(GlobalGZipFilter.class);
@Override
public int getOrder() {
return -2;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpResponse originalResponse = exchange.getResponse();
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
log.info("Content should be GZipped: {}", isGZipped(originalResponse));
if (isGZipped(originalResponse) && body instanceof Flux) {
Flux<? extends DataBuffer> flux = (Flux<? extends DataBuffer>) body;
return super.writeWith(flux.buffer().map(dataBuffers -> {
ByteOutputStream outputStream = new ByteOutputStream();
for (DataBuffer i : dataBuffers) {
byte[] array = new byte[i.readableByteCount()];
i.read(array);
outputStream.write(array);
}
String resultResponse = new String(outputStream.getBytes());
return bufferFactory.wrap(zipString(resultResponse));
}));
}
return super.writeWith(body); // if body is not a flux. never got there.
}
};
return chain
.filter(exchange
.mutate()
.response(decoratedResponse)
.build()); // replace response with decorator
}
流程是收集包含结果的缓冲区,将其转换为一个完整的byte[]
并使用gzip压缩此byte[]
。
结果似乎已正确处理,但只有在应用程序停止后,结果才会显示在客户端中。交易以某种方式在结束之前不会结束。是否需要确认结果或当前选择的流量不正确?
答案 0 :(得分:0)
在处理助焊剂或数据时,问题并不多。我忘记考虑的是,将要返回的内容压缩到gzip时,回复的长度会有所不同。根据压缩后的内容添加内容长度将达到目的:
String resultResponse = new String(outputStream.getBytes());
byte[] zippedResponse = zipString(resultResponse);
originalResponse.getHeaders().setContentLength(zippedResponse.length);
return bufferFactory.wrap(zippedResponse);