web-dev-qa-db-ja.com

HTTP応答ヘッダーを削除するにはどうすればよいですか?

応答ヘッダー_Content-Disposition_の1つを削除する必要がある状況があります。そのため、これを行うサーブレットフィルターを作成することを考えました。しかし、HttpServletResponseにはsetHeader()メソッドしかなく、それを削除するメソッドがないことに気付きました。これどうやってするの?

31
Daniel

その後、標準のサーブレットAPIを使用してヘッダーを削除することはできません。あなたの最善の策は、ヘッダーが設定されるのを単に防ぐことです。これを行うには、 Filter を作成します。これは、ServletResponseをカスタムの HttpServletResponseWrapper 実装に置き換え、- setHeader() ヘッダー名がContent-Disposition

基本的に:

@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パターンにそのフィルターをマッピングして、実行するだけです。

43
BalusC

これはサーブレットAPIに準拠していない可能性がありますが、値をnullに設定するとGlassFish 4で機能し、おそらくGlassFishの下にあるTomcatでも機能します。

ヘッダーの削除を許可するメソッドを追加するか、null値でのsetHeaderの使用を正式にサポートするには、サーブレットAPI仕様を更新する必要があります。

これが重要な例は、Webアプリケーションでセキュリティ制約(SSL/TLS)を使用している場合、コンテナが自動的にヘッダーを追加してキャッシュを防止するという事実により、静的リソースのキャッシュは複雑になります(disableProxyCachingで無効にしようとすることができ、 Tomcat/GlassFishのsecurePagesWithPragma)。安全でないコンテンツに最適なキャッシュコントロール用のサーブレットフィルターをすでに持っているので、キャッシュコントロールをすべて1か所に保持し、PramaとCache-Controlをnullに設定して、コンテナーに追加されたヘッダーをクリアします。

3
Ryan

他の応答として。設定された後にヘッダーを削除する方法はありません。少なくとも標準ではありません(glassfishでは、値をnullに設定してヘッダーをクリアできます)。つまり、結局のところ、2つの選択肢があります。

  1. response.reset()を使用して応答をリセットします。これにより、すべてのヘッダーが削除され、バッファデータもすべて削除されます。場合によっては、適切な代替手段になる可能性があります(私の場合、認証検証エラーの後)。応答がすでにコミットされている場合は、IllegalStateExceptionが発生します。

  2. ヘッダーを空の文字列に設定します。これによりヘッダーが削除されることはありません。ただし、http仕様ではAccept-Encoding、TE(転送エンコーディング)、およびHostヘッダーの定義と空の値のみが含まれているため、ニーズに応じてアプリケーション層で制御できます。

1
le0diaz

これは、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を呼び出すと、値の配列になります。しかし、ヘッダーを削除する必要があります。

1
yetimoner