【问题标题】:How to inject a header from the errormessage如何从错误消息中注入标头
【发布时间】:2017-01-26 04:08:39
【问题描述】:

我一直在尝试为错误响应状态(并且失败)注入自定义标头。

我使用了一个非常简单的 lambda

exports.handler = (event, context, callback) => {
   // TODO implement

   //callback(null, 'Hello from Lambda');

   var error = {
       name:"error", 
       message:"I am a failure",
       statusCode: 400
   };

   error["x-test"] = 'foo';

   callback(JSON.stringify(error), null);
};

在api网关中,我做了以下操作:

设置 CORS 以包含 x-test 响应模板 = "$input.path('$.errorMessage')" 要包含的响应参数:

method.response.header.x-test = integration.response.body.x-test

另外,我有一个使用 '.*statusCode.*?400.*' 映射的 statusCode

结果是空的。

所以我决定退后一步,看看如果我这样做会发生什么:

method.response.header.x-test = integration.response.body

我发现我得到了errorMessage的字符串化响应。

{"x-test":"{\"errorMessage\":\"{\\\"name\\\":\\\"error\\\",\\\"message\\\":\\\"I am a failure\\\",\\\"statusCode\\\":400,\\\"x-test\\\":\\\"foo\\\"}\"}"}

所以我决定通过执行以下操作更改响应模板以将其强制为 json:

响应模板 = "$util.parseJson($input.path('$.errorMessage'))"

我仍然得到字符串化的响应:

{"x-test":"{\"errorMessage\":\"{\\\"name\\\":\\\"error\\\",\\\"message\\\":\\\"I am a failure\\\",\\\"statusCode\\\":400,\\\"x-test\\\":\\\"foo\\\"}\"}"}

我的猜测是它并没有按预期进行转换,而只是用于最终输出。

那么你将如何获取一个值并将其塞入标题中?

谢谢, 凯莉

【问题讨论】:

    标签: aws-lambda aws-api-gateway


    【解决方案1】:

    我认为这更多是关于 Lambda 和 APIGateway 所施加的限制的设计选择。我会尽力把我的想法走一遍。

    首先,在 Lambda 中,callback(error, result) 函数可以将错误 string 作为第一个参数,也可以将 object 作为结果响应。如果您想传递一个简单的错误消息,您绝对可以这样做。但是,在您的情况下,当您尝试传递整个错误对象时,选择第二个选项显然是更好的解决方案(与将对象字符串化并将其再次解析为对象相反)。因此,您的 Lambda 函数的最后一行应该是:

    callback(null, error);

    是的,在这种情况下,如果您在 Lambda 中测试您的函数,输出结果将不再是红色并将其标记为错误,但这并不重要,因为您可以在 APIGateway 中格式化您的标头和响应。

    现在您需要在 APIGateway 中进行设置,您需要在其中使用 Lambda 传递的对象。

    使用方法执行接口来配置headers其实还是比较简单的。

    • 方法响应 中,您需要为特定状态代码添加要包含在响应中的标头,在您的情况下是 x-test。 (如果您希望 API 返回不同的状态码,您也可以在此面板中进行配置。)

    • 然后转到Integration Response,在相同的状态码下,您将看到添加的标头可用。根据来自 AWS 的 this 文档,您可以使用 integration.response.body.JSONPath_EXPRESSION 分配标头值(这是您应该在 Lambda 中返回对象而不是字符串的另一个原因,因为现阶段没有正式的 API 可以从字符串中解析对象)。这一次,当您的 Lambda 传递一个对象时,x-test 标头的值是:

    integration.response.body['x-test']

    • 现在您的 API 应该包含正确的标头。

    注意为了在 APIGateway 中设置不同的状态码,您应该在响应正文中留下一些可区分的数据字段(您的 statusCode: 400 应该可以正常工作),这样您就可以使用 RegEx 将这些字段与特定状态代码匹配。

    所以...以上不适用于成功消息。我在谈论错误处理设计模式时发现了这个blog。显然他们建议只在出现错误时映射状态代码,在这种情况下不应该传递任何正文(只有 errorMessage),因为浏览器无论如何都不关心状态代码的响应正文而不是 200。

    我想毕竟不可能同时自定义状态码和标头,而 Lambda 将对象传递给 APIGateway?

    【讨论】:

    • 我正和你走同样的路callback(null, error); 1。谢谢! 2. 我真的在努力确定问题/如果有的话,可以制定方向(并发症等......) 3. 再次感谢你 :)
    • 因此,如果我一直尝试使其成功(通过传递错误对象),似乎会出现问题。我似乎无法映射 400 以上。从我读到的 lambda 正则表达式将集成响应绑定到响应仅适用于 errorMessage 属性。有没有另一种方法来处理成功声明?
    • 您可以对错误执行此操作,但您将被限制为在回调中仅发送标头值作为字符串,然后使用“integration.response.body.errorMessage”进行映射。请参阅rpgreen.wordpress.com/2016/01/04/… 中的第二个示例
    • @KellyTheDev 我认为您是对的,我想结论是如果您将对象从 Lambda 传递到 APIGateway,则无法自定义状态代码(但您可以自定义标头)。另一方面,如果您传递错误消息,您可以自定义状态代码(标题不可能)。
    【解决方案2】:

    这是因为您正在对来自 Lambda 函数的错误对象进行字符串化。 API Gateway 尝试解析 JSON-Path 表达式,但无法评估字符串中的“x-test”。如果你返回一个对象而不是一个字符串,这应该可以工作。

    您可能需要考虑使用proxy integrations,它允许您直接从您的 Lambda 函数控制标头和状态。

    更新:我已经写了一篇关于这个主题的博客文章,其中包含示例代码@https://rpgreen.wordpress.com/2017/01/25/how-to-send-response-headers-for-aws-lambda-function-exceptions-in-api-gateway/

    【讨论】:

    • 嗨 Ryan,看起来代理是通配符。有办法限制吗?
    • 目前没有,但您可以将代理路径与静态父/子资源结合起来
    • 感谢瑞恩的所有帮助。似乎这是唯一的选择。虽然我确实了解它背后的设计。很遗憾,它被锁定为不允许使用错误消息转换标头。 AWS 为您提供了所有这些灵活性,然后他们决定不让这成为一种选择。之所以会很棒,是因为我们想为整个事务或请求/响应流输出一个唯一标识符,这与 aws 类似,但跨越了我们的链式微服务请求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 2018-10-02
    相关资源
    最近更新 更多