Search code examples
spring-bootspring-cloud-gatewayspring-filter

Can I conditionally skip other filters in Spring Cloud Gateway?


I set GlobalFilter whose order is -1, to check if the jwt in request header is valid. If not valid, I response with header which says client to redirect to login page. If it turns out to be invalid, there is no need to meet other filters. Can I temporally disable other filters in chain and directly send response?

@Order(-1)
@Component
public class JwtRequestFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        try {
            String token = exchange.getRequest().getHeaders().get("Authorization").get(0).substring(7);
        } catch (NullPointerException e) {
            logger.warn("no token.");
            //exchange.getResponse().setStatusCode(HttpStatus.valueOf(401));
            exchange.getResponse().getHeaders().set("status", "401");
            logger.info("status code :" + exchange.getResponse().getStatusCode());
        }
        return chain.filter(exchange);
    }

}

Additionally, I found that exchange.getResponse().setStatusCode(HttpStatus.valueOf(401)); does not work but exchange.getResponse().getHeaders().set("status", "401"); works. Why it is not changed with setStatusCode? I got 401 from both code when I log right after I set the status code, but using curl I always got 200. `


Solution

  • Yes you can. In your example you have to break chain by returning empty Mono<Void>. It should look like as following:

    @Order(-1)
    @Component
    public class JwtRequestFilter implements GlobalFilter {
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            try {
                String token = exchange.getRequest().getHeaders().get("Authorization").get(0).substring(7);
            } catch (NullPointerException e) {
                logger.warn("no token.");
                //exchange.getResponse().setStatusCode(HttpStatus.valueOf(401));
                exchange.getResponse().getHeaders().set("status", "401");
                logger.info("status code :" + exchange.getResponse().getStatusCode());
                return Mono.empty();
            }
            return chain.filter(exchange);
        }
    
    }
    

    If you don't do it then chain is executed further without care of your logic. You see 200 status responses as your request is properly routed to the destination service which returns typical response. More over your response headers are overwritten by netty. Because of that you can't see 401 response code.