in samcli/local/apigw/local_apigw_service.py [0:0]
def _parse_v2_payload_format_lambda_output(lambda_output: str, binary_types, flask_request):
"""
Parses the output from the Lambda Container. V2 Payload Format means that the event_type is only HTTP
:param str lambda_output: Output from Lambda Invoke
:param binary_types: list of binary types
:param flask_request: flash request object
:return: Tuple(int, dict, str, bool)
"""
# pylint: disable-msg=too-many-statements
# pylint: disable=too-many-branches
try:
json_output = json.loads(lambda_output)
except ValueError as ex:
raise LambdaResponseParseException("Lambda response must be valid json") from ex
# lambda can return any valid json response in payload format version 2.0.
# response can be a simple type like string, or integer
# https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.response
if isinstance(json_output, dict):
body = json_output.get("body") if "statusCode" in json_output else json.dumps(json_output)
else:
body = json_output
json_output = {}
if body is None:
LOG.warning("Lambda returned empty body!")
status_code = json_output.get("statusCode") or 200
headers = Headers(json_output.get("headers") or {})
# cookies is a new field in payload format version 2.0 (a list)
# https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html
# we need to move cookies to Set-Cookie headers.
# each cookie becomes a set-cookie header
# MDN link: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
cookies = json_output.get("cookies")
# cookies needs to be a list, otherwise the format is wrong and we can skip it
if isinstance(cookies, list):
for cookie in cookies:
headers.add("Set-Cookie", cookie)
is_base_64_encoded = json_output.get("isBase64Encoded") or False
try:
status_code = int(status_code)
if status_code <= 0:
raise ValueError
except ValueError as ex:
raise LambdaResponseParseException("statusCode must be a positive int") from ex
try:
if body:
body = str(body)
except ValueError as ex:
raise LambdaResponseParseException(
f"Non null response bodies should be able to convert to string: {body}"
) from ex
# If the customer doesn't define Content-Type default to application/json
if "Content-Type" not in headers:
LOG.info("No Content-Type given. Defaulting to 'application/json'.")
headers["Content-Type"] = "application/json"
try:
# HTTP API Gateway always decode the lambda response only if isBase64Encoded field in response is True
# regardless the response content-type
if is_base_64_encoded:
# Note(xinhol): here in this method we change the type of the variable body multiple times
# and confused mypy, we might want to avoid this and use multiple variables here.
body = base64.b64decode(body) # type: ignore
except ValueError as ex:
LambdaResponseParseException(str(ex))
return status_code, headers, body