2011-10-25 17 views
24

Tengo una situación en la que uno de los encabezados de respuesta Content-Disposition tiene que ser eliminado. Así que pensé en escribir un filtro de servlet para hacer esto. Pero me di cuenta de que el HttpServletResponse tiene solo un método setHeader() pero no hay ningún método para eliminarlo. ¿Cómo puedo hacer esto?¿Cómo eliminar un encabezado de respuesta HTTP?

Respuesta

35

No puede eliminar encabezados posteriormente mediante la API de Servlet estándar. Su mejor opción es simplemente evitar que se establezca el encabezado. Puede hacer esto creando un Filter que reemplaza el ServletResponse con una implementación personalizada HttpServletResponseWrapper que omite el trabajo setHeader() siempre que el nombre del encabezado sea Content-Disposition.

Básicamente:

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

Sólo mapa que filtro en el patrón de URL de interés para conseguir que se ejecute.

+0

Esto ayudó. Gracias por tu publicación. – Daniel

+0

De nada. – BalusC

+0

Este método falla al intentar evitar el encabezado "Servidor". Creo que está siendo configurado por contenedor. – itsraja

3

Esto puede no ser compatible con Servlet API, pero establecer el valor de nulo funciona en GlassFish 4 y probablemente en Tomcat también, ya que eso es lo que está debajo de GlassFish.

Necesitamos actualizar la especificación de la API del servlet para agregar un método que permita eliminar encabezados o para admitir oficialmente el uso de setHeader con un valor nulo.

Un ejemplo donde esto es importante es si usa una restricción de seguridad (SSL/TLS) en su aplicación web, entonces el almacenamiento en memoria caché está complicado por el hecho de que el contenedor agregará encabezados automáticamente para evitar el almacenamiento en caché (puede intentar deshabilitar con disableProxyCaching y securePagesWithPragma en Tomcat/GlassFish). Ya tengo un filtro de servlet para el control de caché que funciona muy bien para contenido no seguro, por lo que me gustaría mantener el control de caché en un solo lugar y simplemente configurar Prama y Cache-Control para anular cualquier encabezado agregado de contenedor.

1

Esto no funciona para mí usando Spring 4. Estoy intentando quitar el encabezado de respuesta Expires. Por cada página De este modo:

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

Y aquí es cómo agrego el filtro:

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() se llama para Expira y Cache-Control, pero no puedo anular el valor de filtro expira, o el valor de Cache-Control. Puedo agregar al valor de Cache-Control. Se convierte en una matriz de valores si invoco setHeader en Cache-Control. Pero necesito eliminar el encabezado.

0

Como las otras respuestas. No hay forma de eliminar un encabezado después de haberlo configurado, al menos no de forma estándar (glassfish permite borrar un encabezado configurando su valor como nulo). Entonces, al final del día, tendría dos opciones:

  1. restablecer la respuesta.

    response.reset()

Esto elimina de forma efectiva todos los encabezados y también cualquier datos en el búfer, dependiendo de que el caso puede ser una buena alternativa (en mi caso fue después de los errores de validación de autenticación). Si la respuesta ya está comprometida, obtendrá una IllegalStateException.

  1. Establecer encabezado para vaciar cadena, claramente esto no elimina el encabezado. Pero la especificación http solo tiene algunas definiciones y valores vacíos en las etiquetas Aceptar codificación, TE (codificación de transferencia) y HOST, por lo que dependiendo de sus necesidades puede controlar eso en su capa de aplicación.
Cuestiones relacionadas