How to set multiple headers at once in Spring WebClient?
Asked Answered
M

4

37

I was trying to set headers to my rest client but every time I have to write

webclient.get().uri("blah-blah")
         .header("key1", "value1")
         .header("key2", "value2")...

How can I set all headers at the same time using headers() method?

Mickey answered 2/12, 2019 at 6:13 Comment(2)
Read the API for the headers(Consumer<HttpHeaders> headersConsumer) method. You provide a Consumer<HttpHeaders> which can use any of the MultiValueMap methods of HttpHeadersEst
@Est The PO is looking for a Supplier not a ConsumerBertold
C
52

If those headers change on a per request basis, you can use:

webClient.get().uri("/resource").headers(httpHeaders -> {
    httpHeaders.setX("");
    httpHeaders.setY("");
});

This doesn't save much typing; so for the headers that don't change from one request to another, you can set those as default headers while building the client:

WebClient webClient = WebClient.builder().defaultHeader("...", "...").build();
WebClient webClient = WebClient.builder().defaultHeaders(httpHeaders -> {
    httpHeaders.setX("");
    httpHeaders.setY("");
}).build();
Clamant answered 5/12, 2019 at 9:29 Comment(5)
cannot understand httpHeaders -> {} part.. can you explain it with a proper example please?Mccallister
This is a proper example actually it is a really really good one. If you do not understand it you probably need to look into lambda and functional interfaces. If just starting out do not expect it to be a quick thing to learn it is hard to grasp first time around it :)Crank
@PlickPlick, do you know if there is something that we can use as network interceptor in case the request of the WebClient returns a 401 UNAUTHORIZED? so we can call a logic to refresh tokens and then recall the last call?Disputant
Check onSuccess onError and onErrorResume. baeldung.com/spring-webflux-errorsCrank
But I'm actually not really sure what you mean by network interceptor. Also I have resently started using webclients so probably not the right guy to ask 🙂Crank
B
9

The consumer is correct, though it's hard to visualize, esp. in that you can continue with additional fluent-composition method calls in the webclient construction, after you've done your work with the headers.

....suppose you have a HttpHeaders (or MutliValue map) holding your headers in scope. here's an example, using an exchange object from spring cloud gateway:

final HttpHeaders headersFromExchangeRequest = exchange.getRequest().headers();
webclient.get().uri("blah-blah")
    .headers( httpHeadersOnWebClientBeingBuilt -> { 
         httpHeadersOnWebClientBeingBuilt.addAll( headersFromExchangeRequest );
    }
)...

the addAll can take a multivalued map. if that makes sense. if not, let your IDE be your guide.

to make the consumer clearer, let's rewrite the above as follows:

private Consumer<HttpHeaders> getHttpHeadersFromExchange(ServerWebExchange exchange) {
    return httpHeaders -> {
        httpHeaders.addAll(exchange.getRequest().getHeaders());
    };
}
.
.
.
webclient.get().uri("blah-blah")
    .headers(getHttpHeadersFromExchange(exchange))
    ...
Broads answered 28/9, 2020 at 23:56 Comment(0)
B
3

I found this problem came up again for me and this time I was writing groovy directly using WebClient. Again, the example I'm trying to drive is using the Consumer as the argument to the headers method call.

In groovy, the additional problem is that groovy closure syntax and java lambda syntax both use ->

The groovy version is here:

def mvmap = new LinkedMultiValueMap<>(headersAsMap)
def consumer = { it -> it.addAll(mvmap) } as Consumer<HttpHeaders>

WebClient client = WebClient.create(baseUrlAsString)
def resultAsMono = client.post()
        .uri(uriAsString).accept(MediaType.APPLICATION_JSON)
        .headers(consumer)
        .body(Mono.just(payload), HashMap.class)
        .retrieve()
        .toEntity(HashMap.class)

The java version is here:

LinkedMultiValueMap mvmap = new LinkedMultiValueMap<>(headersAsMap);
Consumer<HttpHeaders> consumer = it -> it.addAll(mvmap);

WebClient client = WebClient.create(baseUrlAsString);
Mono<ResponseEntity<HashMap>> resultAsMono = client.post()
        .uri(uriAsString).accept(MediaType.APPLICATION_JSON)
        .headers(consumer)
        .body(Mono.just(payload), HashMap.class)
        .retrieve()
        .toEntity(HashMap.class);
Broads answered 29/12, 2021 at 0:13 Comment(1)
This is a very usefull response, because declare an interface a shows an example of java lambda expresion with a linked multivalue map as a params.Baldridge
E
3

In Spring Boot 2.7.5:

webClient
  .get()
    .uri("blah-blah")
      .headers(
        httpHeaders -> {
          httpHeaders.set("key1", "value1");
          httpHeaders.set("key2", "value2");
        })
Eyecatching answered 25/10, 2022 at 12:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.