AWS Lambda与API Gateway HTTP API的CORS问题排查
使用AWS API Gateway HTTP API调用Lambda时的CORS错误排查
配置信息
API Gateway 配置
类型:HTTP API(非REST API)
CORS 设置
Access-Control-Allow-Origin: * Access-Control-Allow-Methods: OPTIONS, POST Access-Control-Allow-Headers: Content-Type
Lambda 函数代码
const AWS = require('aws-sdk'); const ses = new AWS.SES({ region: 'us-east-1' }); exports.handler = async (event) => { const headers = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', 'Access-Control-Max-Age': '3600', // 缓存1小时 }; if (event.httpMethod === 'OPTIONS') { return { statusCode: 200, headers: headers, body: '', }; } if (event.httpMethod === 'POST') { const { name, email, message } = JSON.parse(event.body); const params = { Destination: { ToAddresses: ['email'], // 替换为已验证的邮箱地址 }, Message: { Body: { Text: { Charset: 'UTF-8', Data: `Name: ${name}\nEmail: ${email}\nMessage: ${message}`, }, }, Subject: { Charset: 'UTF-8', Data: 'New Contact Form Submission', }, }, Source: 'xxx@gmail.com', // 替换为已验证的邮箱地址 }; try { await ses.sendEmail(params).promise(); return { statusCode: 200, headers: headers, body: JSON.stringify({ message: '消息发送成功!' }), }; } catch (error) { console.error(error); return { statusCode: 500, headers: headers, body: JSON.stringify({ message: '消息发送失败。' }), }; } } return { statusCode: 405, headers: headers, body: JSON.stringify({ message: '不允许的请求方法' }), }; };
问题现象
提交表单时持续收到CORS错误:
Access to fetch at 'https://cl4dhs3yg7.execute-api.us-east-1.amazonaws.com/dev/contact' from origin 'http://example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
已执行的排查步骤
- 确认Lambda函数在OPTIONS和POST响应中都包含CORS头部
- 验证API Gateway的CORS配置正确
- 修改配置后重新部署API
- 使用CURL测试预检请求和实际请求,但预检请求无输出
预检请求命令
curl -i -X OPTIONS https://cl4dhs3yg7.execute-api.us-east-1.amazonaws.com/dev/contact \ -H "Origin: http://example.com" \ -H "Access-Control-Request-Method: POST" \ -H "Access-Control-Request-Headers: Content-Type"
实际POST请求命令
curl -i -X POST https://cl4dhs3yg7.execute-api.us-east-1.amazonaws.com/dev/contact \ -H "Origin: http://example.com" \ -H "Content-Type: application/json" \ -d '{"name":"hari", "email":"hari987@gmail.com", "message":"test message"}'
补充信息
使用的是API Gateway HTTP API而非REST API;未配置特定参数映射。
问题原因及解决方案
可能的原因
- HTTP API的CORS配置未关联目标路由
HTTP API的CORS设置需要明确绑定到对应的路由(如/dev/contact),仅全局开启CORS但未关联目标路由时,预检请求无法触发正确的CORS响应。 - OPTIONS方法未正确配置到路由
若API Gateway的/dev/contact路由未添加OPTIONS方法,或该方法未指向Lambda函数,预检请求会被API Gateway直接拦截,无法触发Lambda返回CORS头部。 - 部署未生效
修改配置后未重新部署API,导致新的CORS设置未同步到生产环境。
解决方案
1. 绑定CORS配置到目标路由
- 进入AWS控制台的API Gateway,找到目标HTTP API
- 进入CORS设置页面,确认
/dev/contact已添加到关联路由列表;或直接在/dev/contact路由的单独配置中开启CORS
2. 确认OPTIONS方法的路由配置
- 检查
/dev/contact路由的方法列表,确保包含OPTIONS和POST两种方法 - 确认两种方法的集成目标均指向你的Lambda函数,避免OPTIONS请求被拦截
3. 优化Lambda的CORS头部(可选)
- 若生产环境不允许使用通配符
*,可将Access-Control-Allow-Origin设置为请求的Origin值,增强安全性:const origin = event.headers.origin || '*'; const headers = { 'Access-Control-Allow-Origin': origin, 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', 'Access-Control-Max-Age': '3600', };
4. 重新部署并验证
- 修改配置后,点击API Gateway中的部署按钮,推送更新到生产环境
- 重新执行CURL预检请求,确认响应包含
Access-Control-Allow-Origin等CORS头部,且状态码为200
5. 启用日志排查
- 开启API Gateway的访问日志,查看预检请求的流向:是否到达Lambda、Lambda返回的响应是否包含CORS头部,定位问题节点
内容的提问来源于stack exchange,提问作者Jayavaishnavi Chennam
相关产品推荐
相关产品推荐

