Spring-cloud-gateay에서 아래의 플로우로 호출이 존재할 때
Client - spring-cloud-gateway -> backend
backend로부터 온 응답을 확인하고 싶은 경우에 어떻게 response 내용을 조회할 수 있는지 알아보자.
기본으로 제공되는 필터들 중에 response를 조회하거나 조작하는 필터는 두 가지를 발견할 수 있었다.
ModifyRequestBody GatewayFilter Factory
The Netty Write Response Filter
각각의 필터에서 응답을 읽는 부분을 참고해 보면
ModifyRequestBody GatewayFilter Factory에서는 ServerHttpResponseDecorator를 이용해 exchange의 응답값을 읽어 들인다.
간략하게 나타내면 아래와 같이 정리할 수 있다.
GatewayFilterFactory에서는 innerClass인 Filter를 생성해서 넘기고
(보통은 람다로 표현하는데 내용이 길어서 그런지 따로 클래스로 분리한 모습)
Filter에서는 필터체인으로부터 넘겨받은 exchange를 새로 응답을 작성할 ServerHttpResponse에 전달한다.
(ServerHttpResponse도 내용이 길어지니 클래스로 분리)
ServerHttpResponse에서는 필터체인으로부터 넘겨받은 response를 writeWith 메서드에서 조작가능하다.
public class ModifyResponseBodyGatewayFilterFactory
extends AbstractGatewayFilterFactory<ModifyResponseBodyGatewayFilterFactory.Config> {
@Override
public GatewayFilter apply(Config config) {
ModifyResponseGatewayFilter gatewayFilter = new ModifyResponseGatewayFilter(config);
gatewayFilter.setFactory(this);
return gatewayFilter;
}
public class ModifyResponseGatewayFilter implements GatewayFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange.mutate().response(new ModifiedServerHttpResponse(exchange, config)).build());
}
}
protected class ModifiedServerHttpResponse extends ServerHttpResponseDecorator {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith( // 💡 DataBuffer를 String으로 변환해서 로깅
fluxBody.map(
dataBuffer -> {
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
// 💡 DataBuffer의 내용을 String으로 변환
String responseBody = new String(content, StandardCharsets.UTF_8);
log.info("Response Body: {}", responseBody);// 💡 로그로 출력
// 💡 DataBuffer 재생성
DataBufferUtils.release(dataBuffer); // 기존 DataBuffer 해제 (Memory Leak 방지)
return exchange.getResponse()
.bufferFactory()
.wrap(content); // 새로운 DataBuffer로 감싸서 반환
}));
}
}
}