-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
APIGW NG add HTTP and HTTP_PROXY integration #11143
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
Conversation
localstack-core/localstack/services/apigateway/next_gen/execute_api/integrations/http.py
Show resolved
Hide resolved
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.
Fantastic work! So much to unpack in a small pr! 🚀
Great addition to the tests and super excited to see the tests starting to go green! and already some improvements on parity! 🕺
I have left a question about the way we delete the headers, but nothing blocking!
@@ -12,7 +12,7 @@ | |||
|
|||
|
|||
class InvocationRequest(TypedDict, total=False): |
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.
Awesome! That will make it so much easier to use now that we have a clear representation of what will always be there! 🚀
# remove the stage from the path, only replace the first occurrence | ||
raw_uri = raw_uri.replace(f"/{stage_name}", "", 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.
Nice ctach!
for key in list(response.headers.keys(lower=True)): | ||
if key not in ("connection", "content-type"): | ||
del response.headers[key] |
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.
question: Wouldn't we save some work to build from scratch instead?
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 too sure about the whole "reconstruct" the whole Response object from the integration response handler, it almost defeat the purpose a little bit (we could just create a dict with the integration "response", and then only serialize it in the next "request handler", instead of having the integration response handler recreating the response completely. But still the big philosophical question I don't have a proper answer for 😄
But yes, sorry, we could basically override the whole Response.headers
directly. One way would be initialize an empty Headers
object and add the few values that should be kept, but this is a bit annoying because we need to be mindful of the fact that some headers might be "multi-values" and we need to call individually getlist
on every key, and then update this with the mapping.
Something like:
response_headers = Headers()
for header in ("connection", "content-type"):
if values := response.headers.getlist(header):
for value in values:
response_headers.add(header, value)
or maybe a simplified version:
response_headers = Headers()
for header in ("connection", "content-type"):
if values := response.headers.getlist(header):
response_headers.setlist(header, values)
I don't really have a preference, it also look a bit big, and same level of indentation!
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.
@cloutierMat I think I'll merge the PR now, and we can update this in #11144 if you think any of the one above is better! I think we will need to rebase anyway. Is that ok?
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, totally. Sorry for the delay, I don't think it is a deal breaker at all. Let's have that conversation and adjust in a future PR.
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.
No worries, no delay at all here 😄 Just didn't want to block future merge with conflicts 😅 sorry for that!
# TODO: configurable timeout (29 by default) | ||
# request_parameters["timeout"] = 29 |
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.
Question: Do you know if the timeout also affects proxy integration? Is it something we should manage at the Integration handler level?
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 believe this should be the value timeoutInMillis
from the Integration
: https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html
So it should be managed at the integration level, I also had it for PROXY
I think but removed it when refactoring. I'll update 👍
Thinking of which, there's also caching which is currently not supported at all, we might want to think of that later for the features not currently implemented!
"$..headers.x-amzn-trace-id", | ||
# TODO: only missing for HTTP | ||
"$..headers.x-amzn-requestid", | ||
"$..headers.x-amzn-trace-id", |
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.
nit: seems like "$..headers.x-amzn-trace-id"
is missing for both.
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.
good catch, thanks!
@@ -220,6 +224,20 @@ def test_request_override(self, integration_request_handler, default_context): | |||
"multivalue": ["1header", "2header"], | |||
} | |||
|
|||
def test_request_override_casing(self, integration_request_handler, default_context): |
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.
Good! Another strange behavior is mostly supported out of the box! 😄
Motivation
This PR implements the
HTTP
andHTTP_PROXY
integrations. The previous work we have done make those extremely simple to implement and understand, and it shows how much the current work is going to simplify APIGW.The PR also contains a few changes across the board, because we can now test full end-to-end integration tests: the
tests/aws/services/apigateway/test_apigateway_http.py
test file is fully green with the new PR, with improved parity.Changes
HTTP
andHTTP_PROXY
integrationsOptional
and it helps with making sure we're not lacking data once we're in the integrationlegacy
handler as we can now enable full end-to-end tests_PROXY
type, but instead have a mechanism to keep somepath
value, as we would replace the/<stage>
multiple times through, and if you had a path looking/test/test
wheretest
was your stage andtest
just a regular resource, we're replace everythingAccept
andContent-Type
, behavior checked with AWS and add test for itTesting
Set
PROVIDER_OVERRIDE_APIGATEWAY=next_gen
and run all tests intests/aws/services/apigateway/test_apigateway_http.py
, they now all run! 🥳TODO
What's left to do: