如何删除HTTP响应头?

时间:2011-10-25 20:06:49

标签: servlets servlet-filters response-headers

我的情况是必须删除其中一个响应标头Content-Disposition。所以我想写一个servlet过滤器来做到这一点。但我意识到HttpServletResponse只有setHeader()方法但没有方法可以删除它。 我怎么能这样做?

4 个答案:

答案 0 :(得分:42)

之后,您无法通过标准Servlet API删除标头。您最好的选择是阻止标头设置。您可以通过创建Filter来替换ServletResponse并使用自定义HttpServletResponseWrapper实施来执行此操作,只要标题名称为Content-Disposition,就会跳过setHeader()的作业

基本上:

@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);
            }
        }
    });
}

只需将该过滤器映射到感兴趣的网址模式即可运行。

答案 1 :(得分:3)

这可能不符合Servlet API,但将值设置为null可以在GlassFish 4上运行,也可能在Tomcat上运行,因为它就是GlassFish下面的内容。

我们确实需要更新Servlet API规范,以添加允许删除标头的方法或正式支持使用带有空值的setHeader。

这一点非常重要的一个示例是,如果您在Web应用程序上使用安全约束(SSL / TLS),那么静态资源缓存会因容器将自动添加标头以防止缓存而变得复杂(您可以尝试禁用在Tomcat / GlassFish上使用disableProxyCaching和securePagesWithPragma)。我已经有一个用于缓存控制的servlet过滤器,非常适合非安全内容,所以我想将缓存控制全部保存在一个地方,只需将Prama和Cache-Control设置为null即可清除任何容器添加的标题。

答案 2 :(得分:1)

这对我使用Spring 4不起作用。我试图删除Expires响应头。对于每一页。像这样:

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 {}
}

以下是我添加过滤器的方法:

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));
    }
}

为Expires和Cache-Control调用setHeader(),但我无法覆盖Expires过滤器值或Cache-Control值。我可以添加到Cache-Control值。如果我在Cache-Control上调用setHeader,它将变成一个值数组。但我需要删除标题。

答案 3 :(得分:1)

正如其他回应。设置后无法删除标题,至少不是标准(glassfish允许清除标题,将其值设置为null)。所以在一天结束时你会有两个选择:

  1. 使用response.reset()重置响应 - 这有效地删除了所有标头以及任何缓冲数据,具体取决于您的情况可能是一个不错的选择(在我的情况下是在验证验证错误之后)。如果响应已经提交,则会收到IllegalStateException。

  2. 将标题设置为空字符串,显然这不会删除标题。但http规范在Accept-Encoding,TE(传输编码)和HOS​​T头中只有一些定义和空值,因此根据您的需要,您可以在应用层中控制它。