我最近熟悉AWS最具特色的API网关映射模板语法,这对我来说并不是很有意义。
有点令人费解我想要做的很简单。我在JSON中有一个请求正文,我希望添加其他字段timeReceived
并将$context.requestTime
作为其值。我天真的第一次尝试是#set( $bodyObj.timeReceived = $context.requestTime )
,但没有成功。
我很肯定我会让它发挥作用,但是需要时间和精力来做一些IMO很愚蠢的事情,AWS应该改进现有的文档。
编辑:我在下面写的解决方案有效,但我主张重新考虑使用API网关。我最近更新了我的应用程序以使用edge lambda和CloudFront,这在各方面都是一个更好的解决方案。一些棘手的配置与lambda无法使用环境变量因此自动将DeliveryStreamName自动化到代码有点问题(我最终使用自定义解析器与Scepter)。但还是好多了。并且不需要这些愚蠢的黑客=)。
答案 0 :(得分:3)
编辑:在编写这个东西时,我发现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""
}")
但是它将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}
}")
如果您不想要新行或额外空格,则转换为:
#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 }" )
120分钟花在调试和写这个:那是一段旅程。我想我已经回答了我自己的问题,所以希望现在有人可以避免花这么多时间调试这个问题。
130分钟后: Aaand现在我必须解决将该字符串添加到我的CloudFormation模板中的悲剧。好家伙。 (这甚至不是很难,困难的部分是重新部署API网关,在写这个时我必须从控制台手动完成)