Страница ошибки весенней загрузки с обработчиками ресурсов

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

Спасибо!

Другие вопросы по тегам