How to Read HTTP Headers in Spring REST Controllers

1. Overview

In this quick tutorial, we’re going to look at how to access HTTP Headers in a Spring Rest Controller.

First, we’ll be using the @RequestHeader annotation to read headers individually as well as all together.

After that, we’ll take a deeper look at the @RequestHeader attributes.

2. Accessing HTTP Headers

2.1. Individually

If we need access to a specific header, we can configure @RequestHeader with the header name:

@GetMapping("/greeting")
public ResponseEntity<String> greeting(@RequestHeader("accept-language") String language) {
    // code that uses the language variable
    return new ResponseEntity<String>(greeting, HttpStatus.OK);
}

Then we can access the value using the variable passed into our method. If a header named accept-language isn’t found in the request, the method returns a “400 Bad Request” error.

Our headers don’t have to be strings. If we know our header is a number, we can declare our variable as a numeric type:

@GetMapping("/double")
public ResponseEntity<String> doubleNumber(@RequestHeader("my-number") int myNumber) {
    return new ResponseEntity<String>(String.format("%d * 2 = %d", 
      myNumber, (myNumber * 2)), HttpStatus.OK);
}

2.2. All at Once

If we’re not sure which headers will be present, or we need more of them than we want in our method’s signature, we can use the @RequestHeader annotation without a specific name.

We have a few choices for our variable type: a Map, a MultiValueMap, or a HttpHeaders object.

First, let’s get the request headers as a Map:

@GetMapping("/listHeaders")
public ResponseEntity<String> listAllHeaders(
  @RequestHeader Map<String, String> headers) {
    headers.forEach((key, value) -> {
        LOG.info(String.format("Header '%s' = %s", key, value));
    });

    return new ResponseEntity<String>(
      String.format("Listed %d headers", headers.size()), HttpStatus.OK);
}

If we use a Map and one of the headers has more than one value, we’ll get only the first value. This is the equivalent of using the getFirst method on a MultiValueMap.

If our headers may have multiple values, we can get them as a MultiValueMap:

@GetMapping("/multiValue")
public ResponseEntity<String> multiValue(
  @RequestHeader MultiValueMap<String, String> headers) {
    headers.forEach((key, value) -> {
        LOG.info(String.format(
          "Header '%s' = %s", key, value.stream().collect(Collectors.joining("|"))));
    });
        
    return new ResponseEntity<String>(
      String.format("Listed %d headers", headers.size()), HttpStatus.OK);
}

We can also get our headers as an HttpHeaders object:

@GetMapping("/getBaseUrl")
public ResponseEntity<String> getBaseUrl(@RequestHeader HttpHeaders headers) {
    InetSocketAddress host = headers.getHost();
    String url = "http://" + host.getHostName() + ":" + host.getPort();
    return new ResponseEntity<String>(String.format("Base URL = %s", url), HttpStatus.OK);
}

The HttpHeaders object has accessors for common application headers.

When we access a header by name from a Map, MultiValueMap or the HttpHeaders object, we’ll get a null if it isn’t present.

3. @RequestHeader Attributes

Now that we’ve gone over the basics of accessing request headers with the @RequestHeader annotation, let’s take a closer look at its attributes.

We’ve already used the name or value attributes implicitly when we’ve specifically named our header:

public ResponseEntity<String> greeting(@RequestHeader("accept-language") String language) {}

We can accomplish the same thing by using the name attribute:

public ResponseEntity<String> greeting(
  @RequestHeader(name = "accept-language") String language) {}

Next, let’s use the value attribute exactly the same way:

public ResponseEntity<String> greeting(
  @RequestHeader(value = "accept-language") String language) {}

When we name a header specifically, the header is required by default. If the header isn’t found in the request, the controller returns a 400 error.

Let’s use the required attribute to indicate that our header isn’t required:

@GetMapping("/nonRequiredHeader")
public ResponseEntity<String> evaluateNonRequiredHeader(
  @RequestHeader(value = "optional-header", required = false) String optionalHeader) {
    return new ResponseEntity<String>(String.format(
      "Was the optional header present? %s!",
        (optionalHeader == null ? "No" : "Yes")),HttpStatus.OK);
}

Since our variable will be null if the header isn’t present in the request, we need to be sure to do the appropriate null checking.

Let’s use the defaultValue attribute to provide a default value for our header:

@GetMapping("/default")
public ResponseEntity<String> evaluateDefaultHeaderValue(
  @RequestHeader(value = "optional-header", defaultValue = "3600") int optionalHeader) {
    return new ResponseEntity<String>(
      String.format("Optional Header is %d", optionalHeader), HttpStatus.OK);
}

4. Conclusion

In this short tutorial, we learned how to access request headers in Spring REST controllers.

First, we used the @RequestHeader annotation to supply request headers to our controller methods.

After checking out the basics, we took a detailed look at the attributes for the @RequestHeader annotation.

The example code is available over on GitHub.

Related posts:

Spring WebClient Filters
REST Pagination in Spring
Java Program to Implement a Binary Search Algorithm for a Specific Search Sequence
Why String is Immutable in Java?
Java Program to Find the Number of Ways to Write a Number as the Sum of Numbers Smaller than Itself
OAuth2 for a Spring REST API – Handle the Refresh Token in AngularJS
Java Program to Implement Park-Miller Random Number Generation Algorithm
Java Program to Implement Trie
Lớp LinkedHashMap trong Java
Java Concurrency Interview Questions and Answers
Java Program to implement Associate Array
Java Program to Construct K-D Tree for 2 Dimensional Data
Java Collections Interview Questions
Semaphore trong Java
Spring Boot Tutorial – Bootstrap a Simple Application
Java Program to Implement Max-Flow Min-Cut Theorem
Java Program to Perform the Unique Factorization of a Given Number
Java Program to Implement Graph Coloring Algorithm
Hướng dẫn Java Design Pattern – MVC
Quick Intro to Spring Cloud Configuration
Java Program to Generate All Possible Combinations Out of a, b, c, d, e
Guide to Spring 5 WebFlux
Spring Security – Reset Your Password
Giới thiệu thư viện Apache Commons Chain
Java Program to Implement Bloom Filter
Java Program to Implement JobStateReasons API
Control Structures in Java
Spring REST API + OAuth2 + Angular (using the Spring Security OAuth legacy stack)
Java – Write an InputStream to a File
Java Program to Implement Repeated Squaring Algorithm
@DynamicUpdate with Spring Data JPA
Java Program to Perform Postorder Recursive Traversal of a Given Binary Tree