使用AWS Lambda(SAM)与React时遭遇CORS错误求助
问题描述
开发React应用时,通过axios向AWS Lambda发送POST请求,使用SAM创建Lambda API与函数,按官方文档配置后,Postman测试API功能正常,但React本地运行及部署到Lightsail后均出现CORS错误,调试24小时未解决,需定位问题。
template.yml 配置
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > openai-site-parser-and-summary Sample SAM Template for openai-site-parser-and-summary Globals: Api: Cors: AllowMethods: "'GET,POST,OPTIONS'" AllowOrigin: "'*'" AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" Function: Timeout: 120 LoggingConfig: LogFormat: JSON Resources: MyApiGateway: Type: AWS::Serverless::Api Properties: StageName: Prod Cors: AllowHeaders: "'*'" AllowOrigin: "'*'" AllowCredentials: "'*'" AllowMethods: "'*'" OpenAiSiteParserFunction: Type: AWS::Serverless::Function Properties: Environment: Variables: MY_API_KEY: "MY_API-KEY" CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.10 Architectures: - x86_64 Events: EndpointEvent: Type: Api Properties: RestApiId: !Ref MyApiGateway Path: /parse Method: post MyApiGatewayDeployment: Type: AWS::ApiGateway::Deployment DependsOn: - MyApiGateway - OpenAiSiteParserFunction Properties: RestApiId: !Ref MyApiGateway MyApiKey: Type: AWS::ApiGateway::ApiKey Properties: Enabled: true MyUsagePlan: Type: AWS::ApiGateway::UsagePlan DependsOn: - MyApiGatewayDeployment Properties: ApiStages: - ApiId: !Ref MyApiGateway Stage: Prod Description: Usage plan for My API UsagePlanName: MyUsagePlan Throttle: BurstLimit: 100 RateLimit: 50 Quota: Limit: 10000 Period: MONTH MyUsagePlanKey: Type: AWS::ApiGateway::UsagePlanKey Properties: KeyId: !Ref MyApiKey KeyType: API_KEY UsagePlanId: !Ref MyUsagePlan Outputs: OpenAiSiteParserApi: Description: "API Gateway endpoint URL for Prod stage" Value: !Sub "https://${MyApiGateway}.execute-api.${AWS::Region}.amazonaws.com/Prod/parse/" OpenAiSiteParserFunction: Description: "Lambda Function ARN" Value: !GetAtt OpenAiSiteParserFunction.Arn OpenAiSiteParserFunctionIamRole: Description: "Implicit IAM Role created for function" Value: !GetAtt OpenAiSiteParserFunctionRole.Arn
Lambda函数代码(app.py)
import json import requests from bs4 import BeautifulSoup from urllib.parse import urljoin, urlparse from openai import OpenAI def lambda_handler(event, context): # 业务逻辑... return { "statusCode": 200, "headers": { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "*", "Access-Control-Allow-Headers": "*", "Access-Control-Allow-Credentials" : True }, "body": json.dumps({ "summary": final_summary }) }
React端错误信息
Access to XMLHttpRequest at 'https://1234567890.execute-api.us-east-2.amazonaws.com/Prod/parse/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
已尝试的解决方法
尝试1:修改Lambda返回头
调整Lambda的响应头,简化为仅保留Access-Control-Allow-Origin:
def lambda_handler(event, context): # 业务逻辑... return { "statusCode": 200, "headers": { "Access-Control-Allow-Origin": "*" }, "body": json.dumps({ "summary": final_summary }) }
查看Chrome Network面板发现:预检请求响应头包含CORS允许字段,但POST请求返回InternalServerErrorException。
问题定位与解决方案
核心问题分析
- CORS配置冲突:SAM模板中
Globals.Api.Cors与MyApiGateway.Properties.Cors重复配置,且AllowCredentials取值错误(不能设为'*',仅支持true/false)。 - API密钥验证未处理:配置了API密钥和使用计划,但React请求未携带
x-api-key头,导致请求被拦截返回500错误,浏览器因错误响应无CORS头,触发CORS报错。 - Lambda错误无CORS头:Lambda抛出内部异常时,默认不返回CORS头,掩盖真实错误,表现为CORS问题。
分步解决
1. 修复SAM模板CORS配置
删除重复的Globals.Api.Cors段,统一在MyApiGateway中正确配置:
Resources: MyApiGateway: Type: AWS::Serverless::Api Properties: StageName: Prod Cors: AllowHeaders: "'*'" AllowOrigin: "'*'" AllowCredentials: false # 无需凭证时设为false,需要则设为true AllowMethods: "'GET,POST,OPTIONS'"
2. 处理API密钥验证
- 若无需API密钥:删除
MyApiKey、MyUsagePlan、MyUsagePlanKey资源,在API方法设置中关闭API密钥要求。 - 若保留API密钥:在React请求中添加
x-api-key头:
axios.post('https://你的API地址/Prod/parse/', 请求数据, { headers: { 'x-api-key': '你的API密钥' } })
3. 确保Lambda异常时返回CORS头
修改Lambda代码,添加异常捕获,无论成功失败都返回CORS头:
import json import requests from bs4 import BeautifulSoup from urllib.parse import urljoin, urlparse from openai import OpenAI def lambda_handler(event, context): try: # 业务逻辑... return { "statusCode": 200, "headers": { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET,POST,OPTIONS", "Access-Control-Allow-Headers": "*" }, "body": json.dumps({ "summary": final_summary }) } except Exception as e: return { "statusCode": 500, "headers": { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET,POST,OPTIONS", "Access-Control-Allow-Headers": "*" }, "body": json.dumps({ "error": str(e) }) }
4. 重新部署SAM应用
执行命令更新配置:
sam build sam deploy --guided
内容的提问来源于stack exchange,提问作者Pythoner
相关产品推荐
相关产品推荐

