diff --git a/moto/apigateway/models.py b/moto/apigateway/models.py index 8adcef207..d4497e0c4 100644 --- a/moto/apigateway/models.py +++ b/moto/apigateway/models.py @@ -153,10 +153,12 @@ class Integration(BaseModel): request_templates: Optional[Dict[str, Any]] = None, passthrough_behavior: Optional[str] = "WHEN_NO_MATCH", cache_key_parameters: Optional[List[str]] = None, - tls_config: Optional[str] = None, + tls_config: Optional[Dict[str, Any]] = None, cache_namespace: Optional[str] = None, timeout_in_millis: Optional[str] = None, request_parameters: Optional[Dict[str, Any]] = None, + content_handling: Optional[str] = None, + credentials: Optional[str] = None, ): self.integration_type = integration_type self.uri = uri @@ -168,6 +170,8 @@ class Integration(BaseModel): self.cache_namespace = cache_namespace self.timeout_in_millis = timeout_in_millis self.request_parameters = request_parameters + self.content_handling = content_handling + self.credentials = credentials self.integration_responses: Optional[Dict[str, IntegrationResponse]] = None def to_json(self) -> Dict[str, Any]: @@ -188,6 +192,8 @@ class Integration(BaseModel): "cacheNamespace": self.cache_namespace, "timeoutInMillis": self.timeout_in_millis, "requestParameters": self.request_parameters, + "contentHandling": self.content_handling, + "credentials": self.credentials, } def create_integration_response( @@ -488,10 +494,12 @@ class Resource(CloudFormationModel): request_templates: Optional[Dict[str, Any]] = None, passthrough_behavior: Optional[str] = None, integration_method: Optional[str] = None, - tls_config: Optional[str] = None, + tls_config: Optional[Dict[str, Any]] = None, cache_namespace: Optional[str] = None, timeout_in_millis: Optional[str] = None, request_parameters: Optional[Dict[str, Any]] = None, + content_handling: Optional[str] = None, + credentials: Optional[str] = None, ) -> Integration: integration_method = integration_method or method_type integration = Integration( @@ -504,6 +512,8 @@ class Resource(CloudFormationModel): cache_namespace=cache_namespace, timeout_in_millis=timeout_in_millis, request_parameters=request_parameters, + content_handling=content_handling, + credentials=credentials, ) self.resource_methods[method_type].method_integration = integration return integration @@ -1004,7 +1014,7 @@ class RestAPI(CloudFormationModel): } self.tags = kwargs.get(RestAPI.PROP_TAGS) or {} self.disableExecuteApiEndpoint = ( - kwargs.get(RestAPI.PROP_DISABLE_EXECUTE_API_ENDPOINT) or False + kwargs.get("disable_execute_api_endpoint") or False ) self.minimum_compression_size = kwargs.get("minimum_compression_size") self.deployments: Dict[str, Deployment] = {} @@ -1526,6 +1536,7 @@ class APIGatewayBackend(BaseBackend): tags: Optional[List[Dict[str, str]]] = None, policy: Optional[str] = None, minimum_compression_size: Optional[int] = None, + disable_execute_api_endpoint: Optional[bool] = None, ) -> RestAPI: api_id = create_id() rest_api = RestAPI( @@ -1539,6 +1550,7 @@ class APIGatewayBackend(BaseBackend): tags=tags, policy=policy, minimum_compression_size=minimum_compression_size, + disable_execute_api_endpoint=disable_execute_api_endpoint, ) self.apis[api_id] = rest_api return rest_api @@ -1835,10 +1847,11 @@ class APIGatewayBackend(BaseBackend): credentials: Optional[str] = None, request_templates: Optional[Dict[str, Any]] = None, passthrough_behavior: Optional[str] = None, - tls_config: Optional[str] = None, + tls_config: Optional[Dict[str, Any]] = None, cache_namespace: Optional[str] = None, timeout_in_millis: Optional[str] = None, request_parameters: Optional[Dict[str, Any]] = None, + content_handling: Optional[str] = None, ) -> Integration: resource = self.get_resource(function_id, resource_id) if credentials and not re.match( @@ -1881,6 +1894,8 @@ class APIGatewayBackend(BaseBackend): cache_namespace=cache_namespace, timeout_in_millis=timeout_in_millis, request_parameters=request_parameters, + content_handling=content_handling, + credentials=credentials, ) return integration diff --git a/moto/apigateway/responses.py b/moto/apigateway/responses.py index ee4aee3fd..2e22c5854 100644 --- a/moto/apigateway/responses.py +++ b/moto/apigateway/responses.py @@ -76,6 +76,7 @@ class APIGatewayResponse(BaseResponse): tags = self._get_param("tags") policy = self._get_param("policy") minimum_compression_size = self._get_param("minimumCompressionSize") + disable_execute_api_endpoint = self._get_param("disableExecuteApiEndpoint") # Param validation response = self.__validate_api_key_source(api_key_source) @@ -94,6 +95,7 @@ class APIGatewayResponse(BaseResponse): tags=tags, policy=policy, minimum_compression_size=minimum_compression_size, + disable_execute_api_endpoint=disable_execute_api_endpoint, ) return 200, {}, json.dumps(rest_api.to_dict()) @@ -451,6 +453,7 @@ class APIGatewayResponse(BaseResponse): cache_namespace = self._get_param("cacheNamespace") timeout_in_millis = self._get_param("timeoutInMillis") request_parameters = self._get_param("requestParameters") + content_handling = self._get_param("contentHandling") self.backend.get_method(function_id, resource_id, method_type) integration_http_method = self._get_param( @@ -471,6 +474,7 @@ class APIGatewayResponse(BaseResponse): cache_namespace=cache_namespace, timeout_in_millis=timeout_in_millis, request_parameters=request_parameters, + content_handling=content_handling, ) return 201, {}, json.dumps(integration_response.to_json()) elif self.method == "DELETE": diff --git a/tests/test_apigateway/test_apigateway.py b/tests/test_apigateway/test_apigateway.py index 6cde7cfe3..46656353f 100644 --- a/tests/test_apigateway/test_apigateway.py +++ b/tests/test_apigateway/test_apigateway.py @@ -9,13 +9,17 @@ from moto import mock_apigateway, mock_cognitoidp from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID import pytest +from tests import DEFAULT_ACCOUNT_ID + @freeze_time("2015-01-01") @mock_apigateway def test_create_and_get_rest_api(): client = boto3.client("apigateway", region_name="us-west-2") - response = client.create_rest_api(name="my_api", description="this is my api") + response = client.create_rest_api( + name="my_api", description="this is my api", disableExecuteApiEndpoint=True + ) api_id = response["id"] response = client.get_rest_api(restApiId=api_id) @@ -32,7 +36,7 @@ def test_create_and_get_rest_api(): "apiKeySource": "HEADER", "endpointConfiguration": {"types": ["EDGE"]}, "tags": {}, - "disableExecuteApiEndpoint": False, + "disableExecuteApiEndpoint": True, } ) @@ -526,7 +530,11 @@ def test_integrations(): uri="http://httpbin.org/robots.txt", integrationHttpMethod="POST", requestParameters={"integration.request.header.X-Custom": "'Custom'"}, + contentHandling="CONVERT_TO_TEXT", + credentials=f"arn:aws:iam::{DEFAULT_ACCOUNT_ID}:role/apigateway-invoke-lambda-exec-role", + tlsConfig={"insecureSkipVerification": True}, ) + # this is hard to match against, so remove it response["ResponseMetadata"].pop("HTTPHeaders", None) response["ResponseMetadata"].pop("RetryAttempts", None) @@ -539,6 +547,9 @@ def test_integrations(): "passthroughBehavior": "WHEN_NO_TEMPLATES", "cacheKeyParameters": [], "requestParameters": {"integration.request.header.X-Custom": "'Custom'"}, + "contentHandling": "CONVERT_TO_TEXT", + "credentials": f"arn:aws:iam::{DEFAULT_ACCOUNT_ID}:role/apigateway-invoke-lambda-exec-role", + "tlsConfig": {"insecureSkipVerification": True}, } ) @@ -557,6 +568,9 @@ def test_integrations(): "passthroughBehavior": "WHEN_NO_TEMPLATES", "cacheKeyParameters": [], "requestParameters": {"integration.request.header.X-Custom": "'Custom'"}, + "contentHandling": "CONVERT_TO_TEXT", + "credentials": f"arn:aws:iam::{DEFAULT_ACCOUNT_ID}:role/apigateway-invoke-lambda-exec-role", + "tlsConfig": {"insecureSkipVerification": True}, } ) @@ -574,6 +588,9 @@ def test_integrations(): "cacheKeyParameters": [], "passthroughBehavior": "WHEN_NO_TEMPLATES", "requestParameters": {"integration.request.header.X-Custom": "'Custom'"}, + "contentHandling": "CONVERT_TO_TEXT", + "credentials": f"arn:aws:iam::{DEFAULT_ACCOUNT_ID}:role/apigateway-invoke-lambda-exec-role", + "tlsConfig": {"insecureSkipVerification": True}, } )