def _parse_v1_payload_format_lambda_output()

in samcli/local/apigw/local_apigw_service.py [0:0]


    def _parse_v1_payload_format_lambda_output(lambda_output: str, binary_types, flask_request, event_type):
        """
        Parses the output from the Lambda Container

        :param str lambda_output: Output from Lambda Invoke
        :param binary_types: list of binary types
        :param flask_request: flash request object
        :param event_type: determines the route event type
        :return: Tuple(int, dict, str, bool)
        """
        # pylint: disable-msg=too-many-statements
        try:
            json_output = json.loads(lambda_output)
        except ValueError as ex:
            raise LambdaResponseParseException("Lambda response must be valid json") from ex

        if not isinstance(json_output, dict):
            raise LambdaResponseParseException(f"Lambda returned {type(json_output)} instead of dict")

        if event_type == Route.HTTP and json_output.get("statusCode") is None:
            raise LambdaResponseParseException(f"Invalid API Gateway Response Key: statusCode is not in {json_output}")

        status_code = json_output.get("statusCode") or 200
        headers = LocalApigwService._merge_response_headers(
            json_output.get("headers") or {}, json_output.get("multiValueHeaders") or {}
        )

        body = json_output.get("body")
        if body is None:
            LOG.warning("Lambda returned empty body!")

        is_base_64_encoded = LocalApigwService.get_base_64_encoded(event_type, json_output)

        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

        invalid_keys = LocalApigwService._invalid_apig_response_keys(json_output, event_type)
        # HTTP API Gateway just skip the non allowed lambda response fields, but Rest API gateway fail on
        # the non allowed fields
        if event_type == Route.API and invalid_keys:
            raise LambdaResponseParseException(f"Invalid API Gateway Response Keys: {invalid_keys} in {json_output}")

        # 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
            # Rest API Gateway depends on the response content-type and the API configured BinaryMediaTypes to decide
            # if it will decode the response or not
            if (event_type == Route.HTTP and is_base_64_encoded) or (
                event_type == Route.API
                and LocalApigwService._should_base64_decode_body(
                    binary_types, flask_request, headers, is_base_64_encoded
                )
            ):
                body = base64.b64decode(body)
        except ValueError as ex:
            LambdaResponseParseException(str(ex))

        return status_code, headers, body