def invoke_rest_api(invocation_context: ApiInvocationContext): invocation_path = invocation_context.path_with_query_string raw_path = invocation_context.path or invocation_path method = invocation_context.method headers = invocation_context.headers # run gateway authorizers for this request authorize_invocation(invocation_context) extracted_path, resource = get_target_resource_details(invocation_context) if not resource: return make_error_response( "Unable to find path %s" % invocation_context.path, 404) # validate request validator = RequestValidator(invocation_context, aws_stack.connect_to_service("apigateway")) if not validator.is_request_valid(): return make_error_response("Invalid request body", 400) api_key_required = resource.get("resourceMethods", {}).get(method, {}).get("apiKeyRequired") if not is_api_key_valid(api_key_required, headers, invocation_context.stage): return make_error_response("Access denied - invalid API key", 403) integrations = resource.get("resourceMethods", {}) integration = integrations.get(method, {}) if not integration: # HttpMethod: '*' # ResourcePath: '/*' - produces 'X-AMAZON-APIGATEWAY-ANY-METHOD' integration = integrations.get("ANY", {}) or integrations.get( "X-AMAZON-APIGATEWAY-ANY-METHOD", {}) integration = integration.get("methodIntegration") if not integration: if method == "OPTIONS" and "Origin" in headers: # default to returning CORS headers if this is an OPTIONS request return get_cors_response(headers) return make_error_response( "Unable to find integration for: %s %s (%s)" % (method, invocation_path, raw_path), 404, ) res_methods = resource.get("resourceMethods", {}) meth_integration = res_methods.get(method, {}).get("methodIntegration", {}) int_responses = meth_integration.get("integrationResponses", {}) response_templates = int_responses.get("200", {}).get("responseTemplates", {}) # update fields in invocation context, then forward request to next handler invocation_context.resource = resource invocation_context.resource_path = extracted_path invocation_context.response_templates = response_templates invocation_context.integration = integration return invoke_rest_api_integration(invocation_context)
def get_target_resource_details( invocation_context: ApiInvocationContext) -> Tuple[str, Dict]: """Look up and return the API GW resource (path pattern + resource dict) for the given invocation context.""" path_map = helpers.get_rest_api_paths( rest_api_id=invocation_context.api_id, region_name=invocation_context.region_name) relative_path = invocation_context.invocation_path try: extracted_path, resource = get_resource_for_path(path=relative_path, path_map=path_map) invocation_context.resource = resource return extracted_path, resource except Exception: return None, None