-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle trailing slashes for endpoints with regex path params #43016
Handle trailing slashes for endpoints with regex path params #43016
Conversation
This comment has been minimized.
This comment has been minimized.
@jonomorris Thanks for the PR! I think the test failures above look related ^ |
gsmet yeah there are some problems, I'll look into it. |
@gsmet and @stuartwdouglas, I made a small update and the unit tests pass locally in |
This comment has been minimized.
This comment has been minimized.
cc @FroMage |
.statusCode(200) | ||
.body(equalTo("Hello! 1")); | ||
|
||
get("/hello/1/") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if you do get /hello/1////
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Intermediate slashes are encoded, for instance the path becomes /1%2F%2F%2F%2F/
, which doesn't match the regex path matcher \\d+
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, we only alow a single optional slash at the end, then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how I feel about this.
It feels special-casy.
Also, I looked for articles about tailing slashes, and I only find SEO articles that advise to only serve one variant (with, or without).
And last, I've come across this issue spring-projects/spring-framework#28552 where Sprint went the other way around and removed the default of allowing optional trailing slashes by default.
So, I'll ask for more comments from HTTP/REST colleagues who might have a relevant opinion: @cescoffier @vietj:
Do you think we should allow trailing slashes for routes defined without one?
Now, on the other hand, this issue is about fixing the particular difference of assuming a trailing slash for regex paths, so that it's coherent with normal paths, which already assume a trailing slash. And I agree both should be the same. I'm not entirely sure regex matches are right, though, I wonder if non-regex path matching might be in the wrong here and the one that needs fixing. WDYT @geoand ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/foo and /foo/ are not equivalent. They refer to different resources due to the trailing slash:
- /foo refers to a resource.
- /foo/ often suggests that it’s a collection or directory-like structure containing resources.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So @cescoffier you're saying we should change the current behaviour of Quarkus REST to not treat these as the same when routing?
I suppose making the change and running the TCK will tell us what JAX-RS thinks about that :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the problem - many servers consider them equivalent, but the "theory" says they are not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a similar conversation here #26016 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, OK, so the TCK did not test this, and the spec says we have to treat them equivalent. Probably people rely on that now, so let's just harmonize and make sure regexes also behave in a similar way, and if we want to change the default later, we'll wait for users reporting an issue and revisit if required, for both regular and regex.
@@ -76,12 +76,18 @@ private RequestMatch<T> mapFromPathMatcher(String path, PathMatcher.PathMatch<Ar | |||
for (int i = 1; i < potentialMatch.template.components.length; ++i) { | |||
URITemplate.TemplateComponent segment = potentialMatch.template.components[i]; | |||
if (segment.type == URITemplate.Type.CUSTOM_REGEX) { | |||
Matcher matcher = segment.pattern.matcher(path); | |||
// exclude any path end slash when matching a subdir, but include it in the matched length | |||
boolean endSlash = matchPos < path.length() && path.charAt(path.length() - 1) == '/'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we need to consider more than one slash at the end? See my next question for how this behaves for non-regexes.
Agreed @cescoffier @geoand ? |
Will this fix match more complex regex like in #44242? Edit: Just checked the patch and it works as expected. Thanks! |
Can this be backported to 3.15 too? 🙏🏽 |
|
Forgot about this one, sorry. Can the PR be rebased on main so we can get a recent CI run? |
c53f4f0
to
6687b4b
Compare
Status for workflow
|
@FroMage mind taking a last peak to make sure nothing changed? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, let's see how this pans out
For Reactive REST endpoints don't include the path end slash when performing regex path param matches.