WebFlux(reactor)中獲取完整response body數據


場景
使用Spring Cloud Gateway(SCG)時,想在網關日志中輸出返回日志,但由於數據流只能被讀取一次,必須使用特定方式進行重寫才能正常返回到前端。

處理過程
起初使用fluxBody.map讀取數據流,會出現多次輸出的情況,由於使用的時reactor框架處理數據,導致會出現將一個結果集分為多次處理,會執行多次map,效果不理想。
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
Mono<Void> newMono = super.writeWith(
fluxBody.map(dataBuffer -> {
String respBody = dataBuffer.toString(StandardCharsets.UTF_8);
if (respBody.length() > maxLogLength) {
respBody = respBody.substring(0, maxLogLength);
}
if (PathUtil.checkPath(request.getPath().value(), contentLengthUrls)) {
httpHeaders.setContentLength(respBody.length());
}
//匹配是否需要生成slat
if (PathUtil.checkPath(request.getPath().value(), loginUrls)) {
String salt = createSlat(JSON.parseObject(respBody).getString("token"));
if (StringUtils.isEmpty(salt)) {
logger.warn("CreateSalt error:id={}", request.getHeaders().getFirst(HEADER_REQUEST_ID));
} else {
httpHeaders.add("s", salt);
}
}
logger.info("fgwResponse : id={},body = {}", request.getHeaders().getFirst(HEADER_REQUEST_ID), respBody);
return bufferFactory.wrap(content);
})
);
//request中有salt則返回到response中
logger.info("fgwResponse : id={},resp = {}", request.getHeaders().getFirst(HEADER_REQUEST_ID), JSON.toJSONString(exchange.getResponse()));
return newMono;
最后查看github上的討論,開發者給出DataBufferUtils.join(body) .doOnNext的方式。
@Component
public class LogRespFilter implements GlobalFilter, Ordered {

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpResponse originalResponse = exchange.getResponse();
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
//修改header
HttpHeaders httpHeaders = originalResponse.getHeaders();
httpHeaders.add("xxxxxx","aaaaaa");
//輸出返回結果
if (body instanceof Flux) {
Mono<Void> newMono = super.writeWith(
DataBufferUtils.join(body)
.doOnNext(dataBuffer -> {
String respBody = dataBuffer.toString(StandardCharsets.UTF_8);
//輸出body
logger.info("fgwResponse : body = {}", respBody);
})
);
//輸出response,不包含body
logger.info("fgwResponse : resp = {}", JSON.toJSONString(exchange.getResponse()));
return newMono;

}
return super.writeWith(body);
}
};
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}
}

————————————————
版權聲明:本文為CSDN博主「lizz666」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/lizz861109/article/details/106303929


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM