2

Since Servlet 3.0, HttpServletResponse#getHeaderNames() and HttpServletResponse#getHeaders() has been available. However, I'm using an older spec, specifically Servlet 2.4.

Having looked at the resource, How can I get the HTTP status code out of a ServletResponse in a ServletFilter?, I got an idea of how to write a wrapper. If I understand it right, I have to use setHeader() to facilitate the creation of getHeaderNames() and getHeaders(). I think I have a solid footing on how to store the headers to simulate the usage of these missing methods.

The problem is the filter which leverages this wrapper does not seem to be calling setHeader() automatically. I don't get it. I presume sincegetStatus() is working properly, I'm expecting setHeader() to behave in the same fashion. Specifically, I'm looking to print out all the response headers, after calling chain.doFilter(). I'm not sure what I'm doing wrong here. Maybe there is something wrong with how I'm storing header name-value pairs.

I would appreciate any help. Thank you.

public class ServletResponseWrapper extends HttpServletResponseWrapper {

    private int httpStatus = SC_OK;
    private HashMap<String, String> hashMapHeaders = new HashMap<String, String>();

    public ServletResponseWrapper(HttpServletResponse response) {
        super(response);
    }

    @Override
    public void sendError(int sc) throws IOException {
        httpStatus = sc;
        super.sendError(sc);
    }

    @Override
    public void sendError(int sc, String msg) throws IOException {
        httpStatus = sc;
        super.sendError(sc, msg);
    }


    @Override
    public void setStatus(int sc) {
        httpStatus = sc;
        super.setStatus(sc);
    }

    public int getStatus() {
        return httpStatus;
    }

    @Override
    public void sendRedirect(String location) throws IOException {
        httpStatus = SC_MOVED_TEMPORARILY;
        super.sendRedirect(location);
    }

    @Override
    public void setHeader(String name, String value) {
        hashMapHeaders.put(name, value);
        super.setHeader(name, value);
    }

    public String getHeader(String name) {
        return hashMapHeaders.get(name);
    }


    public Enumeration<String> getHeaderNames() {
        Enumeration<String> enumerationHeaderNames = Collections.enumeration(hashMapHeaders.keySet());
        return enumerationHeaderNames;
    }

}

public class ServletResponseWrapperFilter implements Filter {

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        ServletResponseWrapper servletResponseWrapper = new ServletResponseWrapper( (HttpServletResponse) response );
        chain.doFilter( request, servletResponseWrapper );

        // Process response

        // This works, even though I never explicitly call the setStatus() method
        int status = response.getStatus();

        // This returns NULL because no header values get set; I presume setHeader() gets called implicitly
        Enumeration<String> headerNames = servletResponseWrapper.getHeaderNames();
    }

    public void init(FilterConfig config) throws ServletException {
        //empty
    }

    public void destroy() {
        // empty
    }
}

web.xml file

<display-name>Tomcat App</display-name>

<filter>
    <filter-name>ResponseHeadersFilter</filter-name>
    <filter-class>com.company.filters.ResponseHeadersFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>ResponseHeadersFilter</filter-name>
    <url-pattern>/testfilter.jsp</url-pattern>
</filter-mapping>

I took the vendor's servlet out of the equation. The filter now fires on an empty JSP file. Tomcat is also hooked to a front-end web server, IIS. I disabled IIS. Now, I'm accessing the website directly over Tomcat, via port 8080. Despite all this, I dot see any response headers.

Using Fiddler, the response headers I see are few but existing, namely:

  • (Cache) Date
  • (Entity) Content- Length, Content-Type
  • (Miscellaneous) Server
  • And status response, i.e. HTTP/1.1 200 OK

I can get by without getting response headers in the filter. But the big question I have is this is a bug with Servlet version 2.4 or is there some kind of OS Server and/or Tomcat configuration change I need to enable? Unless there's some Tomcat configuration, I'm led to believe this is likely a bug. Perhaps a clean install using the default configuration of the Tomcat version I'm using, 5.5.28, would resolve the problem, but I cannot attempt that at this time.

Community
  • 1
  • 1
user3621633
  • 1,681
  • 3
  • 32
  • 46
  • is the code which processes the response written by you? Can you show it? – JimHawkins Mar 02 '16 at 07:20
  • Unfortunately, no. It's not written by me. It's a rather complex servlet written by a vendor. Does my filter and wrapper code look OK? – user3621633 Mar 02 '16 at 16:09
  • I also want to add I commented out all existing filter declarations and mappings, except the one here. Even if I didn't, only one filter is mapped to the vendor's servlet -- again, that filter is the one discussed here. There should be no order of execution conflicts, then. Still, no response headers. Maybe a bug with Servlet 2.4? – user3621633 Mar 02 '16 at 17:10
  • the code of your filter and wrapper seem OK. Can you post your web.xml? – JimHawkins Mar 03 '16 at 07:11
  • I took out everything but what's needed for this filter to work and took the vendor's servlet out of the equation. Now the filter just operates on an empty JSP file. Tomcat was also linked to a front-end web server, IIS. I disabled IIS and I'm accessing the Tomcat server directly. With all these steps to remove variables, despite all of it, the response headers still are not displaying. – user3621633 Mar 03 '16 at 19:07
  • 1
    There are 6 methods which can manipulate response headers. You're overriding only one of them. Try others too. – BalusC Mar 03 '16 at 19:32
  • I see, thank you. Can you write or link to what those 6 methods are? From this link, http://geronimo.apache.org/maven/specs/geronimo-servlet_2.4_spec/apidocs/javax/servlet/http/HttpServletResponse.html, and this one, https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServletResponseWrapper.html, it would appear what you're speaking of are `addHeader`, `addDateHeader`, `addIntHeader`, `setHeader`, `setDateHeader`, and `setIntHeader`. Is this accurate? If so, I will try to override those and observe the results. Thanks, again. – user3621633 Mar 03 '16 at 19:38
  • I observed and still no response headers. I overrode all 6 methods above and still no luck. At this point, I'm thinking a configuration issue or a bug, either with Servlet 2.4 and/or the servlet container I'm using here, Tomcat 5.5.28. Perhaps a clean, default install would resolve the problem but I can't attempt that at this time. I can workaround this response header issue, however. Thank you all for your help. It is most appreciated and I always learn something. – user3621633 Mar 03 '16 at 20:09

0 Answers0