Reading HTTP Headers in Spring REST Controller

A quick guide on How to Read HTTP Headers in Spring REST Controller.

Overview

This tutorial explains How to read HTTP Headers in a Spring Controller. First, we will have a brief of Spring @ResquestHeader annotation that maps all headers or a specific header into controller method arguments. Next, we will explore various ways to bind request HTTP Headers in a Spring Controller. Lastly, we will cover how to use the HttpServletRequest instance to read the header values in the Spring REST Controller.

Reading HTTP Headers using @RequestHeader

Spring provides @RequestHeader annotation that maps all or a particular header values to an argument of a controller method. The type of @RequestHeader annotation is ‘parameter’. Thus we can add it directly to a controller method argument.

@RequestHeader Annotation

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestHeader {
  @AliasFor("name")
  String value() default "";

  @AliasFor("value")
  String name() default "";

  boolean required() default true;

  String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}Code language: Java (java)

The data type of the header value and the controller method argument must match, or they must be compatible.

Reading HTTP Headers as Java HashMap

In the following example, we read all HTTP headers in a HashMap. We use @RequestHeader annotation to map all HTTP headers into the Java Map instance.

@PostMapping("v1/students")
public void postStudent(
    @RequestHeader Map<String, String> headers,
    @RequestBody Student student) {

  log.info("Header values: {}", headers);
}Code language: Java (java)
curl -L -X POST 'http://localhost:8080/v1/students' \
-H 'Content-Type: application/json' \
--data-raw '{
    "id" : "123"
}'

--
Header values: {host=localhost:8080, user-agent=curl/7.64.1, accept=*/*, content-type=application/json, content-length=20}

Reading HTTP Headers as HTTPHeaders Instance

Alternatively, we can inject the HTTP Headers into an instance of HttpHeaders class. The HttpHeaders is an implementation of a MultiValueMap class.

Next is an example of reading HTTP Header values in the HttpHeader instance.

@PostMapping("/v2/students")
public void postStudent(
    @RequestHeader HttpHeaders headers,
    @RequestBody Student student) {

  log.info("Header values: {}", headers);
}Code language: Java (java)
curl -L -X POST 'http://localhost:8080/v2/students' \
-H 'Content-Type: application/json' \
--data-raw '{
    "id" : "123"
}'

--
Header values: [host:"localhost:8080", user-agent:"curl/7.64.1", accept:"*/*", content-type:"application/json", content-length:"20"]

Reading HTTP Headers as Java MultiValueMap

While mapping HttpHeader values to a Map, Spring only maps the first value of the key into the Map. However, if a header key has more than one value, to read all values, we can use the MultiValueMap.

Example of Reading HttpHeaders to MultiValueMap in Spring REST Controller.

@PostMapping("/v3/students")
public void postStudent(
    @RequestHeader MultiValueMap<String, String> headers,
    @RequestBody Student student) {

  log.info("Header values: {}", headers);
}Code language: Java (java)
curl -L -X POST 'http://localhost:8080/v3/students' \
-H 'Content-Type: application/json' \
--data-raw '{
    "id" : "123"
}'

--
Header values: {host=[localhost:8080], user-agent=[curl/7.64.1], accept=[*/*], content-type=[application/json], content-length=[20]}

Reading Specific HTTP Headers using @RequestHeader

We can also read only a specific header using @RequestHeader by providing the header key as an annotation value.

Example of Reading a specific header in Spring REST Controller.

@PostMapping("/v4/students")
public void postStudent(
    @RequestHeader("content-type") String contentType,
    @RequestBody Student student) {

  log.info("Header value - Content-Type: {}", contentType);
}Code language: Java (java)
curl -L -X POST 'http://localhost:8080/v4/students' \
-H 'Content-Type: application/json' \
--data-raw '{
    "id" : "123"
}'

--
Header value - Content-Type: application/json

Spring treats it as a mandatory header if a particular header is mapped into the Controller method argument. Thus, Spring returns an HTTP status code of 400 (Bad Request) if the mapped header is not present in the request.

To make the header optional, we can use the required attribute of @RequestHeader annotation.

@PostMapping("/v4/students")
public void postStudent(
        @RequestHeader(
            value = "content-type", 
            required = false) 
            String contentType,
        @RequestBody Student student) {

    log.info("Header value - Content-Type: {}", contentType);
}Code language: Java (java)

Next is an example of setting a default header value if a particular header is not present in the request. To set a default value, we can use the defaultValue attribute of the @RequestHeader annotation.

@PostMapping("/v4/students")
public void postStudent(
        @RequestHeader(
            value = "content-type", 
            defaultValue = "application/json") 
            String contentType,
        @RequestBody Student student) {

    log.info("Header value - Content-Type: {}", contentType);
}Code language: Java (java)

Make a note that Spring injects the default value only if the original header is missing or is Null.

Reading HTTP Headers using HttpServletRequest

Alternatively, we can also read request header values directly from the HTTPServletRequest instance.

To access the HttpServletRequest instance in a Spring REST Controller, we need to add it as a method argument.

Next is an example of Reading all header values in Spring REST Controller, using HttpServletRequest.

@PostMapping("/v5/students")
public void postStudent(
    HttpServletRequest request,
    @RequestBody Student student) {

  Enumeration<String> headerNames = request.getHeaderNames();
  while (headerNames.hasMoreElements()) {
    String key = headerNames.nextElement();
    log.info(key + ": " + request.getHeader(key));
  }
}Code language: Java (java)
curl -L -X POST 'http://localhost:8080/v5/students' \
-H 'Content-Type: application/json' \
--data-raw '{
    "id" : "123"
}'

--
host: localhost:8080
user-agent: curl/7.64.1
accept: */*
content-type: application/json
content-length: 20

Summary

This tutorial talked about How to read HTTP Headers in Spring REST Controllers. We learned that using @RequestHeader annotation, we can map all headers or a particular header into an argument of the controller method. Also, we covered how to make a header values optional or provide a default value for a missing header. Lastly, we learned how to use HttpServletRequest and read headers manually.

You can refer to our Github Repository for the complete source code of the examples used in this tutorial.