2011-10-25 2 views
24

J'ai une situation où l'un des en-têtes de réponse Content-Disposition doit être supprimé. J'ai donc pensé à écrire un filtre de servlet pour le faire. Mais j'ai réalisé que le HttpServletResponse a seulement une méthode setHeader() mais aucune méthode pour l'enlever. Comment puis-je faire cela?Comment supprimer un en-tête de réponse HTTP?

Répondre

35

Vous ne pouvez pas supprimer les en-têtes par la suite via l'API Servlet standard. Votre meilleur pari est de seulement empêcher l'en-tête d'être défini. Vous pouvez le faire en créant un Filter qui remplace le ServletResponse par une implémentation personnalisée HttpServletResponseWrapper qui ignore le travail de setHeader() lorsque le nom de l'en-tête est Content-Disposition.

En gros:

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

map Tout ce filtre sur l'URL motif d'intérêt pour l'obtenir pour fonctionner.

+0

Cela a aidé. Merci pour votre message. – Daniel

+0

De rien. – BalusC

+0

Cette méthode échoue lorsque vous tentez d'empêcher l'en-tête "Serveur". Je pense que c'est réglé par conteneur. – itsraja

3

Cela peut ne pas être conforme à l'API Servlet, mais définir la valeur sur null fonctionne sur GlassFish 4 et probablement sur Tomcat car c'est ce qui est sous GlassFish.

Nous avons vraiment besoin de mettre à jour la spécification de l'API Servlet pour ajouter une méthode permettant de supprimer des en-têtes ou de prendre officiellement en charge l'utilisation de setHeader avec une valeur nulle. Un exemple où cela est important est que si vous utilisez une contrainte de sécurité (SSL/TLS) sur votre application Web, la mise en cache statique des ressources est compliquée par le fait que le conteneur ajoutera automatiquement des en-têtes pour empêcher la mise en cache. désactiver avec disableProxyCaching et securePagesWithPragma sur Tomcat/GlassFish). J'ai déjà un filtre de servlet pour le contrôle du cache qui fonctionne bien pour le contenu non sécurisé, donc je voudrais garder le contrôle du cache en un seul endroit et simplement définir Prama et Cache-Control à null pour effacer les en-têtes ajoutés au conteneur.

1

Cela ne fonctionne pas avec Spring 4. J'essaie de supprimer l'en-tête de réponse Expires. Pour chaque page Comme si:

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

Et voici comment ajouter le filtre:

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() est appelé pour Expires et Cache-Control, mais je ne peux pas passer outre la Expires valeur du filtre, ou la valeur Cache-Control. Je peux ajouter à la valeur Cache-Control. Il se transforme en un tableau de valeurs si j'appelle setHeader sur Cache-Control. Mais j'ai besoin de supprimer l'en-tête.

0

Comme les autres réponses. Il n'y a aucun moyen de supprimer un en-tête après avoir été défini, du moins pas standard (glassfish efface un en-tête en définissant sa valeur sur null). Donc, à la fin de la journée, vous auriez deux choix:

  1. réinitialiser la réponse.

    response.reset()

Cela supprime efficacement tous les en-têtes et AUSSI DES DONNÉES TAMPON, selon vous cas peut être une bonne alternative (dans mon cas a été après des erreurs de validation d'authentification). Si la réponse est déjà validée, vous obtiendrez une exception IllegalStateException.

  1. Définissez l'en-tête sur la chaîne vide, cela ne supprime pas clairement l'en-tête. Mais la spécification http ne contient que des définitions et des valeurs vides dans les en-têtes Accept-Encoding, TE (transfert de codage) et HOST, ce qui vous permet de contrôler cela dans votre couche application.