You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pulumi配置AWS API Gateway Response未生效,CORS头缺失问题

问题

使用Pulumi创建代理Lambda后端的AWS API Gateway,Web前端调用该网关,多数场景下由Lambda处理CORS。但当API密钥的Usage Plan配额超出时,Gateway返回429响应却不带CORS头,导致前端无法准确判断问题,无法显示专属的“服务器过载”错误,只能显示通用提示。

尝试通过Pulumi配置Gateway Response来添加CORS头,涵盖QUOTA_EXCEEDED、THROTTLED等多种响应类型,代码如下:

addGatewayResponse(restApi.api.id, "429", "QUOTA_EXCEEDED");
addGatewayResponse(restApi.api.id, "429", "THROTTLED");
addGatewayResponse(restApi.api.id, "403", "INVALID_API_KEY");
addGatewayResponse(restApi.api.id, "403", "MISSING_AUTHENTICATION_TOKEN");
addGatewayResponse(restApi.api.id, "404", "RESOURCE_NOT_FOUND");
addGatewayResponse(restApi.api.id, "400", "DEFAULT_4XX");
addGatewayResponse(restApi.api.id, "500", "DEFAULT_5XX");

function addGatewayResponse(
  restApiId: pulumi.Output<string>,
  statusCode: string,
  responseType: string
) {
  new aws.apigateway.Response(`${name}-GatewayResponse-${responseType}`, {
    restApiId: api.api.id,
    responseType,
    statusCode,
    responseTemplates: {
      "application/json": JSON.stringify({
        message: "$context.error.messageString",
        type: "$context.error.responseType",
        statusCode,
        resourcePath: "$context.resourcePath",
      }),
    },
    responseParameters: {
      "gatewayresponse.header.Access-Control-Allow-Origin": "'*'",
      "gatewayresponse.header.Access-Control-Allow-Headers": "'*'",
      "gatewayresponse.header.Access-Control-Allow-Methods": "'*'",
    },
  });
}

已完全销毁并重建栈,控制台显示配置符合预期,但测试时(省略API密钥或设置低配额),curl返回的429响应无CORS头:

< HTTP/2 429
< date: Thu, 27 Oct 2022 22:30:31 GMT
< content-type: application/json
< content-length: 28
< x-amzn-requestid: xxx
< x-amzn-errortype: LimitExceededException
< x-amz-apigw-id: xxx
< 
* Connection #0 to host xxx.execute-api.xxx.amazonaws.com left intact
{"message":"Limit Exceeded"}

Web端fetch抛出“TypeError: NetworkError when attempting to fetch resource.”错误,无法获取响应状态码。直接调用阶段的Invoke URL,网关已改为区域型以避开CloudFront,正常请求可正常工作,Gateway Response配置似乎完全未生效。

解决方案

1. 修复变量引用错误

你的addGatewayResponse函数接收了restApiId参数,但实际创建aws.apigateway.Response时硬编码使用了api.api.id,如果api并非当前目标REST API的实例引用,会导致Gateway Response绑定到错误的API上,自然无法生效。修改函数内的restApiId为传入的参数:

function addGatewayResponse(
  restApiId: pulumi.Output<string>,
  statusCode: string,
  responseType: string
) {
  new aws.apigateway.Response(`${name}-GatewayResponse-${responseType}`, {
    restApiId: restApiId, // 替换原有的api.api.id
    responseType,
    statusCode,
    responseTemplates: {
      "application/json": JSON.stringify({
        message: "$context.error.messageString",
        type: "$context.error.responseType",
        statusCode,
        resourcePath: "$context.resourcePath",
      }),
    },
    responseParameters: {
      "gatewayresponse.header.Access-Control-Allow-Origin": "'*'",
      "gatewayresponse.header.Access-Control-Allow-Headers": "'*'",
      "gatewayresponse.header.Access-Control-Allow-Methods": "'*'",
    },
  });
}

2. 确保API部署依赖Gateway Response

API Gateway的配置变更需要通过部署才能生效,需确保你的API部署资源依赖于所有Gateway Response资源,这样Pulumi会先创建Gateway Response再部署API,保证配置被正确应用。可以通过dependsOn属性添加依赖:

// 假设你的部署资源定义如下,添加dependsOn
const deployment = new aws.apigateway.Deployment(`${name}-deployment`, {
  restApi: restApi.api,
  stageName: "prod", // 你的阶段名
}, {
  dependsOn: [
    // 列出所有Gateway Response实例,或通过数组收集所有addGatewayResponse创建的资源
  ],
});

3. 验证响应类型与实际匹配

AWS API Gateway针对配额超限返回的响应类型确实是QUOTA_EXCEEDED,但可以通过CloudWatch日志查看$context.error.responseType的实际值,确认是否和你配置的响应类型一致,避免因类型拼写或匹配问题导致配置不生效。

4. 补充预检请求的CORS处理(可选)

如果前端发送OPTIONS预检请求时遇到错误,虽然DEFAULT_4XX已覆盖大部分场景,但可以单独针对OPTIONS方法配置对应的Gateway Response,确保预检请求的错误响应也带有CORS头。

完成上述修改后,重新部署栈并测试,此时429等错误响应应会包含CORS头,前端可正常获取响应状态码并显示专属错误提示。

内容的提问来源于stack exchange,提问作者Dave

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 17:42:15