如何从AWS Lambda函数返回错误集合/对象并映射到AWS API Gateway响应代码

时间:2015-10-06 19:05:05

标签: http amazon-web-services aws-lambda http-response-codes aws-api-gateway

我正在尝试从AWS Lambda函数返回一个对象,而不是一个简单的字符串。

// ...
    context.fail({
        "email": "Email address is too short",
        "firstname": "First name is too short"
    });
// ...

我已经使用errorMessage来映射对状态代码的错误响应,这很棒:

// ...
    context.fail('That "username" has already been taken.');
// ...

我只是想尝试做一些AWS API Gateway无法承受的事情吗?

我还发现这篇文章有助于:Is there a way to change the http status codes returned by Amazon API Gateway?

4 个答案:

答案 0 :(得分:8)

<强>更新 自编写本文以来,lambda已更新了调用签名,现在通过了event, context, callback

您应该使用context.done(err, res)而不是致电callback(err, res)。请注意,context.done的情况仍然适用于回调模式。

还应该添加API网关代理和集成实现,这整个线程已经过时了。 如果您要将API网关与Lambda集成,我建议您阅读本文:http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html

原始回复如下

首先,让我们先澄清一些事情。

context.done()与context.fail()/ context.success

context.done(error, result);只不过是context.fail(error);context.success(response);的封套 Lambda文档明确指出,如果错误为非null,则忽略结果:

  

如果使用RequestResponse(同步)调用类型调用Lambda函数,则该方法返回响应正文,如下所示:   如果错误为null,则将响应主体设置为result的字符串表示形式。这类似于context.succeed()。   如果错误不为空,请将响应正文设置为错误。   如果使用类型为error的单个参数调用该函数,则将在响应正文中填充错误值。   http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html

这意味着无论您是使用失败/成功还是完成,行为都完全相同无关紧要。

API网关和响应代码映射

我已经测试了Lambda的每个可想到的响应处理组合以及API网关中的响应代码映射。

这些测试的结论是“Lambda Error RegExp”仅针对Lambda错误执行,即:您必须致电context.done(error);context.fail(error); RegExp实际触发。

现在,这提出了一个问题,因为已经注意到,Lambda会将您的错误记录在一个对象中,并在您提供的任何内容上调用toString()

{ errorMessage: yourError.toString() }

如果你提供了一个错误对象,你会得到这个:

{ errorMessage: "[object Object]" }

根本没有帮助。

到目前为止,我找到的唯一解决方法是致电

context.fail(JSON.stringify(error));

然后在我的客户端做:

var errorObject = JSON.parse(error.errorMessage);

它不是很优雅,但它有效。 作为我的错误的一部分,我有一个名为“代码”的属性。它可能看起来像这样:

{ 
    code: "BadRequest", 
    message: "Invalid argument: parameter name" 
}

当我对这个对象进行字符串化时,我得到了:

"{\"code\":\"BadRequest\",\"message\":\"Invalid argument: parameter name\"}"

Lambda会将此字符串粘贴在响应的errorMessage属性中,现在我可以安全地在API网关响应映射中grep .*"BadRequest".*

这是一个非常糟糕的工作,可以解决两个奇怪的Lambda和API网关怪癖:

  1. 为什么Lambda坚持包装错误而不是仅仅给予错误 它回来了吗?
  2. 为什么API网关不允许我们进行grep Lambda结果,只有错误?
  3. 我正准备与亚马逊就这两个相当奇怪的行为开启一个支持案例。

答案 1 :(得分:3)

您不必使用context.fail,使用success但发送不同的statusCode和errorMessage,这是我如何格式化输出的示例:

try {
    // Call the callable function with the defined array parameters
    // All the function called here will be catched if they throw exceptions
    result.data = callable_function.apply(this, params);
    result.statusCode = 200;
    result.operation = operation;
    result.errorMessage = ""
} catch (e) {
    result.data = [];
    result.statusCode = 500;
    result.errorMessage = e.toString();
    result.method = method;
    result.resource = resource;
}

// If everything went smooth, send back the result
// If context succeed is not called AWS Lambda will fire the function
// again because it is not successfully exited
context.succeed(result);

使用消费者逻辑处理不同的错误案例逻辑,不要忘记你为函数运行的时间付出代价......

答案 2 :(得分:2)

您应该将context.fail替换为context.done,并仅将context.fail用于非常严重的Lambda function失败,因为它不允许多个输出参数。 Integration Response能够通过对传递给context.done的第一个参数执行regex来匹配映射模板,这也将HTTP状态代码映射到响应。您无法直接从Lambda传递此响应状态代码,因为API Gateway Integration Response的角色是抽象HTTP协议。

请参阅以下内容:

context.done('Not Found:', <some object you can use in the model>);

Integration Response面板此设置:

API Gateway Integration Response Error mapping

您可以针对任何类型的错误复制类似的方法。您还应该创建错误模型并将其映射到您的回复。

答案 3 :(得分:-1)

对于那些试图解决这个问题并且无法完成这项工作的人(像我一样),请查看该帖子的devkit评论(保存我的一天):

https://forums.aws.amazon.com/thread.jspa?threadID=192918

完全在下面再现:

  

我自己也有这个问题,我相信换行   人物是罪魁祸首。

     

foo。*将匹配&#34; foo&#34;的出现次数。其次是任何字符   除了换行符。通常,这可以通过添加&#39; / s&#39;来解决。国旗,即   &#34; foo。* / s&#34;,但Lambda错误正则表达式似乎并不尊重这一点。

     

作为替代方案,您可以使用以下内容:foo(。| \ n)*