如何删除 HTTP 响应标头?

Posted

技术标签:

【中文标题】如何删除 HTTP 响应标头?【英文标题】:How do delete a HTTP response header? 【发布时间】:2011-12-15 06:18:27 【问题描述】:

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

【问题讨论】:

【参考方案1】:

之后您无法通过标准 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);
            
        
    );

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

【讨论】:

此方法在尝试阻止“Server”标头时失败。我认为它是由容器设置的。 @itsraja:确实。您需要在服务器自己的配置中控制它。上面介绍的过滤器只控制chain.doFilter()后面的整个过程中webapp设置的headers。它不控制在此之前或之后设置的标题。顺便说一句,这很有意义:) 也应该覆盖addHeader(String name, String value) @Milanka:有 6 个。只需覆盖代码库中使用的任何内容。 为我工作。只需确保首先运行此过滤器。在我的情况下,在配置方法中的 webSecurityConfigurationAdapter 作为第一个过滤器:httpSecurity.addFilterBefore(HeaderUnsetFilter(), HeaderWriterFilter.class);【参考方案2】:

这可能不符合 Servlet API,但将值设置为 null 可以在 GlassFish 4 上工作,也可能在 Tomcat 上工作,因为那是 GlassFish 下的内容。

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

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

【讨论】:

【参考方案3】:

与其他回复一样。设置后无法删除标头,至少不是标准的(glassfish 可以清除标头,将其值设置为空)。所以最终你会有两个选择:

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

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

【讨论】:

【参考方案4】:

这对我使用 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,它会变成一个值数组。但我需要删除标题。

【讨论】:

以上是关于如何删除 HTTP 响应标头?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 EB 响应中删除标头

为啥不能通过 IIS7 中的 web.config 删除“服务器”响应标头?

如何从响应标头中的内容类型中删除 charset=utf-8

如何从放心的响应中删除xml标头

如何删除 AFNetworking 中的 http 标头选项?

如何使用中间件删除服务器标头?