Let's get started with a Microservice Architecture with Spring Cloud:
Set Multiple Headers at Once in Spring WebClient
Last updated: June 4, 2025
1. Introduction
In this tutorial, we’ll take a look at how to set multiple headers at once in Spring WebClient.
WebClient is a class from Spring WebFlux that, in simple terms, enables both synchronous and asynchronous HTTP requests. We’ll first understand how WebClient handles headers and then explore with code examples different ways to set up multiple headers at once.
2. How WebClient Handles Headers
In general, headers in HTTP requests serve as metadata. They carry information such as authentication details, content types, versions, and more.
In WebClient, the HttpHeaders class manages the headers. It’s a Spring framework class specifically designed to represent request and response headers. It implements MultiValueMap<String, String>, allowing a single header key to have multiple values.
This provides flexibility for headers that require multiple values, such as Accept.
3. Setting Multiple Headers in WebClient
There are several ways to add headers to a request. Depending on the use case, we can set headers for individual requests, define global headers for the entire WebClient instance, or modify them dynamically.
Let’s explore these approaches through code examples.
3.1. Set Headers for Individual Requests
When headers are specific to individual requests and vary by endpoint, the straightforward approach is to set them directly on the request.
In the following example, we create a simple test where we instantiate the WebClient, add two headers to the request, and assert that the request was sent with those headers. We’re also using the MockWebServer from the okhttp3 library to simulate server responses and verify our WebClient‘s behavior:
@Test
public void givenRequestWithHeaders_whenSendingRequest_thenAssertHeadersAreSent() throws Exception {
mockWebServer.enqueue(new MockResponse().setResponseCode(HttpStatus.OK.value()));
WebClient client = WebClient.builder()
.baseUrl(mockWebServer.url("/").toString())
.build();
ResponseEntity<Void> response = client.get()
.headers(headers -> {
headers.put("X-Request-Id", Collections.singletonList(RANDOM_UUID));
headers.put("Custom-Header", Collections.singletonList("CustomValue"));
})
.retrieve()
.toBodilessEntity()
.block();
assertNotNull(response);
assertEquals(HttpStatusCode.valueOf(HttpStatus.OK.value()), response.getStatusCode());
RecordedRequest recordedRequest = mockWebServer.takeRequest();
assertEquals(RANDOM_UUID, recordedRequest.getHeader("X-Request-Id"));
assertEquals("CustomValue", recordedRequest.getHeader("Custom-Header"));
}
This example uses the headers(Consumer<HttpHeaders> headersConsumer) method from the WebClient class.
As we noted earlier, WebClient relies on HttpHeaders, which are configured using the Consumer functional interface in this context. This setup allows us to modify the request headers by passing a lambda that operates on the HttpHeaders instance.
3.2. Set Default Headers Globally
In other scenarios, we may need to define global headers. These headers are configured at a global level, and they’ll be automatically added to each request made using this client instance. This kind of configuration helps us maintain consistency and reduce repetition.
We can always override global headers with request-specific headers, as they only act as a baseline. The only difference from the previous approach is that we add them while building the WebClient:
WebClient client = WebClient.builder()
.baseUrl(mockWebServer.url("/").toString())
.defaultHeaders(headers -> {
headers.put("X-Request-Id", Collections.singletonList(RANDOM_UUID));
headers.put("Custom-Header", Collections.singletonList("CustomValue"));
})
.build();
3.3. Modify Headers Dynamically Using ExchangeFilterFunction
In some situations, we may want to dynamically set or modify headers at runtime. For such cases, we can use the ExchangeFilterFunction class:
ExchangeFilterFunction dynamicHeadersFilter = (request, next) -> next.exchange(ClientRequest.from(request)
.headers(headers -> {
headers.put("X-Request-Id", Collections.singletonList(RANDOM_UUID));
headers.put("Custom-Header", Collections.singletonList("CustomValue"));
})
.build());
After building the ExchangeFilterFunction instance, we then register it with the WebClient during instantiation:
WebClient client = WebClient.builder()
.baseUrl(mockWebServer.url("/").toString())
.filter(dynamicHeadersFilter)
.build();
It’s also worth noting that we can stack multiple filter function instances for a single WebClient.
4. Conclusion
In this article, we explored how Spring WebClient handles headers and saw several ways to set multiple headers. Whether for a single request, across all requests globally, or dynamically at runtime, WebClient provides a straightforward and flexible approach to managing headers consistently and cleanly.
The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
















