Enterprise Java

Send Multiple Headers with Spring WebClient

In modern microservices and cloud-native applications, sending metadata with HTTP requests is a common need. If you have worked with REST APIs, you’ve probably dealt with headers—pieces of information like Content-Type, Authorization, or custom values that help servers understand how to process your request. When using Spring WebClient, a modern tool for making HTTP calls in reactive applications, it’s important to know how to set these headers properly. This guide will walk through how to send multiple headers in a single request and define default headers globally.

1. Understanding WebClient and HTTP Headers

Spring WebClient, introduced in Spring 5 as part of Spring WebFlux, is a non-blocking, reactive HTTP client designed for high-throughput microservices and event-driven systems. It replaces the older RestTemplate in reactive applications and supports:

  • Asynchronous, event-loop based processing
  • Reactive types like Mono and Flux
  • A fluent API for chaining requests
  • Header and cookie management
  • JSON, XML, and stream support

1.1 What Are HTTP Headers?

HTTP headers are metadata sent alongside requests or responses. They inform the server or client how to interpret the message body or control aspects like caching, authentication, or content negotiation. Common headers include:

  • Content-Type: Specifies the format of the payload (e.g., application/json)
  • Authorization: Sends credentials such as bearer tokens
  • Accept: Tells the server what format is expected in the response
  • X-Custom-*: For trace IDs, versioning, or feature toggles

Sample Endpoint to Test

Let’s create a test endpoint that returns a list of books and logs the received headers. First, define a basic Book class to use in our request payload.

public class Book {

    private String title;
    private String author;

    public Book() {
    }

    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

Here is a controller that handles POST requests, receives Book objects sent by WebClient, and logs all incoming headers.

@RestController
@RequestMapping("/api/books")
public class BookController {

    private static final Logger logger = LoggerFactory.getLogger(BookController.class);

    @PostMapping
    public ResponseEntity<String> createBook(@RequestBody Book book, @RequestHeader Map<String, String> headers) {
        logger.info("Received book: {} by {}", book.getTitle(), book.getAuthor());
        logger.info("Received headers: {}", headers);
        return ResponseEntity.ok("Book received successfully");
    }
}

WebClient Configuration

We can either autowire a WebClient.Builder or configure a reusable bean.

@Configuration
public class WebClientConfig {

    @Bean
    public WebClient webClient() {
        return WebClient.builder()
                .baseUrl("http://localhost:8080")
                .build();
    }
}

2. Setting Multiple Headers in WebClient (Per Request)

To set multiple headers on a single request, we can use .header() multiple times or use .headers(Consumer<HttpHeaders>). Here’s a service that sends a Book with multiple headers set at once.

@Service
public class BookClientService {

    @Autowired
    private WebClient webClient;

    public Mono<String> sendBookWithHeaders() {
        Book book = new Book("Effective Java", "Joshua Bloch");

        // Set multiple headers
        return webClient.post()
                .uri("/api/books")
                .headers(httpHeaders -> {
                    httpHeaders.setContentType(MediaType.APPLICATION_JSON);
                    httpHeaders.set("X-Correlation-Id", "12345");
                    httpHeaders.set("X-Client", "WebClientApp");
                    httpHeaders.set("Authorization", "Bearer mock-token");
                })
                .bodyValue(book)
                .retrieve()
                .bodyToMono(String.class);
    }
}

Testing the Setup via REST Controller

Add a simple REST controller to trigger the client.

@RestController
@RequestMapping("/client")
public class WebClientTestController {

    @Autowired
    private BookClientService bookClientService;

    @GetMapping("/send-book")
    public String triggerClient() {
        return bookClientService.sendBookWithHeaders().block(); // blocking only for demo/testing
    }
}

When you access http://localhost:8080/client/send-book, observe the logs in the console and you should see something like this:

com.jcg.example.BookController           : Received book: Effective Java by Joshua Bloch
2025-05-06T13:27:49.350+01:00  INFO 41612 --- [webclient-multi-header-example] 
[nio-8080-exec-2] com.jcg.example.BookController           : 
Received headers: {accept-encoding=gzip, user-agent=ReactorNetty/1.2.5, 
host=localhost:8080, accept=*/*, content-type=application/json, 
x-correlation-id=12345, x-client=WebClientApp, authorization=Bearer mock-token, content-length=50}

3. Setting Default Headers Globally

In many applications, certain HTTP headers need to be sent with every request, such as authorization tokens, API versioning, or environment metadata. Instead of repeating these headers in every WebClient call, Spring WebClient allows us to define default headers globally when building the client. This ensures consistency and reduces boilerplate across your codebase.

Here’s how to configure default headers globally when creating a WebClient instance:

WebClient webClient = WebClient.builder()
        .baseUrl("http://localhost:8080")
        .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
        .defaultHeader("X-App-Version", "1.0")
        .defaultHeader("X-Env", "development")
        .build();

Once configured, all requests using this webClient instance will automatically include these headers, unless they are overridden on a per-request basis using .header(...).

Header Precedence: Request-specific headers override any global default headers if both are set for the same key. Internally, WebClient uses HttpHeaders (a Spring abstraction) that supports case-insensitive keys and multiple values for headers like Accept or Cookie.

4. Conclusion

In this article, we walked through the practical use of Java Spring WebClient to send multiple HTTP headers. The article demonstrated how to configure headers globally, customize them per request, and verify them through a sample controller. These practices are particularly valuable in microservice architectures that rely on consistent metadata, authentication, and request tracing.

5. Download the Source Code

This article explored how to set headers using Java Spring WebClient, covering both default and per-request configurations.

Download
You can download the full source code of this example here: java spring webclient set headers

Omozegie Aziegbe

Omos Aziegbe is a technical writer and web/application developer with a BSc in Computer Science and Software Engineering from the University of Bedfordshire. Specializing in Java enterprise applications with the Jakarta EE framework, Omos also works with HTML5, CSS, and JavaScript for web development. As a freelance web developer, Omos combines technical expertise with research and writing on topics such as software engineering, programming, web application development, computer science, and technology.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button