Search code examples
regexspring-bootrequest-mapping

Spring request mapping regex with deeper paths


How do I use regex to match the following examples in a Spring @RequestMapping:

  1. localhost:8080
  2. localhost:8080/settings
  3. localhost:8080/settings/users
  4. localhost:8080/settings/users/roles
  5. localhost:8080/settings/users/roles/admin

While not allowing these ones:

  1. localhost:8080/style.css
  2. localhost:8080/manifest.json
  3. localhost:8080/api
  4. localhost:8080/api/users
  5. localhost:8080/api/users/abc

I have this regex /{path:[^\\.]*} that seems to only concentrate on not matching URLs with a dot ".". Also, 3., 4., and 5. do not work.

I can change the regex to /{path:[^\\.]*}/* and then 3. does work, but 2. will not work anymore.

What regex must be used to match the above URI (without localhost:8080) of the URLs?

I use it for this FrontendController.java:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class FrontendController {
    private static final Logger logger = LoggerFactory.getLogger(FrontendController.class);

    @RequestMapping(value = "/{path:[^\\.]*}/*")
    public String redirect() {
        logger.info("Redirect call to the frontend");
        return "forward:/";
    }
}

Solution

  • You can accomplish this with the following pattern:

    ^localhost:8080(?!\/api)(?:\/\w+)*$

    Explanation for (?!\/api)(?:\/\w+)*:

    -(?!\/api) is negative lookahead, ensuring that this point in the pattern isn't immediately followed by /api.

    -(?: ) is a non-capturing group, so the pattern it contains can be quantified with * as a group.

    -\w+ is one or more word characters ([a-zA-Z0-9_])

    https://regex101.com/r/VMf2zE/1