"""Common Lambda Error Responses""" import json from collections import OrderedDict from samcli.local.services.base_local_service import BaseLocalService class LambdaErrorResponses: # The content type of the Invoke request body is not JSON. UnsupportedMediaTypeException = ("UnsupportedMediaType", 415) # The AWS Lambda service encountered an internal error. ServiceException = ("Service", 500) # The resource (for example, a Lambda function or access policy statement) specified in the request does not exist. ResourceNotFoundException = ("ResourceNotFound", 404) # The request body could not be parsed as JSON. InvalidRequestContentException = ("InvalidRequestContent", 400) NotImplementedException = ("NotImplemented", 501) PathNotFoundException = ("PathNotFoundLocally", 404) MethodNotAllowedException = ("MethodNotAllowedLocally", 405) # Error Types USER_ERROR = "User" SERVICE_ERROR = "Service" LOCAL_SERVICE_ERROR = "LocalService" # Header Information CONTENT_TYPE = "application/json" CONTENT_TYPE_HEADER_KEY = "Content-Type" @staticmethod def resource_not_found(function_name): """ Creates a Lambda Service ResourceNotFound Response Parameters ---------- function_name str Name of the function that was requested to invoke Returns ------- Flask.Response A response object representing the ResourceNotFound Error """ exception_tuple = LambdaErrorResponses.ResourceNotFoundException return BaseLocalService.service_response( LambdaErrorResponses._construct_error_response_body( LambdaErrorResponses.USER_ERROR, "Function not found: arn:aws:lambda:us-west-2:012345678901:function:{}".format(function_name), ), LambdaErrorResponses._construct_headers(exception_tuple[0]), exception_tuple[1], ) @staticmethod def invalid_request_content(message): """ Creates a Lambda Service InvalidRequestContent Response Parameters ---------- message str Message to be added to the body of the response Returns ------- Flask.Response A response object representing the InvalidRequestContent Error """ exception_tuple = LambdaErrorResponses.InvalidRequestContentException return BaseLocalService.service_response( LambdaErrorResponses._construct_error_response_body(LambdaErrorResponses.USER_ERROR, message), LambdaErrorResponses._construct_headers(exception_tuple[0]), exception_tuple[1], ) @staticmethod def unsupported_media_type(content_type): """ Creates a Lambda Service UnsupportedMediaType Response Parameters ---------- content_type str Content Type of the request that was made Returns ------- Flask.Response A response object representing the UnsupportedMediaType Error """ exception_tuple = LambdaErrorResponses.UnsupportedMediaTypeException return BaseLocalService.service_response( LambdaErrorResponses._construct_error_response_body( LambdaErrorResponses.USER_ERROR, "Unsupported content type: {}".format(content_type) ), LambdaErrorResponses._construct_headers(exception_tuple[0]), exception_tuple[1], ) @staticmethod def generic_service_exception(*args): """ Creates a Lambda Service Generic ServiceException Response Parameters ---------- args list List of arguments Flask passes to the method Returns ------- Flask.Response A response object representing the GenericServiceException Error """ exception_tuple = LambdaErrorResponses.ServiceException return BaseLocalService.service_response( LambdaErrorResponses._construct_error_response_body(LambdaErrorResponses.SERVICE_ERROR, "ServiceException"), LambdaErrorResponses._construct_headers(exception_tuple[0]), exception_tuple[1], ) @staticmethod def not_implemented_locally(message): """ Creates a Lambda Service NotImplementedLocally Response Parameters ---------- message str Message to be added to the body of the response Returns ------- Flask.Response A response object representing the NotImplementedLocally Error """ exception_tuple = LambdaErrorResponses.NotImplementedException return BaseLocalService.service_response( LambdaErrorResponses._construct_error_response_body(LambdaErrorResponses.LOCAL_SERVICE_ERROR, message), LambdaErrorResponses._construct_headers(exception_tuple[0]), exception_tuple[1], ) @staticmethod def generic_path_not_found(*args): """ Creates a Lambda Service Generic PathNotFound Response Parameters ---------- args list List of arguments Flask passes to the method Returns ------- Flask.Response A response object representing the GenericPathNotFound Error """ exception_tuple = LambdaErrorResponses.PathNotFoundException return BaseLocalService.service_response( LambdaErrorResponses._construct_error_response_body( LambdaErrorResponses.LOCAL_SERVICE_ERROR, "PathNotFoundException" ), LambdaErrorResponses._construct_headers(exception_tuple[0]), exception_tuple[1], ) @staticmethod def generic_method_not_allowed(*args): """ Creates a Lambda Service Generic MethodNotAllowed Response Parameters ---------- args list List of arguments Flask passes to the method Returns ------- Flask.Response A response object representing the GenericMethodNotAllowed Error """ exception_tuple = LambdaErrorResponses.MethodNotAllowedException return BaseLocalService.service_response( LambdaErrorResponses._construct_error_response_body( LambdaErrorResponses.LOCAL_SERVICE_ERROR, "MethodNotAllowedException" ), LambdaErrorResponses._construct_headers(exception_tuple[0]), exception_tuple[1], ) @staticmethod def _construct_error_response_body(error_type, error_message): """ Constructs a string to be used in the body of the Response that conforms to the structure of the Lambda Service Responses Parameters ---------- error_type str The type of error error_message str Message of the error that occured Returns ------- str str representing the response body """ # OrderedDict is used to make testing in Py2 and Py3 consistent return json.dumps(OrderedDict([("Type", error_type), ("Message", error_message)])) @staticmethod def _construct_headers(error_type): """ Constructs Headers for the Local Lambda Error Response Parameters ---------- error_type str Error type that occurred to be put into the 'x-amzn-errortype' header Returns ------- dict Dict representing the Lambda Error Response Headers """ return {"x-amzn-errortype": error_type, "Content-Type": "application/json"}