Search code examples
spring-cloud-gatewayspring-filter

Spring Cloud Gateway Change Response


I have an app (app1) which sends requests to another app (app2) via Spring Cloud Gateway. Some end points on app2 are not ready yet so app2 returns 404 (not found) as usual but i would like to change 404 to 501 (Not Implemented). Is there any way to do it? What i did so far as follows:

spring.cloud.gateway.routes[0].id=app2  
spring.cloud.gateway.routes[0].uri=lb://app2
spring.cloud.gateway.routes[0].predicates[0]=Path=/1/app2/get/endPoint1/**,/1/app2/get/endPoint2/**,/1/app2/get/endPoint3/**,/1/app2/get/endPoint4/**
spring.cloud.gateway.routes[0].filters[0]=StripPrefix=1

endPoint1 and endPoint2 have been implemented but endPoint3 and endPoint4 not.
I have implemented following filter to modify 404 to 501 but status is always 200 (OK), even for unimplemented methods, but message on app1 is for unimplemented methods (Implemented methods have no problem).

{
"code": 404,
"type": "Not Found",
"message": "{\"timestamp\":\"2022-07-07T16:15:12.185+00:00\",\"status\":404,\"error\":\"Not Found\",\"message\":\"No message available\",\"path\":\"/app2/endPoint3\"}"  
}

How can i catch 404 and modify it as 501?

@Component
public class GatewayGlobalExceptionHandler implements GlobalFilter, Ordered {

@Override
public int getOrder() {
    return 100;
}

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    ServerHttpResponse originalResponse = exchange.getResponse();
    HttpStatus status = exchange.getResponse().getStatusCode();
    DataBufferFactory bufferFactory = originalResponse.bufferFactory();
    ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
        @Override
        public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
            if (body instanceof Flux) {
                Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                return super.writeWith(fluxBody.map(dataBuffer -> {
                    // probably i should reuse buffers 
                    byte[] content = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(content);
                    //BUT Content is not what i need.
                    return bufferFactory.wrap(uppedContent);
                }));
            }
            return super.writeWith(body); // if body is not a flux. never got there.
        }
    };
    return chain.filter(exchange.mutate().response(decoratedResponse).build());
}
}

Solution

  • to modify the error message i have implemented a Post-GlobalFilter. This way gave me a chance to modify the status. Also, i got 404 for unimplemented methods and 200 for implemented ones in post-GlobalFilter.

    @Configuration
    public class LoggingGlobalFiltersConfigurations {
    
    final Logger logger =
      LoggerFactory.getLogger(
        LoggingGlobalFiltersConfigurations.class);
    
    @Bean
    public GlobalFilter postGlobalFilter() {
        return (exchange, chain) -> {
            return chain.filter(exchange)
              .then(Mono.fromRunnable(() -> {
                  HttpStatus status = exchange.getResponse().getStatusCode();
                  //MAKE MODIFICATION HERE
              }));
        };
    }
    }