Skip to content

Conversation

Postremus
Copy link
Member

@Postremus Postremus commented Apr 15, 2025

Having partially matching paths on resource classes could lead to 404s, even though a matching resource method existed.

Lets take the example from #26496.

@Path("/base")
class Base {
   @GET
   @Path("{id}") 
   public Uni<RestResponse<?>> base() {..}
}
@Path("/base/{id}")
class Extension {
   @GET
   @Path("extension") 
   public Uni<RestResponse<?>> extension() {..}
}

Calling GET /base/123 would result in a 404. /base/{id} is a perfect match for that request, which result in the Extension resource class being used.
Quarkus-rest always only works on the basis of one resource class - the one with the best match.

I however believe that is not up to spec.

https://jakarta.ee/specifications/restful-ws/4.0/jakarta-restful-ws-spec-4.0.pdf

Chapter 3.5.2 Request Matching
Stage 1 only handles matching of the resource class path to the request uri -> both classes match.
Stage 2 figures out which of all resource methods in all matched resource classes matches against the request uri.

So basically, the current implementation results in Stage 1 only reporting one matching resource class, altough it should report 2.

This PR adds additional logic, so that all matching resource classes are remembered, and the handler chain is restarted if the current resource class does not contain a matchin sub resource method, or sub resource locator.

@Postremus Postremus requested a review from geoand April 15, 2025 18:31

This comment has been minimized.

Copy link
Contributor

@geoand geoand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very clever, well done!

@FroMage do you also want to take a look at this?

@geoand
Copy link
Contributor

geoand commented Apr 16, 2025

cc @franz1981 as this one could potentially have a slight performance impact

@geoand geoand added the triage/waiting-for-ci Ready to merge when CI successfully finishes label Apr 16, 2025
@franz1981
Copy link
Contributor

I have added few comments

This comment has been minimized.

@geoand geoand removed the triage/waiting-for-ci Ready to merge when CI successfully finishes label Apr 17, 2025
@franz1981
Copy link
Contributor

Please @geoand wait to merge this till the comments are addressed or at least a round of profiling is performed 🙏

@geoand
Copy link
Contributor

geoand commented Apr 17, 2025

That's why I removed the waiting-for-ci label :)

This comment has been minimized.

@geoand
Copy link
Contributor

geoand commented Apr 18, 2025

@franz1981 PTAL

@franz1981
Copy link
Contributor

I would suggest to just return the match without allocating any list, but just the top match 🙏
Sorry for not commenting but I'm on PTO till next week (Fri) so I can comment with phone :P

This comment has been minimized.

@Postremus
Copy link
Member Author

Sorry for not commenting but I'm on PTO till next week (Fri) so I can comment with phone :P

@franz1981 no worries, I don't mind the back and forth as long as its not too nitpicky :)

@Postremus
Copy link
Member Author

I would suggest to just return the match without allocating any list, but just the top match

I now return an Iterator, which allows to try the next match.

This comment has been minimized.

@geoand geoand requested a review from franz1981 April 21, 2025 09:17
Copy link
Member

@gsmet gsmet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a quick look at the patch and I have a small question: is the very common case where there is only one match fully optimized?

I think we should try to reduce allocations and logic to the minimum in this case.

Maybe it already is but it wasn't obvious so sorry if it's the case.

@Postremus Postremus marked this pull request as draft April 24, 2025 13:33
@Postremus
Copy link
Member Author

drafting this PR, I might be able to simplify more in the common case (where only one path matches).

@gsmet
Copy link
Member

gsmet commented Apr 24, 2025

BTW, I'm not expecting things to go overcomplicated for very minor gains. I.e. maybe keeping the iterator makes sense but making sure that we don't allocate additional things given there's only one item.

I will let you judge of finding the best compromise between readability and performance impact.

@Postremus Postremus marked this pull request as ready for review April 28, 2025 18:59
@Postremus
Copy link
Member Author

Postremus commented Apr 28, 2025

@gsmet @franz1981
Next attempt. This time no additional allocations in the common path; simpler diff.

This comment has been minimized.

This comment has been minimized.

@FroMage
Copy link
Member

FroMage commented May 5, 2025

Very clever, well done!

@FroMage do you also want to take a look at this?

I looked. I don't understand it anymore than the original implementation.

But the test is valid, the improvement is there, and if it doesn't break anything, it's progress, so +1 from me 🤷

@geoand
Copy link
Contributor

geoand commented May 5, 2025

@franz1981 any final comments?

@franz1981
Copy link
Contributor

Will take a look tomorrow morning 🙏

@geoand
Copy link
Contributor

geoand commented May 5, 2025

👌

@Postremus
Copy link
Member Author

@franz1981 Sorry for the ping, but it has been a few days since the last update. And I kind of want to get this off my plate :)

@geoand
Copy link
Contributor

geoand commented May 13, 2025

@franz1981 is on PTO, so if he doesn't respond this week (which I fully expect him not to), I will just go ahead and merge this

This comment has been minimized.

@geoand
Copy link
Contributor

geoand commented May 13, 2025

FYI: I rebased the PR onto main

Copy link

quarkus-bot bot commented May 13, 2025

Status for workflow Quarkus CI

This is the status report for running Quarkus CI on commit 6b67e05.

✅ The latest workflow run for the pull request has completed successfully.

It should be safe to merge provided you have a look at the other checks in the summary.

You can consult the Develocity build scans.

@geoand geoand dismissed franz1981’s stale review May 15, 2025 09:18

Comments addressed

@geoand geoand merged commit d17c7e8 into quarkusio:main May 15, 2025
52 checks passed
@quarkus-bot quarkus-bot bot added this to the 3.24 - main milestone May 15, 2025
@Postremus Postremus deleted the issues/26496 branch May 22, 2025 07:14
TomasHofman added a commit to TomasHofman/quarkus that referenced this pull request Oct 7, 2025
This solves further problems in case when the paths are spread over
multiple resource classes. Improves earlier PR:

quarkusio#47386
TomasHofman added a commit to TomasHofman/quarkus that referenced this pull request Oct 7, 2025
This solves further problems in case when the paths are spread over
multiple resource classes. Improves earlier PR:

quarkusio#47386
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Matching a base path of another controller, results in 405 Method Not Allowed

5 participants