i want to return custom response from spring cloud gateway custom filter without forwarding the request to next filter/service. i have written following code.
@Component public class AuthFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
final ServerHttpRequest request = exchange.getRequest();
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
String secretKey=null;
if (request != null) {
String serviceId = util.getServiceId(route.getUri().getAuthority());
if (StringUtils.isEmpty(serviceId)) {
serviceId = route.getUri().getAuthority();
}
if (this.externalApis.contains(serviceId)) {
return DataBufferUtils.join(exchange.getRequest().getBody())
.flatMap(dataBuffer -> {
DataBufferUtils.retain(dataBuffer);
Flux<DataBuffer> cachedFlux = Flux
.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(
exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return cachedFlux;
}
};
exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, cachedFlux);
System.out.println(gatewayUtil.toRaw(cachedFlux));
Response responseObject= runApi(exchange,chain);
ServerHttpResponseDecorator serverHttpResponseDecorator = gatewayUtil.customResponse(exchange, responseObject);
return chain.filter(exchange.mutate().request(mutatedRequest)
.response(gatewayUtil.customResponse(exchange,responseObject)).build());
});
}
}
and the response object created as follows
public ServerHttpResponseDecorator customResponse(ServerWebExchange exchange,Object responseObj) {
ServerHttpResponse originalResponse = exchange.getResponse();
return new ServerHttpResponseDecorator(originalResponse) {
HttpHeaders headers = new HttpHeaders();
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
@Override
public Mono<Void> writeWith(final Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
return bufferFactory.wrap("this is external".getBytes());
}).switchIfEmpty(Flux.defer(() -> {
System.out.println("Write to database here");
return Flux.just();
}))).onErrorResume(err -> {
// log.error("error while decorating Response: {}", err.getMessage());
return Mono.empty();
});
}
else {
System.out.println("2000000000");
}
return super.writeWith(body);
}
};
}
i want to return customer response back to client. please provide me a solution.