如何在 AWS API Gateway 映射模板中设置对象键值

Tee*_*muK 9 amazon-web-services aws-api-gateway

我最近熟悉了 AWS 最奇特的 API 网关映射模板语法,这对我来说并没有多大意义。

我试图阅读文档,至少说https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#util-template-参考

我想做的很简单。我在JSON请求主体,而我想增加额外的现场timeReceived$context.requestTime作为其值。我天真的第一次尝试是#set( $bodyObj.timeReceived = $context.requestTime )行不通的。

我很肯定我会让它工作,但是做这样简单的事情需要时间和精力,IMO 很愚蠢,AWS 应该改进现有的文档。

编辑:我在下面写的解决方案有效,但我主张重新考虑使用 API Gateway。我最近更新了我的应用程序,改为使用 edge lambda 和 CloudFront,这在各方面都是一个更好的解决方案。一些棘手的 lambda 配置无法使用环境变量,因此将 DeliveryStreamName 自动化到代码有点问题(我最终使用带有 Sceptre 的自定义解析器)。但还是好多了。不需要这些愚蠢的黑客 =)。

Tee*_*muK 9

编辑:在写这篇文章时,我发现 1# 我没有部署我的更改,令人尴尬的是 2# 它有效。现在我只需要使用添加的字段将 JSON 字符串化。

10 分钟后:嗯,这很难......所以我发现这个有效:

#set($payload = $util.parseJson($input.json('$')))
#set($body =  "{
  #foreach ($mapEntry in $payload.entrySet())
    ""$mapEntry.key"": ""$mapEntry.value"",
  #end
  ""timeReceived"": ""$context.requestTime"",
  ""x-client-ip"": ""$context.identity.sourceIp""
}")
Run Code Online (Sandbox Code Playgroud)

但是将 JSON 扩展为多行(JSON 被发送到 Firehose,然后将其存储到 S3)这是不好的。

20 分钟后:当我告诉他我在做什么时,我的高级开发人员嘲笑我,并用几句脏话评论 API 网关映射模板。

40 分钟后:我知道我必须做什么:用空字符串替换所有换行符,但事实证明这比我想象的要难。我还发现对象内的嵌套值没有被字符串化。

50 分钟后:实际上我可以通过将整个 foreach 循环放在一行中来省略换行符替换。但是我再次必须以某种方式对嵌套值进行字符串化。并且requestTime以一些愚蠢的英文格式格式化(没有冒犯!:))

70 分钟后:正确格式化嵌套值真的很困难。我找到了另一个有效的例子:

#set($body =  "{
  #foreach ($mapEntry in $payload.entrySet())
    #if ($mapEntry.value.size() > 0)
      ""$mapEntry.key"": {
      #foreach($subEntry in $mapEntry.value.entrySet())
        ""$subEntry.key"": ""$subEntry.value""#if($foreach.hasNext),#end
      #end
      },
    #else
      ""$mapEntry.key"": ""$mapEntry.value"",
    #end
  #end
  ""timeReceived"": $context.requestTimeEpoch}
}")
Run Code Online (Sandbox Code Playgroud)

如果您不想要新行或额外空格,则转换为:

#set($body = "{#foreach ($mapEntry in $payload.entrySet())#if($mapEntry.value.size() > 0)""$mapEntry.key"": { #foreach($subEntry in $mapEntry.value.entrySet())""$subEntry.key"": ""$subEntry.value""#if($foreach.hasNext), #end#end }, #else""$mapEntry.key"": ""$mapEntry.value"", #end#end""timeReceived"": $context.requestTimeEpoch }" )
Run Code Online (Sandbox Code Playgroud)

调试和写这篇文章花了 120 分钟:嗯,那是一段旅程。我想我已经回答了我自己的问题,所以希望现在有人可以避免像我一样花费太多时间调试它。

130 分钟后: Aaand 现在我必须解决将该字符串添加到我的 CloudFormation 模板中的悲剧。好家伙。(这甚至不难,难的部分是重新部署 API 网关,在撰写本文时,我必须从控制台手动执行)

  • “最奇特的语法”是 [VTL](http://velocity.apache.org/engine/1.7/vtl-reference.html)。在每行末尾添加`##`(注释)应该具有在每行末尾吞下换行符的副作用,允许人类可读的模板仍然产生没有换行符的输出。 (3认同)