如何通过CDK为API Gateway RestAPI集成响应添加自定义CORS头
解决AWS CDK中API Gateway GET请求的CORS头配置问题
标准CDK配置方案
要让GET请求返回CORS头,需要同时配置方法响应和集成响应,之前出现映射表达式无效的错误,通常是因为集成响应的头值格式不符合API Gateway要求(字符串常量需用单引号包裹)。
步骤1:配置方法响应
在添加GET方法时,明确声明要返回Access-Control-Allow-Origin头:
import { RestApi, AwsIntegration } from 'aws-cdk-lib/aws-apigateway'; import { Table } from 'aws-cdk-lib/aws-dynamodb'; // 假设已有restApi和dynamoDbTable实例 const getIntegration = new AwsIntegration({ service: 'dynamodb', action: 'Scan', options: { credentialsRole: yourExecutionRole, requestTemplates: { 'application/json': JSON.stringify({ TableName: dynamoDbTable.tableName, }), }, integrationResponses: [{ statusCode: '200' }], }, }); // 添加GET方法并配置方法响应 const getMethod = restApi.root.addMethod('GET', getIntegration, { methodResponses: [ { statusCode: '200', responseParameters: { 'method.response.header.Access-Control-Allow-Origin': true, // 声明该头会被返回 }, }, ], });
步骤2:配置集成响应
给集成响应添加CORS头的映射,注意值需要用单引号包裹:
// 为GET方法的集成响应添加CORS头 getIntegration.addIntegrationResponse('200', { statusCode: '200', responseParameters: { 'method.response.header.Access-Control-Allow-Origin': "'*'", // 允许所有域名,指定域名则写"'https://your-domain.com'" }, });
部署后,GET请求的响应头就会包含Access-Control-Allow-Origin。
Lambda自定义资源变通方案
如果上述标准方案仍因CDK版本兼容或复杂场景部署失败,可以用Lambda自定义资源直接调用API Gateway的API来修正集成响应。
步骤1:编写Lambda函数
创建一个Node.js Lambda,负责更新API Gateway的集成响应:
const AWS = require('aws-sdk'); const apigateway = new AWS.APIGateway(); exports.handler = async (event) => { if (event.RequestType === 'Delete') { return { Status: 'SUCCESS' }; } const { restApiId, resourceId, httpMethod, allowOrigin } = event.ResourceProperties; const allowOriginValue = allowOrigin || "'*'"; try { await apigateway.updateIntegrationResponse({ restApiId, resourceId, httpMethod, statusCode: '200', patchOperations: [ { op: 'replace', path: '/responseParameters/method.response.header.Access-Control-Allow-Origin', value: allowOriginValue, }, ], }).promise(); return { Status: 'SUCCESS', PhysicalResourceId: `${restApiId}-${resourceId}-${httpMethod}-cors` }; } catch (error) { console.error('Failed to update integration response:', error); return { Status: 'FAILED', Reason: error.message }; } };
步骤2:在CDK中定义自定义资源
将Lambda和自定义资源加入CDK栈:
import { CustomResource } from 'aws-cdk-lib'; import { Function, Runtime, Code } from 'aws-cdk-lib/aws-lambda'; import { Role, ServicePrincipal, ManagedPolicy, PolicyStatement } from 'aws-cdk-lib/aws-iam'; // 创建Lambda执行角色 const corsFixRole = new Role(this, 'CorsFixRole', { assumedBy: new ServicePrincipal('lambda.amazonaws.com'), managedPolicies: [ ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'), ], }); // 授予修改API Gateway集成响应的权限 corsFixRole.addToPolicy(new PolicyStatement({ actions: ['apigateway:updateIntegrationResponse'], resources: [ `arn:aws:apigateway:${this.region}::/restapis/${restApi.restApiId}/resources/${restApi.root.resourceId}/methods/GET/integration/responses/200` ], })); // 创建Lambda函数 const corsFixLambda = new Function(this, 'CorsFixLambda', { runtime: Runtime.NODEJS_18_X, handler: 'index.handler', code: Code.fromInline(`上面的Lambda代码内容`), role: corsFixRole, }); // 部署时触发自定义资源 new CustomResource(this, 'CorsFixCustomResource', { serviceToken: corsFixLambda.functionArn, properties: { restApiId: restApi.restApiId, resourceId: restApi.root.resourceId, // 如果GET方法在子资源,替换为对应resourceId httpMethod: 'GET', allowOrigin: "'*'", // 替换为你的允许域名 }, });
这个自定义资源会在栈部署时自动调用Lambda,为GET方法的集成响应添加CORS头,绕过CDK配置的潜在问题。
内容的提问来源于stack exchange,提问作者alexanderbird
相关产品推荐
相关产品推荐

