Skip to content

ResourceHandlers cannot resolve static resources with certain wildcard patterns #29712

@mufasa1976

Description

@mufasa1976

Bug report

The following Code Snippet worked perfectly within Spring Boot 2.7.6

@Configuration
@EnableWebMvc
public class WebMvcConfiguration implements WebMvcConfigurer {
  private static final String[] ANGULAR_RESOURCES = {
      "/favicon.ico",
      "/main.*.js",
      "/polyfills.*.js",
      "/runtime.*.js",
      "/styles.*.css",
      "/deeppurple-amber.css",
      "/indigo-pink.css",
      "/pink-bluegrey.css",
      "/purple-green.css",
      "/3rdpartylicenses.txt"
  };
  private static final List<Locale> SUPPORTED_LANGUAGES = List.of(Locale.GERMAN, Locale.ENGLISH);
  private static final Locale DEFAULT_LOCALE = Locale.ENGLISH;

  private final String prefix;
  private final Collection<HttpMessageConverter<?>> messageConverters;

  public WebMvcConfiguration(@Value("${spring.thymeleaf.prefix:" + ThymeleafProperties.DEFAULT_PREFIX + "}") String prefix, Collection<HttpMessageConverter<?>> messageConverters) {
    this.prefix = StringUtils.appendIfMissing(prefix, "/");
    this.messageConverters = messageConverters;
  }

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.setOrder(1);
    registry.addResourceHandler("/webjars/**")
            .addResourceLocations("classpath:/META-INF/resources/webjars/");
    for (Locale language : SUPPORTED_LANGUAGES) {
      final var relativeAngularResources = Stream.of(ANGULAR_RESOURCES)
                                                 .filter(resource -> StringUtils.contains(resource, "*"))
                                                 .map(resource -> "/" + language.getLanguage() + resource)
                                                 .toArray(String[]::new);
      registry.addResourceHandler(relativeAngularResources)
              .addResourceLocations(prefix + language.getLanguage() + "/");

      final var fixedAngularResources = Stream.of(ANGULAR_RESOURCES)
                                              .filter(resource -> !StringUtils.contains(resource, "*"))
                                              .map(resource -> "/" + language.getLanguage() + resource)
                                              .toArray(String[]::new);
      registry.addResourceHandler(fixedAngularResources)
              .addResourceLocations(prefix);

      registry.addResourceHandler("/" + language.getLanguage() + "/assets/**")
              .addResourceLocations(prefix + language.getLanguage() + "/assets/");
    }
  }

  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
    registry.setOrder(2);
    for (Locale language : SUPPORTED_LANGUAGES) {
      registry.addViewController("/" + language.getLanguage() + "/**").setViewName(language.getLanguage() + "/index");
    }
  }

  @Bean
  public RouterFunction<ServerResponse> routerFunction() {
    return route(GET("/"), this::defaultLandingPage);
  }

  private ServerResponse defaultLandingPage(ServerRequest request) {
    final var locale = Optional.ofNullable(Locale.lookup(request.headers().acceptLanguage(), SUPPORTED_LANGUAGES))
                               .orElse(DEFAULT_LOCALE);
    return ServerResponse.status(HttpStatus.TEMPORARY_REDIRECT).render("redirect:/" + locale.getLanguage());
  }

  @Override
  public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.defaultContentType(APPLICATION_JSON);
  }

  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.addAll(messageConverters);
  }
}

Unfortunatly for Spring Boot 3.0.0 all Wildcard Resources (i.e. main.b35ffcc13cda91f0.js) wouldn't be served. Instead it will result in a HTTP 404 (Not Found).

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)status: backportedAn issue that has been backported to maintenance branchestype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions