Skip to content

APIGW NG: introduce new unified path style #11350

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 4 commits into from
Sep 26, 2024
Merged

Conversation

bentsku
Copy link
Contributor

@bentsku bentsku commented Aug 14, 2024

Motivation

In LocalStack API Gateway, we currently have a specific path-style format to call execute-api: http(s)://<your-domain>:<port>/restapis/<api_id>/<stage>/_user_request_/<your-path>.
The actual AWS format is this, with the host: http(s)://<api-id>.execute-api.<domain>/<stage>/<your-path>

There are multiple problems with our current "path style" format:

  • it has restapis in the name but is shared with HTTP and WebSockets API in APIGW v2
  • for HTTP APIs, can be optional. That format does not work with that case
  • there is the custom user_request between and , which looks weird and necessitate to re-organize the parts for the user

This PR introduces a new path format for API Gateway, available with the "Next Gen" provider:
http(s)://<your-domain>:<port>/_aws/execute-api/<api-id>/<stage>/<your-path>

This new format follows the same order as AWS, is clearer about the LocalStack-only part, is on the _aws namespace, and has execute-api in the name, which maps to the URL people are used to see.

It also sets up a deprecation path for the previous "path style" and log a message when people uses it with the new provider. We will also need to update the documentation accordingly.

Deprecation message:

2024-08-14T03:10:10.517 WARNING --- [PoolThread-twisted.internet.reactor-0] localstack.deprecations    : /restapis/<api_id>/<stage>/_user_request_ is deprecated (since 3.7.0) and will be removed in upcoming releases of LocalStack! Use /_aws/execute-api/<api_id>/<stage> instead.

Changes

  • register new routes for the APIGW NG router
  • update the CORS handler to recognize this new router
  • add deprecation on the _user_request_ endpoint when using the NG provder
  • update the tests to use this new endpoint too

@bentsku bentsku added aws:apigateway Amazon API Gateway semver: patch Non-breaking changes which can be included in patch releases labels Aug 14, 2024
@bentsku bentsku self-assigned this Aug 14, 2024
@bentsku bentsku changed the title APIGW NG: introduce new path style APIGW NG: introduce new unified path style Aug 14, 2024
Copy link

github-actions bot commented Aug 14, 2024

LocalStack Community integration with Pro

    2 files  ±0      2 suites  ±0   1h 37m 25s ⏱️ + 1m 7s
3 448 tests +5  3 045 ✅ ±0  403 💤 +5  0 ❌ ±0 
3 450 runs  +5  3 045 ✅ ±0  405 💤 +5  0 ❌ ±0 

Results for commit e03967a. ± Comparison against base commit 650483e.

♻️ This comment has been updated with latest results.

@bentsku bentsku added this to the Playground milestone Aug 14, 2024
@bentsku bentsku marked this pull request as ready for review August 16, 2024 16:17
@bentsku bentsku marked this pull request as draft August 16, 2024 17:20
@bentsku bentsku marked this pull request as ready for review August 16, 2024 17:45
Comment on lines 151 to 173
self.router.add(
path="/restapis/<api_id>/<stage>/_user_request_/<greedy_path:path>",
endpoint=deprecated_route_endpoint,
strict_slashes=True,
),
# add the localstack-specific so-called "path-style" routes when DNS resolving is not possible
self.router.add(
path=f"{self.EXECUTE_API_INTERNAL_PATH}/<api_id>/",
endpoint=self.handler,
defaults={"path": "", "stage": None},
strict_slashes=True,
),
self.router.add(
path=f"{self.EXECUTE_API_INTERNAL_PATH}/<api_id>/<stage>/",
endpoint=self.handler,
defaults={"path": ""},
strict_slashes=False,
),
self.router.add(
path=f"{self.EXECUTE_API_INTERNAL_PATH}/<api_id>/<stage>/<greedy_path:path>",
endpoint=self.handler,
strict_slashes=True,
),
Copy link
Contributor

Choose a reason for hiding this comment

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

A better strategy might be to match only <api_id> and <api_id>/<greedy_path:path> and have to do a bit more work when routing the request. It is added work on the rest api but would help us support HTTP api with less mess

Copy link
Contributor Author

@bentsku bentsku Aug 16, 2024

Choose a reason for hiding this comment

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

We had a lengthy discussion about this, and the TLDR; is this:

We're using the router to do as much parsing as it can, and if we were to remove the stage from the path, we would still need to manually parse it from every request by checking the first "resource" of the path and assigning it to the stage name.

For HTTP API, you can define a $default stage, so if you do not specify a stage name, it will fallback to the default. That leads to the registered routes being somewhat misleading, because if you target an HTTP API with a $default stage configured with the following path: test/test-path, then in our edge router endpoint, test will be assigned to the stage value.
The next check is to verify if that test is in the existing stages, and if not, assign the stage value to $default.

We don't use the <greedy_path:path> value in the rest of the invocation, as it is URL-decoded, and we need the raw value. In the rest of the logic, we first use RAW_URI which contains the entire path of the request, and we do manipulation to remove the stage name if the request is prefixed with it. The stage parameter here is only to help us get that first "resource" of the path, it being rightly the stage name or not is not really important, we do not know yet if the request is proper or not.

We've also decided to model the edge router rules to the REST API format, as stage is mandatory. It will be a bit of a workaround to support all kind of API with the same routes, but if properly documented, should be alright.

This Edge router endpoint can be seen as a "first pass" routing, trying to catch all API Gateway request and doing as much work as possible, and then it's up to us to properly route the request to the right API Gateway Resource/Route of the API.

I agree with the sentiment that those routes will match something a bit "misleading" in assigning a stage value to something that isn't a stage value, but we would need to manually parse the first part to check if it is a stage value or not, so letting the router do the work for us is okay, as long as the process is properly documented.

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.

Thanks @bentsku for tackling this and be always ready for good discussion and clarification!

I really appreciate the switch to internal request using _aws 🚀

@bentsku bentsku force-pushed the apigw-ng-new-path-style branch from 08c1821 to e03967a Compare September 26, 2024 09:35
@bentsku bentsku merged commit d064217 into master Sep 26, 2024
34 checks passed
@bentsku bentsku deleted the apigw-ng-new-path-style branch September 26, 2024 10:51
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.

2 participants