WebFlux: How to abort request processing in WebFilter with provided response

Viewed 2653

I'd like to do something like below in my WebFilter to optionally bypass subsequent filters and RestControllers:

if(shouldRedirect(exchange)){
  //do redirect
}else if(!canAccess(exchange)){
  //return a 403 response
}else{
  chain.filter(exchange);
}

How am I supposed to do that?

Thanks

Leon

2 Answers

Technically, the contract says that the filter has to return Mono<Void>, which completes when the exchange (request+response) has been processed.

The usual WebFilter does something on the request/response and then forwards the exchange to the next filter in the chain. But you can also unilaterally process the exchange and call it done.

In this sample, we're setting the status code and calling the response done.

class MyFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.NOT_FOUND);
        return response.setComplete();
    }

}

In addition to Brian's answer...

If you want to write some bytes in your response, you can:

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    exchange.getResponse().setStatusCode(HttpStatus.I_AM_A_TEAPOT);
    return exchange.getResponse().writeWith( Mono.just(exchange.getResponse().bufferFactory().wrap("233".getBytes(StandardCharsets.UTF_8))));
}

In case you have some model to write to your response, you can:

public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    Pet pet = new Pet("type", "petFromFilter");
    return ServerResponse.status(HttpStatus.I_AM_A_TEAPOT)
        .contentType(MediaType.APPLICATION_JSON)
        .body(BodyInserters.fromValue(pet))
        .flatMap(serverResponse -> serverResponse.writeTo(exchange, new Context() {
             @NonNull
             @Override
             public List<HttpMessageWriter<?>> messageWriters() {
                 // serverCodecConfigurer is an autowired field.
                 return serverCodecConfigurer.getWriters();
             }

             @NonNull
             @Override
             public List<ViewResolver> viewResolvers() {
                 return Collections.emptyList();
             }
}));

Related