Adding custom headers to Java HttpServletRequest
The javax.servlet.http.HttpServletRequest is an interface that does not have setter methods except for setCharacterEncoding() and setAttribute() methods that it inherits from its parent javax.servlet.ServletRequest interface. Otherwise, the HttpServletRequest type objects are read only.
There, often, are occasions where you may want to intercept the incoming HTTP request in an HttpServletFilter and add or modify its request headers. Below, I discuss a mechanism where I will show you how to add custom headers to an HttpServletRequest type object. The same mechanism can be applied to modify existing headers.
We use the decorator pattern to dynamically extend the functionality of HttpServletRequest type object and use the decorated object in place of the original object.
In the code below, I call the decorated HTTP servlet request class as the MutableHttpServletRequest that extends the HttpServletRequest implementation class called javax.servlet.http.HttpServletRequestWrapper and defines a constructor that accepts a HttpServletRequest type object.
The input HttpServletRequest type object is used as the backing request object. This is a standard decorator design pattern implementation that we employ here. Let me show you the code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; final class MutableHttpServletRequest extends HttpServletRequestWrapper { // holds custom header and value mapping private final Map<String, String> customHeaders; public MutableHttpServletRequest(HttpServletRequest request){ super(request); this.customHeaders = new HashMap<String, String>(); } public void putHeader(String name, String value){ this.customHeaders.put(name, value); } public String getHeader(String name) { // check the custom headers first String headerValue = customHeaders.get(name); if (headerValue != null){ return headerValue; } // else return from into the original wrapped object return ((HttpServletRequest) getRequest()).getHeader(name); } public Enumeration<String> getHeaderNames() { // create a set of the custom header names Set<String> set = new HashSet<String>(customHeaders.keySet()); // now add the headers from the wrapped request object @SuppressWarnings("unchecked") Enumeration<String> e = ((HttpServletRequest) getRequest()).getHeaderNames(); while (e.hasMoreElements()) { // add the names of the request headers into the list String n = e.nextElement(); set.add(n); } // create an enumeration from the set and return return Collections.enumeration(set); } } |
You would mostly be using this MutableHttpServletRequest class in the servlet filter to intercept incoming HTTP request to add some custom headers. Let me show you a sample usage.
Using the MutableHttpServletRequest class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class SecurityFilter implements javax.servlet.Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(req); ... mutableRequest.putHeader("x-custom-header", "custom value"); chain.doFilter(mutableRequest, response); } @Override public void init(FilterConfig filterConfig) throws ServletException { } } |
This didn’t work for me until I added:
import java.util.Optional;
@Override
public Enumeration<String> getHeaders(String name) {
Set<String> set = new HashSet<>();
Optional.ofNullable(customHeaders.get(name)).ifPresent(h -> set.add(h));
Enumeration<String> e = ((HttpServletRequest) getRequest()).getHeaders(name);
while (e.hasMoreElements()) {
// add the names of the request headers into the list
String n = e.nextElement();
set.add(n);
}
Optional.ofNullable(customHeaders.get(name)).ifPresent(h -> set.add(h));
return Collections.enumeration(set);
}
Hi! please explain why this construction
Optional.ofNullable(customHeaders.get(name)).ifPresent(h -> set.add(h));
is used twice?Not sure what I missed, using code from above, don’t see my 2 custom headers.
I did the same thing and observed that the header is avaialble inside request while in controller HttpHeader i dont get it why?
@PostMapping(value = “/v0.2/card/add”)
public ResponseEntity<ResponseBody> addCard(HttpServletRequest request,
@RequestHeader HttpHeader
putHeaders() will not work until getHeaders(String name) not overridden, as the extractRequestHeaders() from ServletUtil will alwalys call the Request.getHeaders().
Thanks, this really helped me a lot.