Подтвердить что ты не робот

Как удалить заголовок ответа HTTP?

У меня есть ситуация, когда один из заголовков ответов Content-Disposition должен быть удален. Поэтому я подумал о создании фильтра сервлета для этого. Но я понял, что HttpServletResponse имеет только метод setHeader(), но не имеет способа удалить его. Как я могу это сделать?

4b9b3361

Ответ 1

После этого вы не можете удалить заголовки стандартным 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-шаблону, чтобы запустить его.

Ответ 2

Это не может быть совместимым с Servlet API, но установка значения null работает на GlassFish 4 и, вероятно, на Tomcat, так как это то, что находится под GlassFish.

Нам действительно нужно обновить спецификацию API сервлета, чтобы добавить метод, позволяющий удалить заголовки или официально поддерживать с помощью setHeader с нулевым значением.

Примером, где это важно, является использование ограничения безопасности (SSL/TLS) в вашем веб-приложении, тогда статическое кэширование ресурсов осложняется тем фактом, что контейнер будет автоматически добавлять заголовки для предотвращения кеширования (вы можете попытаться отключить с disableProxyCaching и securePagesWithPragma на Tomcat/GlassFish). У меня уже есть фильтр сервлета для управления кешем, который отлично подходит для небезопасного контента, поэтому я хотел бы сохранить управление кешем в одном месте и просто установить Prama и Cache-Control на null, чтобы очистить заголовки, добавленные контейнером.

Ответ 3

Это не работает для меня с помощью 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));
    }
}

setHeader() вызывается для Expires и Cache-Control, но я не могу переопределить значение фильтра Expires или значение Cache-Control. Я могу добавить значение Cache-Control. Он превращается в массив значений, если я вызываю setHeader на Cache-Control. Но мне нужно удалить заголовок.

Ответ 4

Как и другие ответы. Невозможно удалить заголовок после установки, по крайней мере, не стандартный (glassfish позволяет очистить заголовок, установив его значение в ноль). Таким образом, в конце дня у вас будет два варианта:

  1. Сбросьте ответ с помощью response.reset() - это эффективно удаляет ВСЕ заголовки и ТАКЖЕ ЛЮБЫЕ БУФЕРНЫЕ ДАННЫЕ, в зависимости от вашего случая может быть хорошей альтернативой (в моем случае это было после ошибок проверки подлинности). Если ответ уже зафиксирован, вы получите исключение IllegalStateException.

  2. Установите заголовок в пустую строку, очевидно, это не удалит заголовок. Но в спецификации http есть только некоторые определения и пустые значения в заголовках Accept-Encoding, TE (Transfer Encoding) и HOST, поэтому в зависимости от ваших потребностей вы можете контролировать это на уровне приложения.