web-dev-qa-db-fra.com

Comment supprimer un en-tête de réponse HTTP?

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 je me suis rendu compte que la HttpServletResponse a seulement une méthode setHeader() mais aucune méthode pour la supprimer . Comment puis-je faire cela?

26
Daniel

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

Fondamentalement:

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

Mappez simplement ce filtre sur le modèle d'URL qui vous intéresse afin de l'exécuter.

40
BalusC

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

Nous devons vraiment mettre à jour la spécification de l'API Servlet afin d'ajouter une méthode permettant de supprimer les en-têtes ou de prendre officiellement en charge l'utilisation de setHeader avec une valeur null. 

Par exemple, 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 (vous pouvez essayer de désactiver avec disableProxyCaching et securePagesWithPragma sur Tomcat/GlassFish). J'ai déjà un filtre de servlet pour le contrôle du cache qui convient parfaitement au contenu non sécurisé. J'aimerais donc garder le contrôle du cache au même endroit et définir simplement Prama et Cache-Control sur null pour effacer tous les en-têtes ajoutés au conteneur.

3
Ryan

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

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 j'ajoute 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 () étant appelé pour Expires et Cache-Control, mais je ne peux pas remplacer la valeur du filtre Expires ou la valeur de 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 je dois supprimer l'en-tête.

1
yetimoner

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 permet d'effacer 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 TOUTES LES DONNEES BUFFEREDES. Selon votre cas, cela peut être une bonne alternative (dans mon cas, c'était 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 header pour une chaîne vide, ceci ne supprime manifestement pas l'en-tête. Mais la spécification http ne contient que quelques définitions et une valeur vide dans les en-têtes Accept-Encoding, TE (encodage de transfert) et Host, vous pouvez donc contrôler cela en fonction de vos besoins.
0
le0diaz