Страница ошибки весенней загрузки с обработчиками ресурсов
tl;dr: как включить Spring ResourceUrlEncodingFilter для страниц ошибок весенней загрузки?
(Вопрос написан при использовании весенней загрузки 1.3.7.RELEASE и Spring Framework/MVC 4.2.4.RELEASE)
Немного предыстории: у нас есть довольно стандартный Spring Boot / Spring Webmvc проект, использующий Thymeleaf в качестве слоя представления. У нас есть готовая цепочка ресурсов с пружинной загрузкой, позволяющая обслуживать статические ресурсы.
Наши представления тимелист имеют стандартный синтаксис URL-кодирования в них, такие как <script th:src="@{/js/some-page.js}"></script>
, Это зависит от весны org.springframework.web.servlet.resource.ResourceUrlEncodingFilter
чтобы преобразовать URL в URL с соответствующей версией, такой как /v1.6/js/some-page.js
,
Наша обработка ошибок выполняется:
- установка
server.error.whitelabel.enabled=false
- Подклассификация весеннего ботинка по умолчанию
BasicErrorController
переопределитьpublic ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response)
- полагаясь на уже сконфигурированные обработчики представления тимилиста, чтобы отобразить нашу пользовательскую страницу ошибок
Проблема в том, что ResourceUrlEncodingFilter не применяется на наших страницах ошибок. Я предполагаю, что это отсутствие фильтра, регистрируемого для отправленных запросов ERROR, но для меня не очевидно: а) как настроить это при весенней загрузке; и б) почему это не было сделано по умолчанию.
Обновление 1:
Проблема, кажется, с сочетанием OncePerRequestFilter
и ОШИБКА диспетчер. А именно:
ResouceUrlEncodingFilter
по умолчанию не привязывается к диспетчеру ошибок. Несмотря на то, что переопределить это грязно, это не невозможно, но не помогает из-за:OncePerRequestFilter
(родительResourceUrlEncodingFilter
) устанавливает атрибут в Запросе, указывающий, что он был применен, чтобы не применяться повторно. Затем он оборачивает объект ответа. Однако при отправке ОШИБКИ упакованный ответ не используется, и фильтр не переупаковывается из-за того, что атрибут запроса все еще присутствует.
Что еще хуже, логика для настройки boolean hasAlreadyFilteredAttribute
не может быть переопределено по запросу. OncePerRequestFilter
"s doFilter()
метод является окончательным, и getAlreadyFilteredAttributeName()
(точка расширения) не имеет доступа к текущему объекту запроса для получения диспетчера.
Я чувствую, что я должен что-то упустить; Кажется невозможным использовать версионные ресурсы на странице 404 при весенней загрузке.
Обновление 2: рабочее, но грязное решение
Это лучшее, что я смог придумать, что до сих пор кажется ужасно грязным:
public abstract class OncePerErrorRequestFilter extends OncePerRequestFilter {
@Override
protected String getAlreadyFilteredAttributeName() {
return super.getAlreadyFilteredAttributeName() + ".ERROR";
}
@Override
protected boolean shouldNotFilterErrorDispatch() {
return false;
}
}
public class ErrorPageCapableResourceUrlEncodingFilter extends OncePerErrorRequestFilter {
// everything in here is a perfect copy-paste of ResourceUrlEncodingFilter since the internal ResourceUrlEncodingResponseWrapper is private
}
// register the error-supporting version if the whitelabel error page has been disabled ... could/should use a dedicated property for this
@Configuration
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
@ConditionalOnClass(OncePerErrorRequestFilter.class)
@ConditionalOnWebApplication
@ConditionalOnEnabledResourceChain
@ConditionalOnProperty(prefix = "server.error.whitelabel", name = "enabled", havingValue="false", matchIfMissing = false)
public static class ThymeleafResourceUrlEncodingFilterErrorConfiguration {
@Bean
public FilterRegistrationBean errorPageResourceUrlEncodingFilterRegistration() {
FilterRegistrationBean reg = new FilterRegistrationBean();
reg.setFilter(new ErrorPageCapableResourceUrlEncodingFilter());
reg.setDispatcherTypes(DispatcherType.ERROR);
return reg;
}
}
Лучшие решения?
1 ответ
Об этом сообщается в https://github.com/spring-projects/spring-boot/issues/7348, и исправление уже в пути.
Похоже, вы сделали обширный анализ проблемы; Жаль, что вы не сообщили об этой проблеме ранее. В следующий раз, пожалуйста, подумайте о том, чтобы поднять их на трекере Spring Boot
Спасибо!