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.
Further reading:
Spring RequestMapping
How to Set a Header on a Response with Spring
Using Spring ResponseEntity to Manipulate the HTTP Response
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(HttpHeaders.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(HttpHeaders.ACCEPT_LANGUAGE) String language) {}
We can accomplish the same thing by using the name attribute:
public ResponseEntity<String> greeting(
@RequestHeader(name = HttpHeaders.ACCEPT_LANGUAGE) String language) {}
Next, letβs use the value attribute exactly the same way:
public ResponseEntity<String> greeting(
@RequestHeader(value = HttpHeaders.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.
