从帖子正文读取时,AWS API 网关 CORS 错误
Posted
技术标签:
【中文标题】从帖子正文读取时,AWS API 网关 CORS 错误【英文标题】:AWS API gateways CORS error when reading from post body 【发布时间】:2021-06-01 15:32:35 【问题描述】:我有一个用 React JS 编写的应用程序,在 localhost 上运行,它对 AWS 中的 API Gateway 进行 API 调用。 API Gateway 将请求转发到 lambda 函数,该函数返回响应。我在 AWS 端启用了 CORS。 此刻,每当我单击应用程序中的“请求”按钮时,我都会收到来自网关的响应。这是我当前的python代码:
import json
def lambda_handler(event, context):
response =
response['result'] = "Success"
response['message'] = "Updated successfully!"
return
'headers':
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
,
"body": json.dumps(response)
这是请求的正文:
"ID": "1101",
"RequestDate": "2021-02-28"
这很好用。我从此响应中获得了“消息”值,并且可以毫无问题地显示它。
接下来我想显示包含来自请求的一些数据的信息。例如,我想从请求中获取RequestDate
,而不是Updated successfully
,并返回Updated successfully on 2021-02-28
。
我添加了这两行:
def lambda_handler(event, context):
body = json.loads(event['body'])
request_date = body['RequestDate']
response =
response['result'] = "Success"
response['message'] = "Updated successfully!"
return
'headers':
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
,
"body": json.dumps(response)
在我进行此更改后,我会在我的应用程序中获得以下代码:
Access to fetch at url from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
只有当我添加 request_date = body['RequestDate']
时才会发生这种情况。我试着只归还尸体,它也能正常工作。
在我的 react js 应用程序中,我还添加了以下标头:
async callAPI(url, method, data)
let result = await fetch(url,
method: method,
headers:
'Accept': 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
,
body: JSON.stringify(
data
)
)
return result.json().then(body => this.notify(body['message']));
我尝试启用 CORS 并再次部署资源,但无济于事。我已将 Access-Control-Allow-Origin
添加到 AWS 中允许的标头中。正如我所提到的,在添加一行之前,它与 post 方法一起工作得很好。这里可能出了什么问题,我该如何补救?
编辑: 还有一件事。我仅从在 localhost 上运行的应用程序中收到此错误。卷曲或使用任何 REST 客户端都可以正常工作。
编辑2: 添加获取代码
【问题讨论】:
你可以尝试从 lambda 返回'Access-Control-Allow-Headers':'*'
吗?
试过了,还是一样
【参考方案1】:
在 lambda 的响应中添加 statusCode
return
'statusCode': 200,
'headers':
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
,
'body': json.dumps(response)
如果您的 lambda 有任何错误,它将返回没有任何 CORS 标头的默认 5XX 响应,在这种情况下,浏览器将抱怨找不到 cors 标头。
您可以在try
块和except
块中添加您当前的代码,您可以打印错误并返回一些默认响应,如下所示
return
'statusCode': 500,
'headers':
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
,
'body': json.dumps('message':'Unexpected error')
在您的 lambda 中添加一些日志语句并检查 Lambda 代理设置的 api 网关配置。
请务必检查您的 api 网关日志和 lambda 函数日志,了解有关错误的更多详细信息。
【讨论】:
【参考方案2】:这是我的服务器上的内容,它运行良好。在前端使用 fetch。
服务器代码:
import json
result = "hello": "world"
return
'statusCode': 200,
'headers':
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": "*"
,
'body': json.dumps(result)
使用 ES6 的前端代码
url = "Your url"
path = "Your desired path"
data = "hello": "world"
const response = await fetch(url + path,
method: "POST",
cache: "no-cache",
mode: "cors",
body: JSON.stringify(data),
);
【讨论】:
您发布的内容也对我有用。当我尝试从服务器收到的请求中读取任何数据时,就会发生错误。添加body = json.loads(event['body']) request_date = body['RequestDate']
会破坏它。您是否尝试过从请求中获取任何数据并显示它?
我想您的获取请求中没有包含“RequestDate”。你能分享你的获取请求代码吗?此外,您会收到 CORS 错误,因为您的函数无法执行并返回错误消息。将其放在 try: except:
块中以防止它发生。
我添加了获取代码。包括“请求日期”。一旦我在服务器端注释掉“request_date = body['RequestDate']”,我就会停止收到错误并获得正确的响应,但是我无法将请求中的日期添加到响应中。【参考方案3】:
在 Lambda 中设置 CORS 取决于您设置 API Gateway 的方式。 API Gateway 有多种模式 [REST、HTTP、WebSocket]。在 REST 的情况下,API Gateway 在传递给 Lambda 之前对传入请求进行一些预处理,例如参数验证。 HTTP Proxy 就是这样,传递给 Lambda,Websockets 不适合这个讨论。
我假设这是因为您在标准配置中使用 API Gateway 而您没有enabled CORS on API Gateway。您在上面提供的代码将适用于为 HTTP 配置的 API 网关。
如果您使用的是CDK 或 CloudFormation,那么您必须在那里配置 CORS,否则最简单的是使用控制台。
在 AWS 控制台中转到您的 API,选择资源,选择您的方法或服务,从操作菜单中启用 CORS。然后发布您更新的 API。
Here 是 AWS 文档的链接,其中概述了如何操作。
一些建议,当通过浏览器测试端点时,最好不要使用 Localhost 或 127.0.0.1 它会产生意想不到的后果。 Edit your hosts file 给自己一个域名,然后用那个域名代替。
CORS 的存在是为了阻止Cross Site Scripting or Cross Site Origin Attacks。尽量不要使用*,测试肯定,但生产没有。如果您在 S3 上有代码,并且在 API Gateway 上有您的 REST 服务,您可以使用相同的 Origin 与 CloudFront 连接,并让 CloudFront 知道基于 URL(例如 /API)转发到 APIGateway 和另一个到 S3。因此,一切都具有相同的域。
【讨论】:
我已启用 CORS,如您的回答中所述。目前我只需要它来工作,我不需要担心安全性。以上是关于从帖子正文读取时,AWS API 网关 CORS 错误的主要内容,如果未能解决你的问题,请参考以下文章
Cors - 如何处理需要自定义标头的预检选项请求? (AWS:使用 vpc 端点的私有 API 网关)
如何使用 AWS API 网关和 Lambda 通过 CORS?
使用 AWS CDK 为 AWS API 网关启用 CORS