def _parse_v2_payload_format_lambda_output()

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