使用 AWS API Gateway 和 Java 处理错误响应状态代码/实体

Posted

技术标签:

【中文标题】使用 AWS API Gateway 和 Java 处理错误响应状态代码/实体【英文标题】:Handling error response status code/entity with AWS API Gateway and Java 【发布时间】:2016-05-10 10:15:43 【问题描述】:

我是 AWS API Gateway 的新手,我将它与 AWS Lambda (Java) 一起使用。 显然,更改响应状态代码(更改为 4xx、5xx 等)的唯一方法是返回一个必须与资源的集成响应部分中的 Lambda 错误正则表达式匹配的字符串,或者抛出一个也应该包含与正则表达式匹配的消息,对吗?

但是如果我只能返回一个字符串,我该如何为响应实体提供更多详细信息? 以下是我的 RESTful API 用于返回的内容以及相应的错误状态代码:


    "code": "123",
    "message": "Invalid email address",
    "path": "/email"

code 属性对调试或国际化 (i18n) 很有用,path 是要更正的字段。 有时我将它包装在一个“错误”JSON 对象中,有时我返回一个验证错误列表而不是只有 1 个错误,等等。我根据项目规范对其进行自定义。

如何使用 API Gateway 生成这样的响应实体? 谢谢。

编辑:感谢 kennbrodhagen 的建议,这就是我最终要做的事情: 1. 我将我的错误对象字符串化(使用 Jackson ObjectMapper) 2. 我抛出了一个RuntimeException 并带有字符串化错误作为消息 在集成响应中: 3. 我将我的错误的某些属性用于 Lambda 错误正则表达式 4. 我映射了这个模板

 "error": $input.path('$.errorMessage') 

那么API响应(如果发生错误)就变成了

 "error": "code": "123", ... 

目前非常基本,但比仅在响应中获取字符串要好。

【问题讨论】:

你能返回像 4XX 或 5XX 这样的 HTTP 状态吗?我正在为 Java 和 200 以外的状态代码而苦苦挣扎。如果您有时间,请在此处查看我的问题 ***.com/questions/45200322/…。谢谢! 【参考方案1】:

我知道您正在使用 Java,但我更熟悉 node,因此我更容易以这种方式进行原型设计。希望它会翻译过来没有太多麻烦。

这是我在 node.js 中创建的原型函数。目标是将 err 对象作为错误中的 JSON 响应正文返回。 status 属性将用于映射到相应的 HTTP 状态。

exports.handler = function(event, context) 
    var response = 
        status: 400,
        message: "Error details",
        path: "/x"
    

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

;

要使用 status 属性值映射到 HTTP 400,然后将整个结构作为 JSON 响应返回,请执行以下操作:

    在 Lambda 中,当您将错误传递给 context.done 或 context.fail 时,对其调用 JSON.stringify() 以将其转换为 JSON 字符串。由于您使用的是 Java,我假设您会找到一种不同的方法将错误转换为等效的 JSON 字符串。

    在 API Gateway 集成响应中,将映射设置为使用正则表达式,该表达式将匹配包含 JSON 格式的状态代码的属性。在下面的示例中,我使用 .*"status":400.* 来匹配 status 属性。请注意,我将代码作为数字发送,因此如果您想使用字符串,则必须在正则表达式中添加引号。另请注意,将 .* 放在正则表达式的开头和结尾很重要,这样它将匹配子字符串。

    在 API Gateway 集成响应中设置一个 application/json Content-Type 和一个如下所示的映射模板:

    $input.path('$.errorMessage')

Lambda 将您传递给 done/fail 的内容并在其上调用 toString()。然后,它将该字符串分配为它发送到 API Gateway 的 JSON 响应中的 errorMessage 属性的值。

接下来,API Gateway 将正则表达式应用于 errorMessage 属性的值。

最后,API Gateway 针对 Lambda 响应字符串执行您的映射模板。映射模板从 errorMessage 中提取值并将其呈现为响应正文。

要让 API Gateway 返回多个不同的状态结果,您需要为每个结果设置单独的集成响应映射。您可以将相同的模板复制/粘贴到每个模板中。

【讨论】:

你的回答启发了我,我会用我最终做的事情来编辑我的问题。希望 AWS 将来会提供一种不那么“肮脏”的方式;-) 我更新了我的回复以解决一些问题并添加更多细节。【参考方案2】:

显然,更改响应状态代码(更改为 4xx、5xx 等)的唯一方法是返回一个必须与资源的集成响应部分中的 Lambda 错误正则表达式匹配的字符串,或者抛出一个异常应该包含与正则表达式匹配的消息,对吗?

正确。

在目标响应中,您可以配置映射模板,这些模板可以访问来自 Lambda 的响应的任何其他部分以及上下文变量,这些内容在此处记录:http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html

因此您可以在“/email”下的 400 响应上设置映射模板


    "code": "123",
    "message": "Invalid email address",
    "path": "$context.resourcePath"

或者类似的东西。这将是为您的 Lambda 错误 -> 状态代码映射设置自定义响应正文的唯一方法。

【讨论】:

嗯,我的“path”属性不是资源路径,它是无效字段,如果密码对资源“/register”的调用无效,它可能是“/password”例如。如果您熟悉它,则与 Spring MVC 表单验证相同,它们使用“路径”一词来定义表单中的哪些字段不正确。此外,相同的错误状态代码可能会链接到 JSON 实体中的不同“代码”值。所以这些属性必须以某种方式从 Lambda 处理程序传递到 API Gateway...

以上是关于使用 AWS API Gateway 和 Java 处理错误响应状态代码/实体的主要内容,如果未能解决你的问题,请参考以下文章

Google Cloud Api Gateway 是不是提供请求签名和验证 sdk,例如使用 Signature 4 签署 AWS API Gateway 请求?

AWS API Gateway:如何实现持续交付?

AWS Lambda 和 Gateway API - 使用 cloudformation 的蓝/绿部署

连接 AWS Api Gateway 和私有 ALB

AWS Lambda 和 API Gateway 响应集成问题

AWS API Gateway + AWS Lambda 中的 CORS