Как удалить заголовок ответа HTTP? - PullRequest
27 голосов
/ 26 октября 2011

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

Ответы [ 4 ]

43 голосов
/ 26 октября 2011

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

3 голосов
/ 16 октября 2014

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

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

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

1 голос
/ 07 апреля 2016

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

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

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

1 голос
/ 25 февраля 2016

Это не работает для меня с использованием 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. Но мне нужно удалить заголовок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...