2

I'm trying to build an SPA backend (static content server, api) with some additional features/controls that require a flexible URL rewrite/routing/handling. These requirements are proving difficult to achieve together, despite trying the approach in some similar answers I've read through on here.

What I need to do:

  1. Serve static assets (js,images,css,html,etc) from URL path: /assets/
  2. Store these static assets in a filesystem directory and map to the above path
  3. For any static asset request not found return a 404
  4. Expose REST APIs from a set of named URL paths: /api/ and /anotherapi/ etc...
  5. For all other requests outside of these URL paths, serve /index.htm to bootstrap the SPA

So far, I have the following...

For the REST APIs:

@RestController @RequestMapping(value="/api/**") public class StateAPIController { @RequestMapping(value = {"/api/method1"}, method = RequestMethod.POST) @ResponseBody public String method1() { return "method1..."; } @RequestMapping(value = {"/api/method2"}, method = RequestMethod.POST) @ResponseBody public String method2() { return "method2..."; } } 

(This works fine)

For rendering static files from a specific filesystem location and mapping "/" to "/index.htm":

@Configuration @EnableWebMvc public class AssetServerConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry .addResourceHandler("/") .addResourceLocations("file:/some/path/index.htm"); registry .addResourceHandler("/assets/**") .addResourceLocations("file:/some/path/assets/"); } @Bean public ViewResolver viewResolver() { UrlBasedViewResolver viewResolver = new UrlBasedViewResolver(); viewResolver.setViewClass(InternalResourceView.class); return viewResolver; } } 

(This works, but not sure if the best way to solve this)

To redirect/forward any other requests (outside of those reserved paths) to "/" (and therefore "/index.htm"):

@ControllerAdvice @RequestMapping(value="/**") public class AssetServerController { @RequestMapping(value = {"/**/{path:[^\\.]*}", "/{path:^(?!/assets/).*}", "/{path:^(?!/api/).*}"}, method = RequestMethod.GET) public String index() { return "forward:/"; } } 

(This only partially works... and the main issue I need help with)

So, here, I need to exclude a list of paths (/assets/ & /api/), but this is proving difficult to get right with the regex/AntPathMatcher filter in the RequestMapping, and has both false matches (showing index.htm when it shouldn't) and misses (showing 404s when it should show index.htm).

Due to the above, I also cannot correctly serve 404s when a resource is missing under one of the reserved paths (e.g. assets).

a) what is the best way to approach this? Have I got this completely wrong? Is there a better way?

b) how do I make the regex work, as it doesn't seem to follow normal regex rules, and examples I've seen so far don't achieve my goal...

1 Answer 1

1

Answered here: Spring RequestMapping Regex to exclude string

Based on answer here: Spring @RequestMapping "Not Contains" Regex

Pattern that worked for excluding /assets/: value = {"/{path:(?!.*assets).+}/**"}

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.