Reading HTTP Headers in Spring REST Controller

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 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 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 on 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)

In order to do that, 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 next example we are Reading all HTTP headers in a HashMap. We are using @RequestHeader annotation to map all HTTP headers into 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 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 values and we want to read all values, we can use 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 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

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

In order to make the header optional we can use 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. In order to set a default value we can use defaultValue attribute of @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)

Note that, Spring will inject 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 HTTPServletRequest instance.

In order to access 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 controller method. Also, we covered how to make a header values optional or how to provide a default values for a missing header. Lastly, we learned how to use HttpServletRequest and read headers manually.

For the full source code of the examples used in this tutorial, you can refer to our Github Repository.