Тело ответа пусто даже при включенном кэшировании - PullRequest
1 голос
/ 25 октября 2019

Невозможно получить тело ответа в моем фильтре. Кэширование включено.

Я испробовал множество реализаций фильтров - Filter, OncePerRequestFilter и GenericFilterBean. Я также попытался написать собственный механизм кэширования, но не из этой работы. У меня уже работает один фильтр журналирования - этот фильтр выполняется перед новым и служит для чтения запросов и ответов. Фильтр журналирования работает, но я хочу добавить еще один, который читает ответ и проверяет его на соответствие XSD. Проблема в том, что фильтр журналирования получает заполненный ответ OK, но фильтр валидатора XML получает пустую строку.

Мой метод @Controller просто возвращает Callable. Асинхронная обработка может не быть проблемой, потому что фильтр журнала работает хорошо.

@Component
public class ResposeBodyXmlValidator extends OncePerRequestFilter {
    private final XmlUtils xmlUtils;
    private final Resource xsdResource;

    public ResposeBodyXmlValidator(
        XmlUtils xmlUtils,
        @Value("classpath:xsd/some.xsd") Resource xsdResource
    ) {
        this.xmlUtils = xmlUtils;
        this.xsdResource = xsdResource;
    }

    @Override
    protected void doFilterInternal(
        HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain
    ) throws ServletException, IOException {
        ContentCachingResponseWrapper response = new ContentCachingResponseWrapper(httpServletResponse);

        doFilter(httpServletRequest, response, filterChain);

        if (MediaType.APPLICATION_XML.getType().equals(response.getContentType())) {
            try {
                xmlUtils.validate(new String(response.getContentAsByteArray(), response.getCharacterEncoding()), xsdResource.getInputStream());
            } catch (IOException | SAXException e) {
                String exceptionString = String.format("Chyba při volání %s\nNevalidní výstupní XML: %s",
                    httpServletRequest.getRemoteAddr(),
                    e.getMessage());
                response.setContentType(MediaType.TEXT_PLAIN_VALUE + "; charset=UTF-8");
                response.setCharacterEncoding(StandardCharsets.UTF_8.name());
                response.getWriter().print(exceptionString);
            }
        }
        response.copyBodyToResponse(); // I found this needs to be added at the end of the filter
    }
}

Я ожидаю, что все мои фильтры смогут читать тело ответа, которое кэшируется.

Обновление

Я сам ошибся. Даже LoggerFilter не может читать seponse. Я думаю, что это как-то связано с асинхронной обработкой запроса.

1 Ответ

0 голосов
/ 25 октября 2019

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

...