AWS Amplify 在任何 Lambda 失败时返回一般网络错误

Sas*_*sha 5 amazon-web-services reactjs aws-lambda serverless-framework aws-amplify

我正在构建一个应用程序,通过在 Web (React) 前端使用的 AWS Amplify 与 AWS 上的无服务器 API (API Gateway/Lambda) 连接。

当请求成功时,一切都会正常(我想肯定是这样)。不存在 CORS 问题或任何问题。但是,如果我尝试返回“失败”响应,我的前端不会收到该响应。它收到一个通用Network Error信息,但不包含有关所发生情况的信息,并且控制台会记录失败。

我认为代码会更有意义。我使用如下代码向 API 请求(在其他地方配置的 Amplify):

import { API } from 'aws-amplify';
...
API.get('apiName', path, options)
  .then(response => {
     // Whatever
  })
  .catch(err => {
     // Whatever
  })
Run Code Online (Sandbox Code Playgroud)

在 Lambda 中,我返回(Cloudwatch 验证了这一点,因为我在运行之前记录了callback(null, responseObject))一个完整的响应对象,如下所示:

{
    "statusCode": 200,
    "headers": {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": true
    },
    "body": "{ /* whatever */ }"
}
Run Code Online (Sandbox Code Playgroud)

或这个:

{
    "statusCode": 500,
    "headers": {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": true
    },
    "body": "{ /* error here */ }"
}
Run Code Online (Sandbox Code Playgroud)

在这种200情况下,响应完美地到达我的前端(在函数中显示.thenresponse)。在500(或一般错误)情况下,.catch调用,并且err对象不是我放入响应正文中的对象,而是一个Network Error没有相关信息(或状态代码)的泛型:

Error: Network Error
    at createError (createError.js:16)
    at XMLHttpRequest.handleError (xhr.js:87)
Run Code Online (Sandbox Code Playgroud)

澄清一下,简单地将 200更改statusCode为 400 都意味着请求在前端被捕获(好),并且错误没有我从 Lambda 返回的任何信息(坏)。

控制台还记录错误:

DELETE https://abcdefg.execute-api.us-west-2.amazonaws.com/development/my-endpoint 403 ()

Failed to load https://abcdefg.execute-api.us-west-2.amazonaws.com/development/my-endpoint: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 403.
Run Code Online (Sandbox Code Playgroud)

它还记录与 CORS 失败相关的内容,这对我来说毫无意义,因为我遵循与成功案例完全相同的模式,只是具有更高statusCode.

Cross-Origin Read Blocking (CORB) blocked cross-origin response https://abcdefg.execute-api.us-west-2.amazonaws.com/development/my-endpoint with MIME type application/json.
XHR failed loading: DELETE "https://abcdefg.execute-api.us-west-2.amazonaws.com/development/my-endpoint".
Run Code Online (Sandbox Code Playgroud)

知道这是怎么回事吗?无法访问前端的真实信息错误确实令人沮丧。如果有任何其他信息有助于解决此问题,请告诉我。

编辑——根据下面@Michael的反馈,我检查了我的应用程序是否正在使用lambda或lambda-proxy,事实上,它正在使用lambda-proxy,据我所知,它应该产生这种行为。

这是我的 serverless.yml 文件中的一些代码,

functions:
  projectsGetAll:
    handler: handlers/projects/getAll.handler
    events:
      - http:
          path: projects
          method: get
          cors: true
          authorizer: aws_iam
Run Code Online (Sandbox Code Playgroud)

以下是来自 AWS API Gateway 的这些端点之一的屏幕截图(端点被涂白):

在此输入图像描述

我想确认这是 lambda-proxy 的意外行为。是否可能有一些设置把事情搞砸了?

Sas*_*sha 3

弄清楚了!返回的错误对象(一个通用的500NetworkError 包含我构建的错误,在response键下)。

因此,如果我登录error.response,我会得到完全构造的错误对象,带有它自己的消息和statusCode,即使错误对象本身具有codeof500和消息Error: Network Error,并且错误捕获过程似乎会抛出不准确的错误日志(CORB 的东西)安慰。

诡异的。不确定这是否是预期的 Lambda 行为,或者 Amplify 的行为,或者我做错了什么,但如果其他人遇到这个问题,我希望这会有所帮助!

编辑-显然这是预期的放大行为,我在文档中错过了。

但我发现了另一个似乎是错误的问题。仅当我未headers在请求选项中指定时,才会显示此响应键。换句话说,这个请求返回一个error带有response键的:

API.get('my-api', '/path')
Run Code Online (Sandbox Code Playgroud)

但这会在没有密钥的情况下返回错误:

API.get('my-api', '/path', { headers: { 'Content-Type': 'application/json' } })
Run Code Online (Sandbox Code Playgroud)

很奇怪,但对我来说是真的。即使其他选项也很好,但 headers 选项似乎把事情搞砸了(并且仅适用于错误响应)。