Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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 ?

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)
                The weird thing is.. we don't need to call mutate for modifying response. Just exchange.response.headers.add("x-test-response", "test-value")  will works.
– aldok
                Dec 17, 2020 at 2:03
                Thanks a lot for this solution! I used it to add header to responses but it worked only for non-error responses. I resolved this problem by adding highest order for the filter bean: @Order(Ordered.HIGHEST_PRECEDENCE)
– Rib47
                Jul 20, 2021 at 12:00
                I am doing the same way. But sometimes, I got mentioned error. Not sure what I am missing. out 10-15 times, I use to get once or twice this error
– prasingh
                Feb 23, 2021 at 10:20
                I had a logical error. Pretty new in Reactive programming. But Your answer makes sense to me. Got the answer to my error.
– prasingh
                Feb 24, 2021 at 9:29
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.