Amazon API Gateway で AWS Service Proxy を使って DynamoDB にアクセスする

2016.02.04

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Amazon API Gateway の Service Proxy

Amazon API Gateway (以下 API Gateway) は、API を簡単に作成、公開、保守、監視、保護できるサービスです。ある機能にアクセスするための、アプリケーションの玄関として振舞うような API を作成することができます。

API Gateway では、公開する API が呼び出されたときの接続先の種別 (Integration type) を下記の4つの中から設定することができます。

  • Lambda function : Lambda function の呼び出し
  • HTTP Proxy : HTTP エンドポイントへのリクエスト
  • Mock Integration : モック化
  • AWS Service Proxy : AWS の各種サービスの呼び出し

このうち「AWS Service Proxy」を使えば、端的に言うと「AWS サービスの API 化」が実現できます。任意の HTTP メソッドに変更したり、一部パラメータを固定値にしたり、認証を不要にしたり、といったようなカスタマイズが行えます。

今回はこの AWS Service Proxy を使い、API Gateway から DynamoDB にアクセスする ということを行ってみたいと思います。APIGateway + Lambda + DynamoDB はよく見かける構成ですが、今回は Lambda レス というところがポイントです。

AWS Service Proxy で Amazon DynamoDB を利用する

今回はペットを表現した Pets というテーブルを題材にします。ハッシュキーは id とし、id からアイテムを引き出せるようにします。

この id を API Gateway で作る API のリクエストパラメータにし、Get リクエストで取得できるように作ります。

api-gateway-ddb-image

DynamoDB テーブルの作成

まず、上記の設計となる DynamoDB テーブルを作成します。また、テスト用に適当なアイテムを作成しておきましょう。

api-gateway-ddb-01

IAM Role の作成

次に API Gateway が上記の DynamoDB テーブルの GetItem を呼び出すことができるようにします。次のようなポリシーになる IAM Role を作成しましょう。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "dynamodb:GetItem"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:dynamodb:us-east-1:xxxxxxxxxxxx:table/Pets"
    }
  ]
}

API の設定

次に、API で DynamoDB のアイテムが取得できるように設定します。

API、Resource、Method を作成済みの前提で進めます。作り方については下記を参考に作成してください。

リクエストパラメータの設定

まず、リクエストパラメータを設定を行います。Method の設定から「Method Request」を選択します。

api-gateway-ddb-02

「URL Query String Parameters」に、「Name」が id となるパラメータを追加します。

api-gateway-ddb-03

Integration Request の設定

次に、DynamoDB テーブルにアクセスする設定を行います。Method の設定から「Integration Request」を選択します。

api-gateway-ddb-04

「Integration type」から「AWS Service Proxy」を選択し、接続するサービスの API について設定します。

api-gateway-ddb-05

次の表のように設定を行います。

項目 設定値
AWS Region DynamoDB テーブルを作成したリージョン
AWS Service DynamoDB
AWS Subdomain なし
HTTP method POST
Action GetItem
Execution role 上記で作成した IAM Role の ARN
Credentials cache Do not add ~

「HTTP method」と「Action」は、ドキュメントを読みつつ設定します(GetItem の場合はこちら)。GetItem の HTTP メソッドは POST であるところがポイントです。

さらに「Mapping Templates」を設定します。ここでは、リクエストパラメータである id を、GetItem のリクエストになるように設定します。「Content-Type」は application/json です。

api-gateway-ddb-06

{
  "TableName": "Pets",
  "Key": {
    "ID": {
      "S": "$input.params('id')"
    }
  }
}

Integration Response の設定

次に、取得した DynamoDB のアイテムを任意の JSON フォーマットに変換する設定を行います。Method の設定から「Integration Request」を選択します。

api-gateway-ddb-07

「Mapping Templates」の設定を、下記のようにします。ちなみに文字列型に限定してパースしているため、他の型を使う場合はもう少しカスタマイズする必要があります。

api-gateway-ddb-08

#set($item = $input.path('$.Item'))
{
#foreach($param in $item.keySet())
  $param : ${item.get($param).S}
#end
}

Method のテスト

次に、設定した Method をテストしてみましょう。Method の設定から「TEST」を選択します。

「Query Strings」の id に、DynamoDB テーブルに登録したアイテムの値を指定してテストします。

api-gateway-ddb-09

ここでは name??? になっていますが、API Gateway の画面で文字化けしているだけですので、無視して構いません。

デプロイして呼んでみよう

最後にデプロイし、実際に呼んでみましょう。

api-gateway-ddb-10

次のような URL になると思います。

https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/prod/item?id=xxx

curl で叩いてみます。

$ curl "https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/prod/item?id=xxx"
{
  name : 柴犬
  id : 1
}

呼べました!

まとめ

Mapping Template (VTL) を駆使すれば、Lambda 挟まなくても API 化できることがお分かりいただけたかと思います。

ただ、もっと細かいロジックを差し込みたい場合はやっぱり Lambda が必要になります。あくまで、DynamoDB の中身をあまり加工せずに提供したい場合に採用できるかと思います。

ぜひ参考にしてください!

参考