Фильтр сервлетов: как получить все заголовки из servletRequest?

Вот как выглядит мой WebFilter

@WebFilter("/rest/*")
public class AuthTokenValidatorFilter implements Filter {

    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
        final Enumeration<String> attributeNames = servletRequest.getAttributeNames();
        while (attributeNames.hasMoreElements()) {
            System.out.println("{attribute} " + servletRequest.getParameter(attributeNames.nextElement()));
        }

        final Enumeration<String> parameterNames = servletRequest.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            System.out.println("{parameter} " + servletRequest.getParameter(parameterNames.nextElement()));
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
    }
}

Я попытался узнать в Интернете, как получить значения для HTTP headers, поступающие из запроса.

Я ничего не нашел, поэтому я попытался перечислить по servletRequest.getAttributeNames() и servletRequest.getParameterNames(), ничего не зная, но не получая заголовков.

Вопрос
Как получить все заголовки запроса?


person daydreamer    schedule 11.08.2014    source источник


Ответы (3)


Преобразование ServletRequest в HttpServletRequest (только если ServletRequest request является instanceof HttpServletRequest).

Затем вы можете использовать методы HttpServletRequest.getHeader() и HttpServletRequest.getHeaderNames().

Что-то вроде этого:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    Enumeration<String> headerNames = httpRequest.getHeaderNames();

    if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                    System.out.println("Header: " + httpRequest.getHeader(headerNames.nextElement()));
            }
    }

    //doFilter
    chain.doFilter(httpRequest, response);
}
person Buhake Sindi    schedule 11.08.2014
comment
@BuhakeSindi есть индикаторы, при каких обстоятельствах ServletRequest может быть чем-то. отличается от HttpServletRequest? - person sthzg; 17.10.2015
comment
'HttpServletReqiest' ЯВЛЯЕТСЯ 'ServletRequest'. Это подинтерфейс. СервлетЗапрос. Могут быть различные классы/интерфейсы ServletRequest, такие как «PortletRequest», поэтому всегда нужно выполнять проверку «instanceof» для различных типов сервлетов. - person Buhake Sindi; 17.10.2015
comment
Почему getHeaderNames(); пропустил какой-то заголовок, такой как x-forward-for, детали поддержания активности и т. д.? - person Asif Mushtaq; 26.08.2016
comment
@UnKnown эти заголовки заполняются прокси-серверами. Это должно быть настроено на уровне сервера. Сервлет просто возвращает параметры, установленные этими серверами. - person Buhake Sindi; 21.02.2017

В Java 8+ вы можете использовать поток для сбора заголовков запросов:

HttpServletRequest httpRequest = (HttpServletRequest) request;

Map<String, String> headers = Collections.list(httpRequest.getHeaderNames())
    .stream()
    .collect(Collectors.toMap(h -> h, httpRequest::getHeader));

ОБНОВЛЕНО

@Matthias напомнил мне, что заголовки могут иметь несколько значений:

Map<String, List<String>>

Map<String, List<String>> headersMap = Collections.list(httpRequest.getHeaderNames())    
    .stream()
    .collect(Collectors.toMap(
        Function.identity(), 
        h -> Collections.list(httpRequest.getHeaders(h))
    ));

org.springframework.http.HttpHeaders

HttpHeaders httpHeaders = Collections.list(httpRequest.getHeaderNames())
    .stream()
    .collect(Collectors.toMap(
        Function.identity(),
        h -> Collections.list(httpRequest.getHeaders(h)),
        (oldValue, newValue) -> newValue,
        HttpHeaders::new
    ));

https://gist.github.com/Cepr0/fd5d9459f17da13b29126cf313328fe3

person Cepr0    schedule 11.04.2018
comment
вы пытались это скомпилировать? - person Eugene; 13.02.2019
comment
Мне пришлось немного подправить его для весны - response.getHeaderNames() .stream() .collect(Collectors.toMap( Function.identity(), h -> new ArrayList<>(response.getHeaders(h)), (oldValue, newValue) -> newValue, HttpHeaders::new )); - person bobmarksie; 21.10.2019
comment
@bobmarksie в вашем варианте вы используете response, но вопрос был о request. К сожалению, HttpServletRequest#getHeaderNames возвращает Enumeration, а не Collection. - person Cepr0; 21.10.2019
comment
Спасибо @Cepr0! Все еще нашел ваш ответ очень полезным, хотя я использовал его по-другому. - person bobmarksie; 22.10.2019

Вы должны учитывать, что один и тот же заголовок HTTP может встречаться несколько раз с разными значениями:

Map<String, Serializable> headers = Collections.list(request.getHeaderNames()).stream().collect(Collectors.toMap(h -> h, h -> {
    ArrayList<String> headerValues = Collections.list(request.getHeaders(h));
    return headerValues.size() == 1 ? headerValues.get(0) : headerValues;
}));
person Matthias    schedule 09.07.2019