【问题标题】:AWS API gateways CORS error when reading from post body从帖子正文读取时,AWS API 网关 CORS 错误
【发布时间】: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':'*' 吗?
  • 试过了,还是一样

标签: amazon-web-services cors aws-api-gateway


【解决方案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,如您的回答中所述。目前我只需要它来工作,我不需要担心安全性。
    猜你喜欢
    • 2020-05-04
    • 2019-12-30
    • 2021-08-26
    • 1970-01-01
    • 2019-05-10
    • 2020-05-28
    • 2018-03-01
    • 2020-01-21
    • 1970-01-01
    相关资源
    最近更新 更多