Skip to content

migrating NG APIGW routing to Werkzeug routing #11057

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

Merged
merged 3 commits into from
Jun 20, 2024

Conversation

bentsku
Copy link
Contributor

@bentsku bentsku commented Jun 19, 2024

Motivation

This PR is currently target #11051.

Follow up from #11051, looking at the op_router code, I realized the format of the paths for our specs were the same as API Gateway, so much that we could reuse a simplified version of the RestServiceOperationRouter (we do not need to match on required headers and query string parameters, so that makes it much, much simpler).

All the logic to already create the rules were there, so I've re-used most of the code.
Only issue is that some of the code is private, I'm not sure how to re-architecture to make it re-usable, maybe in some routing package? \cc @alexrashed

Changes

  • migrate the previous legacy routing and path parameters extraction to the Werkzeug routing

@bentsku bentsku added aws:apigateway Amazon API Gateway semver: patch Non-breaking changes which can be included in patch releases labels Jun 19, 2024
@bentsku bentsku requested a review from alexrashed June 19, 2024 18:38
@bentsku bentsku self-assigned this Jun 19, 2024
@bentsku bentsku requested a review from cloutierMat as a code owner June 19, 2024 18:38
Copy link
Contributor

@cloutierMat cloutierMat left a comment

Choose a reason for hiding this comment

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

Wow! That simplifies things a lot! and reuses our operation router.

Definitely not great to be importing the private method though 😁

Looks like most of these are used only once. And maybe we could restructure the op_router.py to have a RestOperationRouter class from which RestServiceOperationRouter and RestAPIResourceRouter are subclassed.

We could then have the shared values and methods as part of the parent class 🤔

Comment on lines 53 to 62
try:
# trailing slashes are ignored in APIGW
path = context.invocation_request["path"].rstrip("/")

rule, args = matcher.match(path, method=request.method, return_rule=True)
except MethodNotAllowed as e:
# MethodNotAllowed (405) exception is raised if a path is matching, but the method does not.
# Our router handles this as a 404.
# TODO: raise proper Gateway exception
raise Exception("Not found") from e
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we also catch the exception raised if no path are matching in order to raise the proper Gateway Exception also?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great catch! Thanks, I'll add this right now 🙏

@bentsku
Copy link
Contributor Author

bentsku commented Jun 19, 2024

Looks like most of these are used only once. And maybe we could restructure the op_router.py to have a RestOperationRouter class from which RestServiceOperationRouter and RestAPIResourceRouter are subclassed.

We could then have the shared values and methods as part of the parent class 🤔

Really good point, that sounds reasonable!

I'd also like to get @alexrashed opinion on this, it feels a bit direct to directly import from op_router.py, it also feels like this might be a bit more general and available?

Copy link
Member

@alexrashed alexrashed left a comment

Choose a reason for hiding this comment

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

This PR really makes my day! Great to see that the custom parsing logic is finally going away, and that you could even re-use stuff we built for the op-router before! 🥳

Concerning the imports from op_router:
I think you can just move forward and refactor the op_router module. It's really great to see that the utility functions / base implementation in the operation router were useful for this, and there's actually that much overlap.
We could just create a separate module localstack.services.aws.protocol.routing with all the stuff that is not directly related to the service-operation-routing. Maybe you can even abstract it in a way such that an inheritance structure makes sense as @cloutierMat suggestion (but this isn't a necessity and shouldn't be forced if it doesn't work / feel well). 🥳

But that could also be done in a later iteration if you would prefer that, which is why I'll just approve this PR right away. 😛

Big kudos for tackling this! 🦸🏽

Copy link
Member

Choose a reason for hiding this comment

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

-148 LoC of super complex self built parsing logic replaced by +127 LoC in very nicely abstracted route matching configuration handed forward to a bullet proof library (Werkzeug) 😍

@bentsku
Copy link
Contributor Author

bentsku commented Jun 20, 2024

Awesome, thanks a lot @alexrashed! I will refactor op_router in a follow up PR in order to enable to continue working on the handler so we can merge this PR in the previous one. Thanks a lot for the suggestion, localstack.services.aws.protocol.routing sounds really good! And thanks again for the great router code, this made our lives much easier 🙏

@bentsku bentsku merged commit 82845b6 into add-apigw-ng-routing Jun 20, 2024
18 checks passed
@bentsku bentsku deleted the add-apigw-ng-asf-routing branch June 20, 2024 11:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
aws:apigateway Amazon API Gateway semver: patch Non-breaking changes which can be included in patch releases
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants