22
33import org .springframework .boot .SpringApplication ;
44import org .springframework .boot .autoconfigure .SpringBootApplication ;
5+ import org .springframework .context .annotation .Bean ;
6+ import org .springframework .core .io .ClassPathResource ;
7+ import org .springframework .web .servlet .function .RequestPredicate ;
8+ import org .springframework .web .servlet .function .RouterFunction ;
9+ import org .springframework .web .servlet .function .ServerResponse ;
10+
11+ import static org .springframework .web .servlet .function .RequestPredicates .path ;
12+ import static org .springframework .web .servlet .function .RequestPredicates .pathExtension ;
13+ import static org .springframework .web .servlet .function .RouterFunctions .route ;
514
615@ SpringBootApplication
716public class Application {
@@ -11,9 +20,21 @@ public static void main(String[] args) {
1120 app .run (args );
1221 }
1322
14-
15-
1623 public static SpringApplication configureApplication () {
1724 return new SpringApplication (Application .class );
1825 }
26+
27+ /**
28+ * This is a custom router function to accommodate to our single page application that we serve from this spring boot backend as well.
29+ * This RouterFunction will make sure that we serve `frontend/index.html` whenever the path does not start with `/api/`, is not `/error` and does
30+ * not have a path extension (to exclude static resources).
31+ *
32+ * @see <a href="https://github.com/spring-projects/spring-framework/issues/27257">Spring framework issue 27257</a> for more details.
33+ */
34+ @ Bean
35+ RouterFunction <ServerResponse > spaRouter () {
36+ ClassPathResource index = new ClassPathResource ("frontend/index.html" );
37+ RequestPredicate spaPredicate = path ("/api/**" ).or (path ("/error" )).or (pathExtension (extension -> !extension .isBlank ())).negate ();
38+ return route ().resource (spaPredicate , index ).build ();
39+ }
1940}
0 commit comments