How do delete a HTTP response header?
Asked Answered
S

4

40

I have a situation where one of the response headers Content-Disposition has to be removed. So I thought of writing a servlet filter to do this. But I realized that the HttpServletResponse has only a setHeader() method but no method to remove it. How can I do this?

Subcontinent answered 25/10, 2011 at 20:6 Comment(0)
H
57

You can't delete headers afterwards by the standard Servlet API. Your best bet is to just prevent the header from being set. You can do this by creating a Filter which replaces the ServletResponse with a custom HttpServletResponseWrapper implementation which skips the setHeader()'s job whenever the header name is Content-Disposition.

Basically:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
        public void setHeader(String name, String value) {
            if (!name.equalsIgnoreCase("Content-Disposition")) {
                super.setHeader(name, value);
            }
        }
    });
}

Just map that filter on the URL-pattern of interest to get it to run.

Halvaard answered 25/10, 2011 at 20:14 Comment(11)
This method fails when trying to prevent "Server" header. I think it is being set by container.Schiro
@itsraja: Indeed. You need to control it in server's own config. The filter presented above only controls the headers set by webapp during the whole process behind chain.doFilter(). It does not control the headers set before or after that. Which makes quite sense, by the way :)Halvaard
am trying to reset "Server" to some value for websphere server community edition, and yet to nail how to do it.Schiro
"Server" header can not be removed but can be updated. In websphere /var/config/config.xml, <gbean name="TomcatWebConnector"> , add an attribute "server" with desired value. For Tomcat, server.xml, Connector tag "server" attribute.Schiro
One should probably override addHeader(String name, String value) too.Moriyama
@Milanka: There are 6 of them. Just override whatever's being used in your codebase.Halvaard
Worked for me. Just had to make sure, that this filter was run first. In my case in the webSecurityConfigurationAdapter in the configure method as first filter: httpSecurity.addFilterBefore(HeaderUnsetFilter(), HeaderWriterFilter.class);Chinkiang
@Halvaard This filter removes header only if success response and doesn't remove the headers if error response.Undersize
@Akshay: that's only the case if you don't let the filter listen on FORWARD dispatcher. That's where among others the error pages run through.Halvaard
@Halvaard Any way to remove Response headers in case of error response / exception?Undersize
@Akshay: as said, also let the filter listen on FORWARD dispatcher.Halvaard
P
4

This may not be Servlet API compliant, but setting the value to null works on GlassFish 4 and probably on Tomcat too as that is what is underneath GlassFish.

We really need to update the Servlet API specification to either add a method to allow removing headers or to officially support using setHeader with a null value.

An example where this is important is if you use a security constraint (SSL/TLS) on your web application then static resource caching is complicated by the fact that the container will automatically add headers to prevent caching (you can try to disable with disableProxyCaching and securePagesWithPragma on Tomcat/GlassFish). I've already got a servlet filter for cache control that works great for non-secure content so I would like to keep cache control all in one place and simply set Prama and Cache-Control to null to clear any container added headers.

Pardoes answered 16/10, 2014 at 17:59 Comment(0)
G
3

As the other responses. There is no way to remove a header after being set, at least not standard (glassfish lets clear a header setting it's value to null). So at the end of the day you would have two choices:

  1. Reset the response with response.reset() - This effectively removes ALL headers AND ALSO ANY BUFFERED DATA, depending on you case can be a good alternative (in my case was after authentication validation errors). If the response is already committed you'll get an IllegalStateException.

  2. Set header to empty string, clearly this doesn't remove the header. But the http specification only has some definitions for and empty value in the Accept-Encoding, TE (transfer encoding) and HOST headers, so depending in your needs you can control that in your application layer.

Gwenn answered 7/4, 2016 at 16:57 Comment(0)
R
1

This does not work for me using Spring 4. I'm trying to strip out the Expires response header. For every page. Like so:

public class CachingFilter implements Filter {
    private final Log logger = LogFactory.getLog(getClass());

    public CachingFilter() {}
    public void destroy() {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        logger.debug("doFilter()");
        chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
            public void setHeader(String name, String value) {
                logger.debug("setHeader(" + name + ","+value+")");

                if (!name.equalsIgnoreCase("Expires")) {
                    super.setHeader(name, value);
                }
            }
        });
    }

    public void init(FilterConfig fConfig) throws ServletException {}
}

And here is how I add the filter:

public class AppConfig implements WebApplicationInitializer {
    private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
    private static final String DISPATCHER_SERVLET_MAPPING = "/";

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(AppContext.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, new DispatcherServlet(rootContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping(DISPATCHER_SERVLET_MAPPING);

        EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);

        FilterRegistration.Dynamic noCache = servletContext.addFilter("noCacheFilter", new CachingFilter());
        noCache.addMappingForUrlPatterns(dispatcherTypes, true, "/*");

        servletContext.addListener(new ContextLoaderListener(rootContext));
    }
}

setHeader() being called for Expires and Cache-Control, but I can't override the Expires filter value, or the Cache-Control value. I can add to the Cache-Control value. It turns into an array of values if I call setHeader on Cache-Control. But I need to delete the header.

Rana answered 25/2, 2016 at 6:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.