javaspring-bootspring-mvccustom-headers

Injecting custom headers into ServletRequest in Spring Boot JAVA


I have a requirement to inject custom headers into every request a spring boot application is getting, for this, I have written some code but it seems it is not doing its work. For a brief, I have implemented the Filter interface and defined the doFilter method, extended the HttpServletRequestWrapper class, and overridden getHeader() and getHeaderNames() method to take into account the custom headers I am reading from the properties file.

But, the moment I get into the controller and check the request I am not getting my custom headers that were set through the MyReqWrapper. Below is the code, I've also tried searching it in Stackoverflow but couldn't find the solution on what is/could be wrong here. Can someone point me in the right direction?

Also, please point me on how to test whether custom headers are actually set or not.

This is Filter implementation

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ReqFilter implements Filter {
    private static final String CUSTOMHEADERENABLED = "customheadersenabled";
    private static final String CUSTOMHEADERCOUNT = "customheaderscount";
    
    @Autowired
    private Environment env;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        try {
            boolean customHeadersEnabled = Boolean.parseBoolean(env.getProperty(CUSTOMHEADERENABLED, "false"));
            int count = Integer.parseInt(env.getProperty(CUSTOMHEADERCOUNT, "0"));

            if (customHeadersEnabled && count > 0) {
                MyReqWrapper myReq = new MyReqWrapper((HttpServletRequest) servletRequest);
                myReq.processMyHeaders(count, env);
                filterChain.doFilter(customRequest, servletResponse);
            } else {
                filterChain.doFilter(servletRequest, servletResponse);
            }
        }
        catch(ServletException ex){
            throw ex;
        }
    }

    @Override
    public void destroy() {
        //
    }
}

This is custom request wrapper extending HttpServletRequestWrapper

final class MyReqWrapper extends HttpServletRequestWrapper {
    private static final String CUSTOMHEADERPREFIX = "header1";
    private final Map<String, String> myHeaders;

    public MyReqWrapper(HttpServletRequest request) {
        super(request);
        myHeaders = new HashMap<>();
    }

    @Override
    public String getHeader(String name) {
        String headerValue = myHeaders.get(name);

        if (headerValue != null){
            return headerValue;
        }
        return ((HttpServletRequest) getRequest()).getHeader(name);
    }

    @Override
    public Enumeration<String> getHeaderNames() {
        Set<String> set = new HashSet<>(myHeaders.keySet());

        Enumeration<String> headerNames = ((HttpServletRequest) getRequest()).getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String n = headerNames.nextElement();
            set.add(n);
        }
        return Collections.enumeration(set);
    }

    public void processMyHeaders(int headerCount, Environment env) {
        while(headerCount > 0){
            String [] headerKeyValue = Objects.requireNonNull(env.getProperty(String.format("%1$s%2$s", CUSTOMHEADERPREFIX, headerCount--)))
                    .split(":");
            this.myHeaders.put(headerKeyValue[0], headerKeyValue[1]);
        }
    }
}


Solution

  • This was solved for me and I forgot to update this with an answer.

    So the problem was I was using HttpServletRequest class from two different namespaces in the ReqFilter and controller classes, namely one from "org.apache.catalina.servlet4preview.http.HttpServletRequest" and another from "javax.servlet.http.HttpServletRequest".

    Once I used uniform namespace in both the files I could access the headers from controller classes.