Throwing Custom Runtime exception in Spring Cloud Gateway Filters
Asked Answered
S

2

6

We are using Spring Cloud Gateway with Spring Boot 2 and reactive WebFlux module.

There is an authentication filter which is added for one of the routes. Now if we throw a RuntimeException with a particular status code, it is really not picking up.

Earlier this authentication check was part of the HandlerInterceptor in Spring, but now we cannot use the web module along with WebFlux (conflict from Spring cloud gateway).

Example:

@Override
public GatewayFilter apply(Object config) {
   ServerHttpRequest httpRequest = exchange.getRequest();
   if(!someUtil.validRequest(httpRequest) {
          throw new RuntimeException("Throw 401 Unauthorized with Custom error code and message");
   }
}

Currently, the actual response always gives a 500 internal server error. From where is this coming from? Can we get hold of the errors from Filters here?

Skunk answered 23/5, 2018 at 5:39 Comment(0)
P
2

You can implement a custom error handler, and here is the Spring Boot document.

Or you can simply throw a ResponseStatusException. The default error handler will render the specific status.

Parasympathetic answered 3/8, 2018 at 6:48 Comment(1)
Throwing a ResponseStatusException with a custom HTTP status code did work for me, but it still bypassed by Spring Boot @ControllerAdvice controller.Stivers
D
-1

Keep in mind, as of the time of writing, spring-cloud-gateway uses Spring Framework WebFlux. This means that the approach would be different. You can get hold of the exception in a filter as shown below.

Declare an exception like this:

public class UnauthorisedException extends ResponseStatusException {

    public UnauthorisedException(HttpStatusCode status) {
        super(status);
    }

    public UnauthorisedException(HttpStatusCode status, String reason) {
        super(status, reason);
    }

}

NB: The exception extends ResponseStatusException.

The ControllerAdvice class can be implemented as follows:

@ControllerAdvice
public class MyErrorWebExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(UnauthorisedException.class)
    public Mono<ServerResponse> handleIllegalState(ServerWebExchange exchange, UnauthorisedException exc) {
         exchange.getAttributes().putIfAbsent(ErrorAttributes.ERROR_ATTRIBUTE, exc);
return ServerResponse.from(ErrorResponse.builder(exc,HttpStatus.FORBIDDEN,exc.getMessage()).build());
    }

}

In your filter you can now implement the apply method as follows:

public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
                if (request.getHeaders().get("token") == null){ //test is an example
                    throw new UnauthorisedException(HttpStatus.FORBIDDEN, "Not Authorised from Gateway");
                }
            ServerHttpRequest.Builder builder = request.mutate();
            return chain.filter(exchange.mutate().request(builder.build()).build());
        };
    }
Decile answered 10/12, 2022 at 14:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.