0

I fail to configure Spring correctly with static resources. I read many posts everywhere, found various but incomplete responses.

Context:

  • Angular module (build with maven-frontend-plugin)
  • Fronted embedded in the Spring fatjar
  • Backend only handles requests starting by /api
  • Backend also handles static resources from an external directory
  • Backend do not have to know frontend paths
  • Backend can use PathMatcher or AntMatcher (who cares ?!)
  • Frontend uses real routes (not #)
  • Frontend handles exactly /, /foo, /bar, for this example
  • Java 17 & Angular 14

What we expect:

  • For /api/**: let Spring handles the request without searching static resources and if the API does not exist, we expect a 404 in a JSON format. All answers fail to satisfy this rule.
  • For static resource from directory: read them if possible
  • For all others URLs (we suppose the backend only handles /api) we use frontend static resources, and the frontend decided to display a 404 page when not found (or just redirect on /, whatever)

Solution 1: only update application.yml

spring:
  web:
    resources:
      static-locations: classpath:/static/,file:/tmp

This is the simplest solution and we have:

  • http://localhost:8080/: OK, serves frontend
  • http://localhost:8080/static.png : OK, serves static file from directory
  • http://localhost:8080/foo: KO, blank page (should serve frontend)
  • http://localhost:8080/api/not-exist: KO, blank page (should be json 404)

To handle 404 on backend, we could catch Tomcat errors with a custom ErrorController (controllerAdvice + RestController) with @RequestMapping("${server.error.path:${error.path:/error}}") but as soon as we are using this, we lost static resources from directory (static.png above).

Solution 2: solution 1 + overload WebMvcConfigurer

@Override
public void addViewControllers(ViewControllerRegistry registry) {
    registry
            .addViewController("/**/{path:[\\w]+}")
            .setViewName("forward:/");
}

and

spring:
  mvc:
    throw-exception-if-no-handler-found: true
    pathmatch:
      matching-strategy: ANT_PATH_MATCHER

Better:

  • http://localhost:8080/: OK, serves frontend
  • http://localhost:8080/static.png : OK, serves static file from directory
  • http://localhost:8080/foo: OK, serves frontend
  • http://localhost:8080/api/not-exist: KO, redirects on frontend

Also, I still don't understand how it works, and the Spring order resolution. I understood Controller got the priority, ok, then what ? And if we add the ErrorController it do not catch any 404 anymore. And throw-exception-if-no-handler-found seems to have not effect either.

Maybe we should add a context for external static resources. We could have:

  • /api/...: use controllers or throw 404 as JSON
  • /external/...: use external resources or 404 blank (or JSON)
  • other: it serves frontend and this one manages 404
user2668735
  • 1,048
  • 2
  • 18
  • 30

0 Answers0