Невозможно получить тело ответа в моем фильтре. Кэширование включено.
Я испробовал множество реализаций фильтров - 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. Я думаю, что это как-то связано с асинхронной обработкой запроса.