Reputation: 23413
On Spring MVC rest service I am having issues trying to match anything that is beyond my configured RequestMapping value.
So for e.g. I have this:
@RequestMapping(value = "{configKey}/{arguments:.*}", method = RequestMethod.GET)
Which says that match anything that is beyond the second path variable. The problem is that this e.g. works ok with:
get("/test/document")
while this ends up with 404:
get("/test/document/download")
It is weird that Spring can't handle this regex. I actually tried a lot of solutions, but none of them worked.
Previously I had this configuration on JAX-RS:
@Path("/{configKey}/{arguments:.*}")
And everything was good, but now I am migrating and having this issue.
Does anyone know what's going on and how to fix this?
EDIT:
Adding {configKey}/**
- doesn't work
Adding {configKey}/{arguments}/**
works, but for e.g. if I call:
get("/test/document/download")
I get only test
as my config key and document
as arguments. In the arguments I expect to get all what's beyond the {configKey}
. Which can be anything for e.g. it should work in any case:
get("/test/document")
get("/test/document/download")
get("/test/document/download/1")
get("/test/document/download/1/2")
get("/test/whatever/xxx/1/2/etc")
Which was working with config for JAX-RS: @Path("/{configKey}/{arguments:.*}")
Upvotes: 6
Views: 12809
Reputation: 441
For anyone that lands here looking for an answer, but realizes that the current answers are from 2015, this has been improved with newer versions of Spring because of the PathPattern
.
https://spring.io/blog/2020/06/30/url-matching-with-pathpattern-in-spring-mvc
PathPattern is compatible with AntPathMatcher syntax except for the following:
Support for additional syntax to match and capture 0 or more path segments at the end, e.g. "/foo/{*spring}". This is useful as a catch-all pattern in REST APIs with access to the captured path segments through a @PathVariable.
Support for "**" for multi-segment matching is only allowed at the end of a pattern. This helps to eliminate most causes of ambiguity when choosing the closest match for a given request.
In particular, a @GetMapping(path = "/foo/{*spring}")
did the trick for me (a @RequestMapping
would work too), which injects a @PathVariable String spring
to your method. So if I called the API with GET /foo/1/2/3
, the String spring
would equal /1/2/3
(yes, with the leading slash)
Upvotes: 0
Reputation: 23413
I found a workaround to it, it's not the permanent solution, I think it's a bug in Spring and I raised a Jira, but until it's fixed here it is:
I had to define my request mapping like this:
@RequestMapping(value = "{configKey}/**", method = RequestMethod.GET)
So basically match all what's after first variable in a path.
Then:
String arguments = pathMatcher.extractPathWithinPattern(
request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString(),
request.getPathInfo());
Where a pathMatcher is an instance of AntPathMatcher used by Spring.
So now calling HTTP GET on for e.g. this path:
get("/test/leaderboard/user/mq/frankie1")
I have:
configKey = test
arguments = leaderboard/user/mq/frankie1
Upvotes: 0
Reputation: 5936
Spring Use AntPathMatcher, The mapping matches URLs using the following rules:
1. ? matches one character
2. * matches zero or more characters
3. ** matches zero or more 'directories' in a path
This is how I configure request mapping url, I've test in my computer, and it works and You can custom based on your needs.
@RequestMapping(value = "/new-ajax/**", method = RequestMethod.GET)
Test case
/new-ajax/document/1
/new-ajax/document/download/1
/new-ajax/document/download/1/2
/new-ajax/test/whatever/xxx/1/2/etc
Upvotes: -1
Reputation: 28569
The following mapping should work for you
@RequestMapping(value = "{configKey}/**", method = RequestMethod.GET)
This mapping is known as default mapping pattern.
Upvotes: 2