Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webflux, How to intercept a request and add a new header

Using Webflux filter, I am trying to intercept the requests and check if the request is coming from certain URI then add a new Authorization header

The filter code is simple and straightforward

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class AuthorizationFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {

        return chain.filter(Optional.of(exchange)
                .filter(serverWebExchange -> serverWebExchange.getRequest().getURI().getPath().endsWith("/callback"))
                .map(serverWebExchange -> addNewHeader(serverWebExchange))
                .orElse(exchange));
    }

    private ServerWebExchange addNewHeader(ServerWebExchange serverWebExchange) {

        String authHeader=serverWebExchange.getRequest().getQueryParams().get("state").get(0);

        if (authHeader == null) {
            throw new BadRequestException("State not complete (access_token missing) for //callback");
        }

        try {
            serverWebExchange.getRequest().getHeaders().setBearerAuth(authHeader);
        }catch (Throwable t){
            t.printStackTrace();
        }

        return serverWebExchange;
    }
}

But it throws an exception

java.lang.UnsupportedOperationException
    at org.springframework.http.ReadOnlyHttpHeaders.set(ReadOnlyHttpHeaders.java:99)
    at org.springframework.http.HttpHeaders.setBearerAuth(HttpHeaders.java:774)

It seems the header map is read only.How can i overcome this issue and add the new Header ?

like image 574
Melad Basilius Avatar asked Oct 15 '19 14:10

Melad Basilius


2 Answers

You can mutate the ServerWebExchange and its ServerHttpRequest with their mutate() methods which returns a 'Builder' for each of them.

Example Java:

@Component
public class AuthorizationFilter implements WebFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpRequest mutatedRequest = exchange.getRequest().mutate().header(HttpHeaders.AUTHORIZATION, "Bearer " + authHeader).build();
        ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build();
        return chain.filter(mutatedExchange);
    }
}

Example Kotlin:

@Component
class AuthorizationFilter : WebFilter {
    override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
        val mutatedRequest = exchange.request.mutate().header(HttpHeaders.AUTHORIZATION, "Bearer $authHeader").build()
        val mutatedExchange = exchange.mutate().request(mutatedRequest).build()
        return chain.filter(mutatedExchange)
    }
}
like image 184
gmeiner.m Avatar answered Oct 22 '22 03:10

gmeiner.m


The problems caused because you add a new header in the map operator of the chain, in this case webflux finilized serverWebExchange and it is immutable. You just need to add a header before calling chain.filter(...).

like image 42
Yauhen Balykin Avatar answered Oct 22 '22 04:10

Yauhen Balykin