def create_aws_request_context( service_name: str, action: str, parameters: Mapping[str, Any] = None, region: str = None, endpoint_url: Optional[str] = None, ) -> RequestContext: """ This is a stripped-down version of what the botocore client does to perform an HTTP request from a client call. A client call looks something like this: boto3.client("sqs").create_queue(QueueName="myqueue"), which will be serialized into an HTTP request. This method does the same, without performing the actual request, and with a more low-level interface. An equivalent call would be create_aws_request_context("sqs", "CreateQueue", {"QueueName": "myqueue"}) :param service_name: the AWS service :param action: the action to invoke :param parameters: the invocation parameters :param region: the region name (default is us-east-1) :param endpoint_url: the endpoint to call (defaults to localstack) :return: a RequestContext object that describes this request """ if parameters is None: parameters = {} if region is None: region = config.AWS_REGION_US_EAST_1 service = load_service(service_name) operation = service.operation_model(action) # we re-use botocore internals here to serialize the HTTP request, but don't send it client = aws_stack.connect_to_service(service_name, endpoint_url=endpoint_url, region_name=region) request_context = { "client_region": region, "has_streaming_input": operation.has_streaming_input, "auth_type": operation.auth_type, } request_dict = client._convert_to_request_dict(parameters, operation, context=request_context) aws_request = client._endpoint.create_request(request_dict, operation) context = RequestContext() context.service = service context.operation = operation context.region = region context.request = create_http_request(aws_request) return context
def invoke(self, context: RequestContext) -> HttpResponse: if context.operation and context.service_request: # if the parsed request is already set in the context, re-use them operation, instance = context.operation, context.service_request else: # otherwise parse the incoming HTTPRequest operation, instance = self.parser.parse(context.request) context.operation = operation serializer = self.serializer try: # Find the operation's handler in the dispatch table if operation.name not in self.dispatch_table: LOG.warning( "missing entry in dispatch table for %s.%s", self.service.service_name, operation.name, ) raise NotImplementedError handler = self.dispatch_table[operation.name] # Call the appropriate handler result = handler(context, instance) or dict() # Serialize result dict to an HTTPResponse and return it return serializer.serialize_to_response(result, operation) except ServiceException as e: return serializer.serialize_error_to_response(e, operation) except NotImplementedError: action_name = operation.name service_name = operation.service_model.service_name message = ( f"API action '{action_name}' for service '{service_name}' " f"not yet implemented") LOG.info(message) error = CommonServiceException("InternalFailure", message, status_code=501) # record event analytics.log.event("services_notimplemented", payload={ "s": service_name, "a": action_name }) return serializer.serialize_error_to_response(error, operation)
def invoke(self, context: RequestContext) -> HttpResponse: if context.operation and context.service_request: # if the parsed request is already set in the context, re-use them operation, instance = context.operation, context.service_request else: # otherwise, parse the incoming HTTPRequest operation, instance = self.parser.parse(context.request) context.operation = operation try: # Find the operation's handler in the dispatch table if operation.name not in self.dispatch_table: LOG.warning( "missing entry in dispatch table for %s.%s", self.service.service_name, operation.name, ) raise NotImplementedError return self.dispatch_request(context, instance) except ServiceException as e: return self.on_service_exception(context, e) except NotImplementedError: return self.on_not_implemented_error(context)