React本地客户端调用AWS Lambda遇CORS问题,求解决方案
问题背景
从http://localhost:3000的React客户端调用自行开发的AWS Lambda函数时,浏览器报CORS错误:
从源 'http://localhost:3000' 获取资源时被CORS策略阻止:请求的资源上不存在 'Access-Control-Allow-Origin' 头。若不需要透明响应,可将请求模式设置为 'no-cors' 以禁用CORS。
但使用Postman请求时能正常看到所有CORS响应头,Lambda已配置如下响应头:
return { 'statusCode': 200, 'body': json.dumps(result_object), 'headers': { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Vary': 'Origin', 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,Access-Control-Allow-Origin,Access-Control-Allow-Methods', } }
响应头的冗余问题
你的响应头配置有两处冗余,但不是报错的直接原因:
Access-Control-Allow-Headers里包含了Access-Control-Allow-Origin和Access-Control-Allow-Methods,这两个是响应头,不是客户端会发送的请求头,完全不需要列在这里,建议删除。- 当
Access-Control-Allow-Origin设为*时,Vary: Origin没有意义,可以去掉。
核心解决方案(按优先级排序)
1. 必须处理OPTIONS预检请求
浏览器发起非简单请求(比如POST发送JSON、带自定义请求头)时,会先发送OPTIONS预检请求,确认服务器允许跨域。Postman不会触发这个预检,所以能正常请求,但浏览器会。你的Lambda目前只在业务请求(GET/POST)里返回CORS头,OPTIONS请求没处理,导致浏览器拿不到CORS头报错。
修改Lambda代码,优先处理OPTIONS请求:
import json def lambda_handler(event, context): # 先处理OPTIONS预检请求 if event['httpMethod'] == 'OPTIONS': return { 'statusCode': 200, 'headers': { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token' }, 'body': json.dumps({}) } # 下面是你的业务逻辑代码 result_object = {"key": "value"} return { 'statusCode': 200, 'body': json.dumps(result_object), 'headers': { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token' } }
2. 检查API Gateway的CORS配置(如果用它触发Lambda)
如果你的Lambda是通过AWS API Gateway暴露的,仅在Lambda里配置CORS头不够,必须在API Gateway里开启CORS:
- 登录API Gateway控制台,选择你的API,找到对应的资源路径
- 点击「Enable CORS」按钮,配置允许的源(可填
http://localhost:3000或*)、允许的方法(GET,POST,OPTIONS)、允许的请求头 - 配置完成后,必须重新部署API才能生效
- 注意:API Gateway的CORS配置会覆盖Lambda返回的部分响应头,建议保持两边配置一致,或者直接依赖API Gateway的CORS设置。
3. 本地开发临时绕过方案(仅测试用)
如果只是本地开发调试,可以用以下两种方式绕过CORS检查:
- React代理:在项目的
package.json里添加代理配置,将请求转发到Lambda/API Gateway地址:
之后React里直接请求"proxy": "https://your-api-gateway-url.execute-api.region.amazonaws.com/prod"/your-endpoint即可,代理会自动转发,绕过浏览器CORS检查。 - 关闭浏览器CORS安全检查:
- Windows:
chrome.exe --disable-web-security --user-data-dir="C:/ChromeDevSession" - Mac:
open -n -a Google\ Chrome --args --disable-web-security --user-data-dir="/tmp/chrome_dev"
注意:此方式仅限本地测试,不要用于日常浏览。
- Windows:
4. 确认请求是否为简单请求
如果你的请求是简单请求(比如GET、POST且Content-Type为application/x-www-form-urlencoded/multipart/form-data/text/plain),浏览器不会发送OPTIONS预检。如果你的请求不符合这个条件,就必须按方案1处理OPTIONS请求。
内容的提问来源于stack exchange,提问作者BergP

