从帖子正文读取时,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 网关 CORS [关闭]

如何使用 AWS API 网关和 Lambda 通过 CORS?

使用 AWS CDK 为 AWS API 网关启用 CORS

具有自定义授权者和 CORS 间歇性 200 然后 403 然后 200 的 AWS API 网关 ...奇怪

从托管在 S3 存储桶上的站点访问 AWS API 时出现 CORS 问题 [关闭]