1. Overview

In this tutorial, we're going to look at how we can access HTTP headers using Spring MVC.

2. Getting HTTP Request Headers

Firstly, we'll look at getting HTTP request headers. Spring MVC provides several ways for this purpose.

2.1. @RequestHeader Annotation

The @RequestHeader annotation binds the specified request header to a method parameter.

As the first step, we must provide the header name as the annotation value. Then we must declare a method parameter to hold the header value.

@GetMapping("/getHeader")
public String getHeader(@RequestHeader("Accept") String acceptHeader) {
    return acceptHeader;
}

Here, we're binding the Accept header to the String parameter, acceptHeader.

Note that an HTTP header can have multiple values separated by commas. So when we specify multiple media types as acceptable, acceptHeader will store all of them.

@Test
public void shouldGetHeader() throws Exception {
    mockMvc.perform(get("/getHeader")
      .accept(MediaType.APPLICATION_JSON_UTF8_VALUE, MediaType.APPLICATION_JSON_VALUE))
      .andExpect(status().isOk())
      .andExpect(content().string("application/json;charset=UTF-8, application/json"));
}

Alternatively, we can bind the header values to a List instance for more convenient access:

@GetMapping("/getHeaderAsList")
public List<String> getHeaders(@RequestHeader("Accept") List<String> acceptHeaders) {
    return acceptHeaders;
}

Here, Spring MVC will tokenize the Accept header value and populate the acceptHeaders parameter.

@Test
public void shouldGetHeaderAsList() throws Exception {
    mockMvc.perform(get("/getHeaderAsList")
      .accept(MediaType.APPLICATION_JSON_UTF8_VALUE, MediaType.APPLICATION_JSON_VALUE))
      .andExpect(status().isOk())
      .andExpect(jsonPath("$.[0]").value("application/json;charset=UTF-8"))
      .andExpect(jsonPath("$.[1]").value("application/json"));
}

2.2. @RequestHeader for All Request Headers

We can also use @RequestHeader to get all HTTP headers.

In contrast to getting a single header, we won't set the annotation value. Moreover, the method parameter which will hold the headers can be declared in different ways.

Firstly, we'll use HttpHeaders as the parameter type:

@GetMapping("/getHeaders")
public Set<String> getHeaders(@RequestHeader HttpHeaders httpHeaders) {
    return httpHeaders.keySet();
}

Alternatively, we can declare our method parameter as Map<String, String>:

@GetMapping("/getHeadersFromMap")
public Set<String> getHeadersFromMap(@RequestHeader Map<String, String> httpHeaders) {
    return httpHeaders.keySet();
}

Lastly, we can also declare it as MultiValueMap<String, String>:

@GetMapping("/getHeadersFromMultiValue")
public Set<String> getHeadersFromMultiValue(@RequestHeader MultiValueMap<String, String> httpHeaders) {
    return httpHeaders.keySet();
}

2.3. HttpServletRequest

Spring MVC allows us to bind the current HttpServletRequest to our endpoint methods. We'll now use this request instance to access HTTP headers:

@GetMapping("/getHeaderFromRequest")
public String getHeaderFromRequest(HttpServletRequest servletRequest) {
    return servletRequest.getHeader("Accept");
}

Here, we're calling the getHeader method of HttpServletRequest to access the Accept header.

2.4. HttpEntity

Similar to HttpServletRequest, we can also bind HttpEntity to our endpoint methods. The HttpEntity class also exposes HTTP request headers:

@GetMapping("/getHeaderFromEntity")
public List<String> getHeaderFromEntity(HttpEntity<String> httpEntity) {
    return httpEntity.getHeaders().getAccept().stream().map(MimeType::toString).collect(Collectors.toList());
}

Here, we're navigating into the HttpEntity instance and accessing its headers. Then we're calling the convenience method getAccept to get the values of Accept.

3. Setting HTTP Response Headers

Next, we'll look at several ways to set HTTP response headers.

3.1. HttpServletResponse

Since HttpServletResponse enables us to add/set response headers, we can declare a HttpServletResponse parameter in our controller methods.

@GetMapping("/setHeader")
public void setHeader(HttpServletResponse servletResponse) {
    servletResponse.setHeader("X-Source", "Spring");
    servletResponse.addHeader("X-Source", "Java");
}

Here, we're first setting the X-Source header as Spring - using setHeader method. Then we're adding Java as the second value - using addHeader method.

In the final response, the X-Source header will contain these two values:

@Test
public void shouldSetHeader() throws Exception {
    mockMvc.perform(get("/setHeader").accept(MediaType.APPLICATION_JSON_UTF8))
      .andExpect(status().isOk())
      .andExpect(header().stringValues("X-Source", "Spring", "Java"));
}

3.2. ResponseEntity

We can also use ResponseEntity to set HTTP response headers. By returning a ResponseEntity instance, we can define the response status code, response headers, and response body.

@GetMapping("/setHeaderWithHttpEntity")
public ResponseEntity<String> setHeaderWithEntity() {
    HttpHeaders headers = new HttpHeaders();
    headers.add("X-Source", "Spring");
    return new ResponseEntity<>("", headers, HttpStatus.OK);
}

In this example, we're adding a single response header - X-Source -  and specifying the response body as empty.

3.3. HttpHeaders

When we return an instance of HttpHeaders from our controller methods, it will define the response headers.

@GetMapping("/setHeaderWithHttpHeaders")
public HttpHeaders setHeader() {
    HttpHeaders headers = new HttpHeaders();
    headers.add("X-Source", "Spring");
    return headers;
}

Similar to the previous examples, we're setting the X-Source header as Spring.

4. Summary

In this tutorial, we've first investigated how to read HTTP request headers using Spring MVC. Then we've looked at setting response headers.

Lastly, check out the source code for all examples in this tutorial over on Github.