diff --git a/.changelog/45329.txt b/.changelog/45329.txt new file mode 100644 index 000000000000..66dc4fce8e11 --- /dev/null +++ b/.changelog/45329.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_api_gateway_integration: Add `response_transfer_mode` argument +``` diff --git a/internal/service/apigateway/integration.go b/internal/service/apigateway/integration.go index e44885ccf890..449ad961e4b6 100644 --- a/internal/service/apigateway/integration.go +++ b/internal/service/apigateway/integration.go @@ -122,6 +122,12 @@ func resourceIntegration() *schema.Resource { Required: true, ForceNew: true, }, + "response_transfer_mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateDiagFunc: enum.Validate[types.ResponseTransferMode](), + }, "rest_api_id": { Type: schema.TypeString, Required: true, @@ -213,6 +219,10 @@ func resourceIntegrationCreate(ctx context.Context, d *schema.ResourceData, meta input.RequestTemplates = flex.ExpandStringValueMap(v.(map[string]any)) } + if v, ok := d.GetOk("response_transfer_mode"); ok { + input.ResponseTransferMode = types.ResponseTransferMode(v.(string)) + } + if v, ok := d.GetOk("timeout_milliseconds"); ok { input.TimeoutInMillis = aws.Int32(int32(v.(int))) } @@ -267,6 +277,11 @@ func resourceIntegrationRead(ctx context.Context, d *schema.ResourceData, meta a requestTemplates := make(map[string]string) maps.Copy(requestTemplates, integration.RequestTemplates) d.Set("request_templates", requestTemplates) + if integration.ResponseTransferMode == "" { + d.Set("response_transfer_mode", string(types.ResponseTransferModeBuffered)) + } else { + d.Set("response_transfer_mode", integration.ResponseTransferMode) + } d.Set("timeout_milliseconds", integration.TimeoutInMillis) d.Set(names.AttrType, integration.Type) d.Set(names.AttrURI, integration.Uri) @@ -442,6 +457,18 @@ func resourceIntegrationUpdate(ctx context.Context, d *schema.ResourceData, meta }) } + if d.HasChange("response_transfer_mode") { + responseTransferMode := d.Get("response_transfer_mode").(string) + if responseTransferMode == "" { + responseTransferMode = string(types.ResponseTransferModeBuffered) + } + operations = append(operations, types.PatchOperation{ + Op: types.OpReplace, + Path: aws.String("/responseTransferMode"), + Value: aws.String(responseTransferMode), + }) + } + if d.HasChange("timeout_milliseconds") { operations = append(operations, types.PatchOperation{ Op: types.OpReplace, diff --git a/internal/service/apigateway/integration_test.go b/internal/service/apigateway/integration_test.go index 4fa68447567c..689435dde756 100644 --- a/internal/service/apigateway/integration_test.go +++ b/internal/service/apigateway/integration_test.go @@ -11,6 +11,7 @@ import ( "github.com/YakDriver/regexache" "github.com/aws/aws-sdk-go-v2/service/apigateway" + awstypes "github.com/aws/aws-sdk-go-v2/service/apigateway/types" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -582,6 +583,60 @@ func TestAccAPIGatewayIntegration_TLS_insecureSkipVerification(t *testing.T) { }) } +func TestAccAPIGatewayIntegration_responseTransferMode(t *testing.T) { + ctx := acctest.Context(t) + var conf apigateway.GetIntegrationOutput + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_api_gateway_integration.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); acctest.PreCheckAPIGatewayTypeEDGE(t) }, + ErrorCheck: acctest.ErrorCheck(t, names.APIGatewayServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckIntegrationDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccIntegrationConfig_responseTransferMode(rName, string(awstypes.ResponseTransferModeStream)), + Check: resource.ComposeTestCheckFunc( + testAccCheckIntegrationExists(ctx, resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, names.AttrType, "HTTP_PROXY"), + resource.TestCheckResourceAttr(resourceName, "integration_http_method", "ANY"), + resource.TestCheckResourceAttr(resourceName, names.AttrURI, "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "response_transfer_mode", string(awstypes.ResponseTransferModeStream)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateIdFunc: testAccIntegrationImportStateIdFunc(resourceName), + ImportStateVerify: true, + }, + { + // Switch to Buffered + Config: testAccIntegrationConfig_responseTransferMode(rName, string(awstypes.ResponseTransferModeBuffered)), + Check: resource.ComposeTestCheckFunc( + testAccCheckIntegrationExists(ctx, resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, names.AttrType, "HTTP_PROXY"), + resource.TestCheckResourceAttr(resourceName, "integration_http_method", "ANY"), + resource.TestCheckResourceAttr(resourceName, names.AttrURI, "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "response_transfer_mode", string(awstypes.ResponseTransferModeBuffered)), + ), + }, + { + // Switch back to Stream + Config: testAccIntegrationConfig_responseTransferMode(rName, string(awstypes.ResponseTransferModeStream)), + Check: resource.ComposeTestCheckFunc( + testAccCheckIntegrationExists(ctx, resourceName, &conf), + resource.TestCheckResourceAttr(resourceName, names.AttrType, "HTTP_PROXY"), + resource.TestCheckResourceAttr(resourceName, "integration_http_method", "ANY"), + resource.TestCheckResourceAttr(resourceName, names.AttrURI, "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "response_transfer_mode", string(awstypes.ResponseTransferModeStream)), + ), + }, + }, + }) +} + func TestAccAPIGatewayIntegration_disappears(t *testing.T) { ctx := acctest.Context(t) var conf apigateway.GetIntegrationOutput @@ -1269,3 +1324,35 @@ resource "aws_api_gateway_integration" "test" { } `, rName, insecureSkipVerification) } + +func testAccIntegrationConfig_responseTransferMode(rName, responseTransferMode string) string { + return fmt.Sprintf(` +resource "aws_api_gateway_rest_api" "api" { + name = %[1]q +} + +resource "aws_api_gateway_resource" "resource" { + path_part = "resource" + parent_id = aws_api_gateway_rest_api.api.root_resource_id + rest_api_id = aws_api_gateway_rest_api.api.id +} + +resource "aws_api_gateway_method" "method" { + rest_api_id = aws_api_gateway_rest_api.api.id + resource_id = aws_api_gateway_resource.resource.id + http_method = "ANY" + authorization = "NONE" +} + +resource "aws_api_gateway_integration" "test" { + rest_api_id = aws_api_gateway_rest_api.api.id + resource_id = aws_api_gateway_resource.resource.id + http_method = aws_api_gateway_method.method.http_method + integration_http_method = "ANY" + type = "HTTP_PROXY" + uri = "https://example.com" + + response_transfer_mode = %[2]q +} +`, rName, responseTransferMode) +} diff --git a/website/docs/r/api_gateway_integration.html.markdown b/website/docs/r/api_gateway_integration.html.markdown index e9a1a165a352..506a0ec39c25 100644 --- a/website/docs/r/api_gateway_integration.html.markdown +++ b/website/docs/r/api_gateway_integration.html.markdown @@ -220,6 +220,8 @@ This resource supports the following arguments: * `request_templates` - (Optional) Map of the integration's request templates. * `request_parameters` - (Optional) Map of request query string parameters and headers that should be passed to the backend responder. For example: `request_parameters = { "integration.request.header.X-Some-Other-Header" = "method.request.header.X-Some-Header" }` +* `response_transfer_mode` – (Optional) Specifies the response transfer mode of the integration. Valid values are `BUFFERED` and `STREAM`. Default to `BUFFERED`. + Once set, setting the value to `BUFFERED` requires explicitly specifying `BUFFERED`, rather than removing this argument. * `passthrough_behavior` - (Optional) Integration passthrough behavior (`WHEN_NO_MATCH`, `WHEN_NO_TEMPLATES`, `NEVER`). **Required** if `request_templates` is used. * `cache_key_parameters` - (Optional) List of cache key parameters for the integration. * `cache_namespace` - (Optional) Integration's cache namespace.