2

我正在尝试从 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

4 回答 4

9

更新 自撰写本文以来,lambda 已更新调用签名,现在通过event, context, callback.

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

还应该添加 API 网关代理和集成实现,这整个线程已经过时了。如果您将 API Gateway 与 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 函数,则该方法返回响应正文如下: 如果错误为空,则将响应正文设置为结果的字符串表示形式。这类似于 context.succeed()。 如果错误不为空,则将响应正文设置为错误。 如果使用类型为 error 的单个参数调用该函数,则错误值将填充到响应正文中。 http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html

这意味着无论您使用失败/成功或完成的组合都没有关系,行为完全相同。

API 网关和响应码映射

我已经测试了来自 Lambda 的响应处理与 API Gateway 中的响应代码映射相结合的每一种可能的组合。

这些测试的结论是“Lambda Error RegExp”仅针对 Lambda error 执行,即:您必须调用context.done(error);orcontext.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 属性中,我现在可以安全地.*"BadRequest".*在 API Gateway 响应映射中使用 grep for。

这是一个非常有效的 hack,它可以解决 Lambda 和 API Gateway 的两个奇怪的怪癖:

  1. 为什么 Lambda 坚持包装错误而不是按原样返回?
  2. 为什么 API Gateway 不允许我们在 Lambda 结果中进行 grep,只有错误?

我正在就这两种相当奇怪的行为向亚马逊开立支持案例。

于 2015-11-04T12:50:50.520 回答
3

您不必使用 context.fail,使用成功但发送不同的 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);

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

于 2015-10-07T09:47:20.157 回答
2

您应该替换使用context.failwithcontext.donecontext.fail仅用于非常严重的Lambda function故障,因为它不允许多个输出参数。Integration Response能够通过对传递给它的第一个参数执行正则表达式来匹配映射模板,context.done还将 HTTP 状态代码映射到响应。您不能直接从中传递此响应状态代码,Lambda因为它是API Gateway Integration Response抽象 HTTP 协议的角色。

请参阅以下内容:

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

Integration Response面板这个设置:

API Gateway 集成响应错误映射

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

于 2015-10-07T00:46:55.120 回答
-1

对于那些在这个问题上尝试了一切但无法完成这项工作的人(比如我),请查看这篇文章的 thedevkit 评论(节省了我的一天):

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

在下面完全复制它:

我自己也遇到过这个问题,我相信换行符是罪魁祸首。

foo.* 将匹配出现的“foo”,后跟除换行符以外的任何字符。通常这是通过添加'/s'标志来解决的,即“foo.*/s”,但 Lambda 错误正则表达式似乎不尊重这一点。

作为替代方案,您可以使用类似: foo(.|\n)*

于 2016-02-17T17:42:37.773 回答