-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
APIGW: add Binary Media support for response in AWS_PROXY
#12199
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
AWS_PROXY
LocalStack Community integration with Pro 2 files ± 0 2 suites ±0 27m 49s ⏱️ - 1h 26m 12s Results for commit 294e374. ± Comparison against base commit 952eb3e. This pull request removes 3020 and adds 1 tests. Note that renamed tests count towards both.
♻️ This comment has been updated with latest results. |
349b657
to
294e374
Compare
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 investigation with a really clean fix!
The amount of work behind those test is impressive. I left a question, but feel free to ignore as it seems to be getting around the caching issue. I think maybe on first deployment we could do without the extra wait, but it also makes for improved consistency and easy to see what is being tested!
Great work 🚀
# we poll that the API is returning the right data after deployment | ||
poll_condition( | ||
lambda: _assert_invoke(accept="image/png", expect_binary=False), timeout=timeout, interval=1 | ||
) | ||
if is_aws_cloud(): | ||
time.sleep(5) | ||
|
||
# we did not configure binaryMedias so the API is not returning binary data even if all conditions are met | ||
assert _assert_invoke(accept="image/png", expect_binary=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.
question: Any reason for not doing assert poll_condition(...)
. And since to move forward we already needed _assert_invoke()
to be truthy, isn't the time.sleep(5)
redundant?
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, I agree. I had super weird issues with AWS returning "all is good" and then failing and returning 403 or 500 again, so I had the sleep to have it more consistent. I also used poll_condition
because debugging with retry
is a true nightmare, as pytest only catches the first exception raised which has nothing to do with the actual failure...
I could try re-running the test against AWS to see if it's really needed.
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'll merge to rebase #12215, but we should probably find a way to properly validate deployments are.. well, deployed 😄
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 remember facing that issue before, where there is a transition period where the request can be handled either by the new or the old deployment.
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, which is why I also created multiple stages now 😅 I did everything on one stage before, and the stability of the test was horrible 😭
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 think that even on multiple stage, you can hit that issue, right? I ended up created a parametrize test back then to have a completely new api each time. your solution does make it a bit nicer to read, at the cost of extra wait time in aws.
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.
Makes sense to create the new API to be honest... would need to have class scoped lambda, would be a bit easier. Wait before the next PR, where with the same API I test 12 combinations with 3 inputs... 😭 what a pain
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 will give it a minute and catch up on a few other things first! 😉
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.
Welcome back 😆 no worries, take your time, there's no hurry for this one 😄
# we poll that the API is returning the right data after deployment | ||
poll_condition( | ||
lambda: _assert_invoke(accept="image/png", expect_binary=True), timeout=timeout, interval=1 | ||
) | ||
if is_aws_cloud(): | ||
time.sleep(10) | ||
|
||
# all conditions are met | ||
assert _assert_invoke(accept="image/png", expect_binary=True) |
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.
Same here, though this one feels like it could work around caching issues with the multiple deployment 🤔
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.
Yeah, same issue, weird caching or AWS returning "ok" then failing again... no idea why 😭
# Accept has to exactly match what is configured | ||
assert _assert_invoke(accept="*/*", expect_binary=False) | ||
|
||
# client is sending a multiple accept, but AWS only checks the first one | ||
assert _assert_invoke(accept="image/webp,image/png,*/*;q=0.8", expect_binary=False) | ||
|
||
# client is sending a multiple accept, but AWS only checks the first one, which is right | ||
assert _assert_invoke(accept="image/png,image/*,*/*;q=0.8", expect_binary=True) |
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 does simplify the implementation! 🙏
Motivation
As reported in #12115, we did not support returning binary responses from
AWS_PROXY
integration. In the previous implementation of API Gateway, we were returning binary responses but in the wrong way: if theisBase64Encoded
was set toTrue
in the response, we decode it and send binary data.However, it has a deep link to the
binaryMediaTypes
configuration of the REST API. Only if the client sends anAccept
header that matches thebinaryMediaTypes
then theAWS_PROXY
will respond with binary data.This PR was quite frustrating, as it took me hours to implement the test and all the different cases, and I hit some caching issues, things failing in one run and not another, I had to deploy to different stages to be sure I wasn't hitting some weird issues.
And the implementation itself took less than 15min 🤦♂️ At least we have confidence in the different cases, and that the
Content-Type
header is actually not taken into account.The implementation for now only covers
AWS_PROXY
, because the logic for other integrations is more complex, as there also is logic to decode the incoming payload, and theContentHandling
parameter, both for input and output. This will be tackled in a follow up.I can set the
Accept
header andbinaryMediaTypes
in the request context then, if needed.More resources from AWS:
Changes
AWS_PROXY
integration to return or not binary datafixes #12115