AWS Lambda经HTTP API Gateway响应时无法绕过CORS错误
问题:API Gateway + Lambda + MySQL 架构下前端调用遇CORS错误,Postman正常
架构流程
网站调用API Gateway → 触发Lambda → 从MySQL表查询数据 → 返回至网站展示
问题现象
- Postman调用API可正常获取数据
- 前端JavaScript调用时持续触发CORS错误,控制台提示:
Access to XMLHttpRequest at 'https://nnebmzru3e.execute-api.us-east-2.amazonaws.com/proxy+' from origin 'xxx' 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. - CloudWatch日志无错误记录,且能看到MySQL查询返回的数据,怀疑并非单纯CORS配置问题,Lambda可能存在隐性异常
前端调用代码
const Http = new XMLHttpRequest(); const url = 'https://nnebmzru3e.execute-api.us-east-2.amazonaws.com/proxy+'; Http.open("OPTIONS", url); Http.setRequestHeader('Access-Control-Allow-Origin', '*') Http.send(); console.log(Http.responseText) Http.onreadystatechange = (e) => { console.log(Http.responseText) }
Lambda代码
const mysql = require("mysql"); exports.handler = (event, context, callback) => { console.log(event); const connection = mysql.createConnection({ host: process.env.RDS_HOSTNAME, user: process.env.RDS_USERNAME, password: process.env.RDS_PASSWORD, port: process.env.RDS_PORT, }); connection.query( "SELECT * FROM pickemss.pickems where Week = 1", function (error, results, fields) { if (error) { console.log("ERROR DESTROYING CONNECTION"); connection.end(); throw error; } else { console.log("CONNECTED"); connection.end(function (err) { callback(err, formatResponse(results)); }); } } ); }; var formatResponse = function (body) { console.log("Formatting response"); var response = { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token", "Access-Control-Allow-Methods": "*", }, }; response.body = JSON.stringify(body); console.log(response.body); return response; };
已尝试操作
- 切换其他路由使用GET请求,问题依旧
解决方案
1. 修正前端请求的错误操作
- 你当前手动发送
OPTIONS请求,还错误地在请求头中设置Access-Control-Allow-Origin——这个头是服务端响应头,不需要前端手动设置,浏览器会自动发送预检OPTIONS请求。 - 正确的前端GET请求代码:
const Http = new XMLHttpRequest(); const url = 'https://nnebmzru3e.execute-api.us-east-2.amazonaws.com/proxy+'; Http.open("GET", url); Http.onreadystatechange = (e) => { if (Http.readyState === 4 && Http.status === 200) { console.log(Http.responseText); } }; Http.send();
2. 让Lambda正确处理预检OPTIONS请求
当前Lambda直接执行数据库查询,如果是OPTIONS预检请求进来,会触发不必要的数据库调用,甚至可能因为参数不匹配出现隐性错误。在Lambda开头添加预检请求处理逻辑:
exports.handler = (event, context, callback) => { // 直接返回CORS响应处理预检OPTIONS请求 if (event.httpMethod === 'OPTIONS') { callback(null, formatResponse({})); return; } // 原有MySQL查询逻辑不变 console.log(event); const connection = mysql.createConnection({ host: process.env.RDS_HOSTNAME, user: process.env.RDS_USERNAME, password: process.env.RDS_PASSWORD, port: process.env.RDS_PORT, }); // ... 剩余逻辑保持原样 };
3. 修复Lambda错误处理逻辑
当前Lambda捕获到数据库错误时直接throw error,会导致返回500错误且不带CORS响应头,浏览器因此触发CORS错误。修改错误处理:
if (error) { console.log("ERROR DESTROYING CONNECTION"); connection.end(); // 返回带CORS头的错误响应 callback(null, { statusCode: 500, headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token", "Access-Control-Allow-Methods": "*", }, body: JSON.stringify({ error: error.message }) }); }
4. 检查API Gateway配置
- 确认对应资源已开启CORS,配置的
Access-Control-Allow-Origin为*,允许的方法包含GET、OPTIONS - 检查API Gateway集成配置,确保没有覆盖Lambda返回的响应头
- 确认阶段部署是最新版本,避免配置未生效
内容的提问来源于stack exchange,提问作者bryane92
相关产品推荐
相关产品推荐

