REST API集成S3时CORS配置失败,OPTIONS请求返回500错误
REST API与S3集成时OPTIONS请求返回500错误的排查与修复
问题详情
配置REST API与S3集成以返回存储桶对象列表时,CORS设置异常:已启用CORS并生成OPTIONS方法,但通过JS或curl发送OPTIONS请求时收到500 Internal Server Error。
CloudWatch日志
Method request body before transformations: [Binary Data]
Execution failed due to configuration error: Unable to transform request
Method completed with status: 500
curl响应内容
< HTTP/2 500
< date: Wed, 18 Jan 2023 21:43:27 GMT
< content-type: application/json
< content-length: 36
< x-amzn-requestid: e31e295f-2d8a-4cb5-892e-2b1b517f3650
< x-amzn-errortype: InternalServerErrorException
< x-amz-apigw-id: xxxxxxx
<
- Connection #0 to host xxxx.execute-api.eu-central-1.amazonaws.com left intact
{"message": "Internal server error"}%
现有CDK(TypeScript)代码
private createS3Integration(documentsBucket: IBucket, executeRole: Role) { return new apigw.AwsIntegration({ service: 's3', integrationHttpMethod: 'GET', path: '{bucket}', options: { credentialsRole: executeRole, integrationResponses: [ { statusCode: '200', responseParameters: { 'method.response.header.Content-Type': 'integration.response.header.Content-Type' }, } ], requestParameters: { 'integration.request.path.bucket': 'method.request.path.folder' }, }, }); } private addDocumentsGetEndpoint(apiGateway: apigw.RestApi, s3GetIntegration: apigw.AwsIntegration) { apiGateway .root .addResource('{folder}') .addMethod('GET', s3GetIntegration, { methodResponses: [ { statusCode: '200', responseParameters: { 'method.response.header.Content-Type': true }, }, ], requestParameters: { 'method.request.path.folder': true, 'method.request.header.Content-Type': true }, }); }
错误原因
- 自动生成的OPTIONS方法继承了GET集成配置:API Gateway启用CORS时自动创建的OPTIONS方法,会默认复用对应资源的GET方法集成规则(包括S3集成、请求参数映射、凭证角色等),但OPTIONS请求不需要与S3交互,这种不匹配导致请求转换失败。
- GET方法强制要求Content-Type头:现有代码中GET方法配置了
method.request.header.Content-Type: true,但OPTIONS请求通常不会携带该头,进一步触发参数映射错误。
修复方案
1. 手动配置OPTIONS方法(使用Mock集成)
放弃自动生成的OPTIONS方法,为资源手动添加Mock集成的OPTIONS方法,直接返回符合要求的CORS响应头,无需调用S3。
2. 移除GET方法中不必要的请求参数要求
删除GET方法中对Content-Type请求头的强制要求,避免对OPTIONS请求产生影响。
修改后的CDK代码示例
// 新增:手动创建OPTIONS方法的Mock集成 private addDocumentsOptionsEndpoint(apiResource: apigw.IResource) { apiResource.addMethod('OPTIONS', new apigw.MockIntegration({ integrationResponses: [{ statusCode: '200', responseParameters: { 'method.response.header.Access-Control-Allow-Origin': "'*'", 'method.response.header.Access-Control-Allow-Methods': "'GET,OPTIONS'", 'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" }, responseTemplates: { 'application/json': '{}' } }], passthroughBehavior: apigw.PassthroughBehavior.NEVER, requestTemplates: { 'application/json': '{"statusCode": 200}' } }), { methodResponses: [{ statusCode: '200', responseParameters: { 'method.response.header.Access-Control-Allow-Origin': true, 'method.response.header.Access-Control-Allow-Methods': true, 'method.response.header.Access-Control-Allow-Headers': true } }] }); } // 修改GET方法配置,移除不必要的Content-Type头要求 private addDocumentsGetEndpoint(apiGateway: apigw.RestApi, s3GetIntegration: apigw.AwsIntegration) { const folderResource = apiGateway.root.addResource('{folder}'); // 添加GET方法 folderResource.addMethod('GET', s3GetIntegration, { methodResponses: [ { statusCode: '200', responseParameters: { 'method.response.header.Content-Type': true }, }, ], requestParameters: { 'method.request.path.folder': true, // 移除对Content-Type头的强制要求 }, }); // 手动添加OPTIONS方法 this.addDocumentsOptionsEndpoint(folderResource); }
额外注意事项
- 确保S3存储桶的CORS策略允许对应来源、方法和头,示例策略:
{ "CORSRules": [ { "AllowedOrigins": ["*"], "AllowedMethods": ["GET"], "AllowedHeaders": ["*"], "MaxAgeSeconds": 3000 } ] }
- 部署修改后的CDK栈后,重新测试OPTIONS请求,确认返回200状态码及正确的CORS响应头。
内容的提问来源于stack exchange,提问作者jedi
相关产品推荐
相关产品推荐

