8000 APIGW: fix requestOverride not being present in responseTemplates by bentsku · Pull Request #11799 · localstack/localstack · GitHub
[go: up one dir, main page]

Skip to content

APIGW: fix requestOverride not being present in responseTemplates #11799

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 1 commit into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ def __call__(
body, request_override = self.render_request_template_mapping(
context=context, template=request_template
)
# mutate the ContextVariables with the requestOverride result, as we copy the context when rendering the
# template to avoid mutation on other fields
# the VTL responseTemplate can access the requestOverride
context.context_variables["requestOverride"] = request_override
# TODO: log every override that happens afterwards (in a loop on `request_override`)
merge_recursive(request_override, request_data_mapping, overwrite=True)

Expand Down Expand Up @@ -156,7 +160,6 @@ def __call__(
body=body,
)

# LOG.debug("Created integration request from xxx")
context.integr 10000 ation_request = integration_request

def get_integration_request_data(
Expand Down
108 changes: 107 additions & 1 deletion tests/aws/services/apigateway/test_apigateway_integrations.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import base64
import contextlib
import copy
import json
Expand All @@ -21,7 +22,7 @@
from localstack.testing.pytest.fixtures import PUBLIC_HTTP_ECHO_SERVER_URL
from localstack.utils.aws import arns
from localstack.utils.json import json_safe
from localstack.utils.strings import short_uid, to_bytes
from localstack.utils.strings import short_uid, to_bytes, to_str
from localstack.utils.sync import retry
from tests.aws.services.apigateway.apigateway_fixtures import (
api_invoke_url,
Expand Down Expand Up @@ -614,6 +615,111 @@ def invoke_api(url) -> requests.Response:
assert response_data.status_code == 200


@markers.aws.validated
@pytest.mark.skipif(
condition=not is_next_gen_api() and not is_aws_cloud(),
reason="Behavior is properly implemented in Legacy, it returns the MOCK response",
)
def test_integration_mock_with_request_overrides_in_response_template(
create_rest_apigw, aws_client, snapshot
):
api_id, _, root = create_rest_apigw(
name=f"test-api-{short_uid()}",
description="this is my api",
)

rest_resource = aws_client.apigateway.create_resource(
restApiId=api_id,
parentId=root,
pathPart="{testPath}",
)
resource_id = rest_resource["id"]

aws_client.apigateway.put_method(
restApiId=api_id,
resourceId=resource_id,
httpMethod="GET",
authorizationType="NONE",
requestParameters={
"method.request.path.testPath": True,
},
)

aws_client.apigateway.put_method_response(
restApiId=api_id, resourceId=resource_id, httpMethod="GET", statusCode="200"
)

# this should only work for MOCK integration, as they don't use the .path at all. This seems to be a derivative
# way to pass data from the integration request to integration response with MOCK integration
request_template = textwrap.dedent("""#set($body = $util.base64Decode($input.params('testPath')))
#set($context.requestOverride.path.body = $body)
{
"statusCode": 200
}
""")

aws_client.apigateway.put_integration(
restApiId=api_id,
resourceId=resource_id,
httpMethod="GET",
integrationHttpMethod="POST",
type="MOCK",
requestParameters={},
requestTemplates={"application/json": request_template},
)
response_template = textwrap.dedent("""
#set($body = $util.parseJson($context.requestOverride.path.body))
#set($inputBody = $body.message)
#if($inputBody == "path1")
{
"response": "path was path one"
}
#elseif($inputBody == "path2")
{
"response": "path was path two"
}
#else
{
"response": "this is the else clause"
}
#end
""")

aws_client.apigateway.put_integration_response(
restApiId=api_id,
resourceId=resource_id,
httpMethod="GET",
statusCode="200",
selectionPattern="2\\d{2}",
responseTemplates={"application/json": response_template},
)
stage_name = "dev"
aws_client.apigateway.create_deployment(restApiId=api_id, stageName=stage_name)

path_data = to_str(base64.b64encode(to_bytes(json.dumps({"message": "path1"}))))
invocation_url = api_invoke_url(api_id=api_id, stage=stage_name, path="/" + path_data)

def invoke_api(url) -> requests.Response:
_response = requests.get(url, verify=False)
assert _response.ok
return _response

response_data = retry(invoke_api, sleep=2, retries=10, url=invocation_url)
snapshot.match("invoke-path1", response_data.json())

path_data_2 = to_str(base64.b64encode(to_bytes(json.dumps({"message": "path2"}))))
invocation_url_2 = api_invoke_url(api_id=api_id, stage=stage_name, path="/" + path_data_2)

response_data_2 = invoke_api(url=invocation_url_2)
snapshot.match("invoke-path2", response_data_2.json())

path_data_3 = to_str(base64.b64encode(to_bytes(json.dumps({"message": "whatever"}))))
invocation_url_3 = api_invoke_url(api_id=api_id, stage=stage_name, path="/" + path_data_3)

response_data_3 = invoke_api(url=invocation_url_3)
snapshot.match("invoke-path-else", response_data_3.json())


@pytest.fixture
def default_vpc(aws_client):
vpcs = aws_client.ec2.describe_vpcs()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1042,5 +1042,19 @@
}
}
}
},
"tests/aws/services/apigateway/test_apigateway_integrations.py::test_integration_mock_with_request_overrides_in_response_template": {
"recorded-date": "06-11-2024, 23:09:04",
"recorded-content": {
"invoke-path1": {
"response": "path was path one"
},
"invoke-path2": {
"response": "path was path two"
},
"invoke-path-else": {
"response": "this is the else clause"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"tests/aws/services/apigateway/test_apigateway_integrations.py::test_integration_mock_with_path_param": {
"last_validated_date": "2024-11-05T12:55:51+00:00"
},
"tests/aws/services/apigateway/test_apigateway_integrations.py::test_integration_mock_with_request_overrides_in_response_template": {
"last_validated_date": "2024-11-06T23:09:04+00:00"
},
"tests/aws/services/apigateway/test_apigateway_integrations.py::test_put_integration_response_with_response_template": {
"last_validated_date": "2024-05-30T16:15:58+00:00"
},
Expand Down
Loading
0