API Gatewayでバックエンドレスポンスのbodyに含まれる配列の要素数を統合レスポンス機能でheaderに追加してみた

API Gatewayで統合レスポンスのマッピングテンプレートを使って、バックエンドレスポンスのbodyを加工してheaderに追加してみました
2023.07.17

こんにちは、AWS事業本部@福岡オフィスのべこみん(@beco_minn)です。

みなさん、Amazon API Gatewayで統合レスポンスのマッピングテンプレートは使ってますか?

Amazon API Gatewayのレスポンスで、bodyに入ってる値を加工して良い感じにheaderに出力したいな〜って思うこと、ありますよね。

今回は「bodyに含まれている配列の要素数をheaderに出力してみた」という少しニッチな内容の記事です。

やりたいこと

bodyに含まれる配列の要素数をheaderに出力する、これが今回のゴールです。

API Gatewayでは統合レスポンスのマッピングテンプレートという機能でバックエンドからのレスポンスを加工することが出来ます。

やってみた

簡単に下図の構成で検証してみました。

Lambdaの中身はただステータスコードと配列をjson形式で返すだけのものです。

def lambda_handler(event, context):
    return {
        "statusCode": 200,
        "body": {
          "array": ["hoge", "piyo", "fuga"]
          }
    }

マッピングテンプレートはVTL(Velocity Template Language)という少し変わった言語で記述します。

マッピングテンプレートの設定方法については下記記事をご参照ください。下記記事にある通り、#set($context.responseOverride.header.hoge = "hoge") のように書くことでレスポンスのheaderに値を追加することが出来ます。

API Gateway で統合レスポンスのマッピングテンプレートを使って特定条件時にリダイレクトさせる

一次元配列の要素数をheaderに追加するマッピングテンプレート

下記が作成したマッピングテンプレートの内容です。VTLでは配列の要素数はsize()で取得可能です。

## 要素数を算出
#set($arr = $input.path("$.body.array"))
#set($context.responseOverride.header.count = "$arr.size()")
## バックエンドレスポンスのbodyをパススルー
$input.json("$")

実行すると、確かに要素数として count: 3 と出力されています。

$ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/hoge -i
HTTP/2 200 
date: Mon, 17 Jul 2023 05:56:18 GMT
content-type: application/json
content-length: 58
x-amzn-requestid: 97f14291-d705-4bd7-b1dd-0d3622748116
count: 3
x-amz-apigw-id: IMawaEOaNjMFigA=
x-amzn-trace-id: Root=1-64b4d802-3c6e349e1adba3a5488ad52e;Sampled=0;lineage=03363431:0

二次元配列の要素数をheaderに追加するマッピングテンプレート

二次元配列の全ての要素数を取りたいな〜って時もありますよね。

Lambdaの中身を以下のように変更します。

def lambda_handler(event, context):
    return {
        "statusCode": 200,
        "body": {
          "array": [["hoge", "piyo", "fuga"], ["foo", "bar", "baz"]]
          }
    }

マッピングテンプレートは下記の通り。VTLではforeachが使えるため、二次元配列の要素数でも簡単に取得することが出来ます。

## 要素数を算出
#set($arr = $input.path("$.body.array"))
#set($count = 0)
#foreach($item in $arr)
    #set($count = $count + $item.size())
#end
#set($context.responseOverride.header.count = "$count")
## バックエンドレスポンスのbodyをパススルー
$input.json("$")

実行すると、要素数として count: 6 と出力されています。

$ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/hoge -i
HTTP/2 200 
date: Mon, 17 Jul 2023 06:19:15 GMT
content-type: application/json
content-length: 80
x-amzn-requestid: 27ccbdcf-1471-4f5a-945b-bac5dd6b6538
count: 6
x-amz-apigw-id: IMeHgHkXNjMFYGg=
x-amzn-trace-id: Root=1-64b4dd62-7da70fab53f615e251a008d7;Sampled=0;lineage=03363431:0

最後に

今回ご紹介した程度の簡単な操作であれば、Lambdaを使用せずにマッピングテンプレートで加工が出来ることが分かりました。

VTLの記法がややこしいので面倒臭さはありますが、こういうやり方があるのも覚えておくと役に立つ場合があるかもしれません。

本記事がどなたかのお役に立てれば幸いです。

以上、べこみんでした。