I want to serve react app with routes from Spring Boot with WebFlux and functional routing.
I'm trying to implement following rules:
There are few /api
endpoints that should be routed with functions.
Everything starting with the /static
should serve static content.
Everything else should serve index.html
I've added following function:
@Bean
RouterFunction<ServerResponse> routerFunction(Handler1 handler1,
Handler2 handler2) {
HandlerFunction<ServerResponse> indexPage = (req) -> ServerResponse.ok().bodyValue(new ClassPathResource("public/index.html"));
return RouterFunctions.route()
.GET("/api/route1", handler1)
.POST("/api/route2", handler2)
.resources("/static/**", new ClassPathResource("/public/**"))
.GET("/**", indexPage)
.build();
}
API routes work fine, but when I try to get any static content I get index page.
Changing /**
to /
allows me get static content as well as index page by /
route.
Based on the documentation route with static has should be checked first, but somehow it becomes overridden with the last wildcard route.
Router functions are evaluated in order: if the first route does not match, the second is evaluated, and so on. Therefore, it makes sense to declare more specific routes before general ones.
What am I missing?
Figured it out. ClassPathResource
accepts path to location. No need for wildcards.
With GET("/*", indexPage)
static resources were served not using resources("/static/**", new ClassPathResource("/public/**"))
, but with the default webflux configuration spring.webflux.static-path-pattern
.
Correct router function declaration:
@Bean
RouterFunction<ServerResponse> routerFunction(Handler1 handler1,
Handler2 handler2) {
HandlerFunction<ServerResponse> indexPage = (req) -> ServerResponse.ok().bodyValue(new ClassPathResource("public/index.html"));
return RouterFunctions.route()
.GET("/api/route1", handler1)
.POST("/api/route2", handler2)
.resources("/static/**", new ClassPathResource("/public/"))
.GET("/**", indexPage)
.build();
}