Skip to content

[BUG] (type-safe-api) prepare-spec overrides gateway responses #922

@ghost

Description

Describe the bug

I appreciate the amazing work the team have done and have helped my project tremendously.

I'm running into an issue where I want to add DEFAULT_5XX and DEFAULT_4XX gateway response to my API with "Access-Control-Allow-Origin" response headers.

However, when corsOptions is set, it gets overridden with values set from the prepare-spec lambda

Expected Behavior

I should be able to call addGatewayResponse to create custom Gateway responses despite setting corsOptions in my generated API.

corsOptions: {
  allowOrigins: Cors.ALL_ORIGINS,
  allowMethods: Cors.ALL_METHODS,
},
...
this.api.addGatewayResponse(`Default4xxResponse`, {
  type: ResponseType.DEFAULT_4XX,
  responseHeaders: {
    "Access-Control-Allow-Origin": "'*'",
  },
});
this.api.addGatewayResponse(`Default5xxResponse`, {
  type: ResponseType.DEFAULT_5XX,
  responseHeaders: {
    "Access-Control-Allow-Origin": "'*'",
  },
});

While setting CORS for all integration responses is great, sometimes upstream errors due to lambda auth, WAF, etc. needs to return response headers with CORS as well.

Current Behavior

The outputted prepare spec contains

"x-amazon-apigateway-gateway-responses":{"BAD_REQUEST_BODY":{"statusCode":400,"responseTemplates":{"application/json":"{\"message\": \"$context.error.validationErrorString\"}"},"responseParameters":{"gatewayresponse.header.Access-Control-Allow-Headers":"'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent,x-amz-content-sha256'","gatewayresponse.header.Access-Control-Allow-Methods":"'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'","gatewayresponse.header.Access-Control-Allow-Origin":"'*'"}}}}

and this is preventing additional modifications the the API Gateway Responses.

Reproduction Steps

this.api = new Api(this, id, {
  defaultAuthorizer: Authorizers.iam(),
  corsOptions: {
    allowOrigins: Cors.ALL_ORIGINS,
    allowMethods: Cors.ALL_METHODS,
  },
  integrations: {
    sayHello: {
      integration: Integrations.lambda(new SayHelloFunction(this, "SayHello")),
    },
  },
  policy: new PolicyDocument({
    statements: [
      new PolicyStatement({
        effect: Effect.ALLOW,
        principals: [new AccountPrincipal(Stack.of(this).account)],
        actions: ["execute-api:Invoke"],
        resources: ["execute-api:/*"],
      }),
      new PolicyStatement({
        effect: Effect.ALLOW,
        principals: [new AnyPrincipal()],
        actions: ["execute-api:Invoke"],
        resources: ["execute-api:/*/OPTIONS/*"],
      }),
    ],
  }),
});

this.api.api.addGatewayResponse(`Default4xxResponse`, {
  type: ResponseType.DEFAULT_4XX,
  responseHeaders: {
    "Access-Control-Allow-Origin": "'*'",
  },
});
this.api.api.addGatewayResponse(`Default5xxResponse`, {
  type: ResponseType.DEFAULT_5XX,
  responseHeaders: {
    "Access-Control-Allow-Origin": "'*'",
  },
});

Observe that the gateway responses besides the 400 BAD_REQUEST_BODY created from the apiDefinition is not set. If I do not include corsOptions in the constructor, the other response headers will be set correctly, but will run into CORS issues for successful integration responses since CORS are not set for those.

Possible Solution

I'm not too familiar with how apiDefinition interacts with conflicting ApiGateway constructs but consider updating prepare-spec handler. Don't have a solid solution.

Additional Information/Context

Any configuration changes or workarounds would be appreciated.

PDK version used

0.26.1

What languages are you seeing this issue on?

Typescript

Environment details (OS name and version, etc.)

MacOS 15.4.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions