API Gatewayを使用した際に詰まったポイントがあったのでメモ
事象
Data Kinesis FirehoseのPutRecordをAPI Gatewayで実行する際、
以下のマッピングテンプレートを使ってリクエストしようとしました。
#set($data = {"hoge": "$input.params('huga')", "hoge2": $input.json('$')})
{
"DeliveryStreamName": "hogehuga",
"Record": {
"Data": "$util.base64Encode($data)"
}
}
しかしデコードした値を確認したところ、jsonではなく{hoge=huga, hoge2={"hello":"world"}}
のようなkey=value
形式(移行KV形式)に変換されており、jsonが正しく送られていませんでした。
解決方法
jsonと認識されるとKV形式に変換されるため、文字列とすることでKV形式への変換を防げます。
後述するVTLでは、 文字列中に""
と記述することでダブルコーテーションをエスケープすることができるようです。(これを知らず\
や'
でエスケープしようとし時間を使ってしまった...)
#set($data = "{""hoge"": ""$input.params('huga')"", ""hoge2"": $input.json('$')}")
{
"DeliveryStreamName": "hogehuga",
"Record": {
"Data": "$util.base64Encode($data)"
}
}
そもそもなぜ変換されるのか?
警告
ここから先は推論を含んでいるため、完全な情報ではありません。
もし補足や訂正の情報をお持ちであれば、コメントいただけると幸いです🙏
API Gatewayのマッピングテンプレートは公式ドキュメントの通り、 VTL(Velocity Template Language)とJsonPath式で記述します。
マッピングテンプレートは、Velocity Template Language (VTL) で表現されるスクリプトであり、JSONPath 式を使用してペイロードに適用されます。
VTLについて調べたところ、これはjavaをベースとしたテンプレートエンジンでありjavaのデータ構造を使用しているようです。
このためjsonを変数に代入した場合、VTLはjsonをjavaのMap型に内部的に保持すると考えました。
つまり、マッピングテンプレートはリクエスト・レスポンスのjsonを生成する際、以下の処理を実施してます。
- マッピングテンプレート内のjsonを評価
- 変数展開・jsonをmap型で格納
- jsonにシリアライズ
しかし、マッピングテンプレート内で変数として定義されたJSONが参照される場合、その変数はシリアライズされず内部表現形式としてJavaのMap型が直接出力されます。
これが、KV形式に変換されてしまっているように見える原因だと推測しています。