Spring path with variable number of segments

Viewed 191

I have a spring application that stores objects and attributes, and provides paths to access them, in the form /application-root/{object}/{attribute}.

A new change is to allow objects to contain child objects within attributes. A user should be able to access data with a path like this:

/application-root/{object1}/{attribute1}/{object2}/{attribute2}/{object3}/{attribute3}...

There is no hard limit on how deep an object can be nested, so I need to be able to handle a path with a variable number of segments and extract the information from the objects and attributes from it.

I've looked at the regular expressions in PathPattern class, but it looks like it that regex will only match a single segment.

What's the best way to handle a variable number of path segments in Spring?

2 Answers

Options: @see PathPattern

An example:

@RestController
class DemoController {
    
    // Spring Boot 2.3 or lower
    @GetMapping("/search/**")
    public String search(HttpServletRequest request) {
        return request.getRequestURI();
    }
    
    // Spring Boot 2.4 or higher
    @GetMapping("/find/{*mapping}")
    public String find(@PathVariable("mapping") String mapping ) {
        return mapping;
    }
}

curl "http://localhost:8080/search/1/2/3/4" will output /search/1/2/3/4

curl "http://localhost:8080/find/1/2/3/4" will output /1/2/3/4

From here on you could parse/map the String to your objects/attributes

If using a PathPattern like Dirk mentioned is not an option due to version differences, you might be able to use a ServletUriComponentsBuilder to retrieve the path segments in a list:

@RestController
public class SomeController {

    @GetMapping("/application-root/**")
    public void someEndpoint(HttpServletRequest request) {

        List<String> pathSegments = ServletUriComponentsBuilder.fromRequest(request).build().getPathSegments();

        // Remove "/application-root" by sublisting it as the returned list is immutable
        pathSegments.subList(1, pathSegments.size())
    }
}
Related