[アップデート]API Gateway HTTP APIとEventBridgeの統合を使ってみた

2020.08.29

先日、API Gateway HTTP API で AWS サービス統合が利用できるようになりました。

すでにSQSとの統合をやってみたエントリはあります。

今回はEventBridgeとの統合を試してみます。今回のアップデートで、EventBridgeの PutEventsつまりイベントの発行がHTTP APIから可能になりました。

今まではHTTP API と EventBridgeの間にLambdaやコンテナなどを挟んでそこからEventBridgeのイベントの発行をする必要がありました。が、このアップデートにより、間のLambdaやコンテナなどが不要になります。

もうすこし詳細に書くと、HTTP APIはEvent Busというイベントのたまり場に対してイベントを発行するのみです。その先どのようなAWSサービスをトリガするかという点についてはEventBridgeの責務です。EventBridgeでは、送られてきたイベントに一致するルールを作成し、合致したイベントが発生した場合にトリガするAWSサービスを設定します。

HTTP API - EventBridgeの使いどころ

すでにHTTP API - Lambda関数 - EventBridgeという構成を使っている場合

Lambda関数を無くして直接HTTP APIとEventBridgeをつなげることをご検討ください。Lambda関数の課金をなくすことができますし、エラーハンドリングも不要になります。

REST APIで EventBridgeを直接呼び出している場合

REST API→HTTP APIの乗り換えをご検討ください。より安く、より早くすることができます。

カスタムドメインを使えば、同じドメイン上にREST APIとHTTP APIを共存させることができるので、EventBridge統合を使っている一部ルートだけ移行するというのもありだと思います。

やってみた

HTTP APIからEventBridgeのイベントを送信し、EventBridgeからSNSトピックをトリガして、メール送信してみます。

IAMロール作成

HTTP APIにEventBridge統合を作成する際に指定する項目 Invocation role で使用するIAMロールを作成します。 このロールは IAM role that grants API Gateway permissions to invoke your integration.、つまりAPI GatewayがEventBridgeのAPIにアクセスするときに使用されるロールです。

IAMポリシーは、最低限以下のように events:PutEventsの許可だけあればよいです。デフォルトイベントバスのみにイベント送信できるようにしています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "events:PutEvents",
            "Resource": "arn:aws:events:ap-northeast-1:012345678912:event-bus/default"
        }
    ]
}

信頼ポリシーは、以下のようにAPI Gatewayがロールを引き受けられるようにします。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

作成したIAMロールのARNを控えておきましょう。

HTTP APIの作成

HTTP API作成と同時にAWSサービス統合を作成することはできないようです。

というわけでいったんルートなしで作成します。

作成できました。空っぽ。

ルート作成

後にEventBridge統合を紐付けるルート、 /putevent のPOSTメソッドを作成しておきます。

統合を作成&アタッチ

統合をアタッチしたいルートで、「統合をアタッチする」をクリックします。

統合のページ遷移します。「統合を作成してアタッチ」をクリックします。

次ページでは、まず「統合ターゲット」でEventBridge→PutEventsと選択します。

するとその下にPutEventsに関する詳細な設定項目が表示されます。先程作成したIAMロールのARNを入力するInvocation role欄もありますね。

使える変数は以下をご参照ください。

ここまで動作確認

$ curl -X POST https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/putevent
{"message":"Bad Request"}
$ curl -X POST https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/putevent --data '{"Source":"com.mycompany.myapp","Detail":"{\"key1\":\"value1\",\"key2\":\"value2\"}","Resources":["resource1","resource2"],"DetailType":"myDetailType"}'
{"Entries":[{"EventId":"e968f7c2-a95f-b20d-xxxx-81baa5a2afab"}],"FailedEntryCount":0}

--dataにつかったのは こちらのExampleと同じデータです。

{
    "Source":"com.mycompany.myapp",
    "Detail":"{ \"key1\": \"value1\", \"key2\": \"value2\" }",
    "Resources":[
        "resource1",
        "resource2"
    ],
    "DetailType":"myDetailType"
}

レスポンス内容は PutEvents APIのレスポンスそのままです。イベント作成はされていそうですね。ただ、今はこのイベントをサブスクライブしているイベントルールがありません。作成していきましょう。

SNSトピック&サブスクリプション作成

この部分の説明は以下エントリに委ねます。UIが変わっていますがやることは同じです。

EventBridgeルール作成

イベントパターン

{
  "source": [
    "com.mycompany.myapp"
  ],
  "detail-type": [
    "myDetailType"
  ]
}

このイベントパターンは、

  • sourceというフィールドが存在し、その値が com.mycompany.myapp である
  • かつ、 detail-typeというフィールドが存在し、その値が myDetailTypeである

場合に、設定したターゲットリソースがトリガされます。イベントパターンの詳細は以下をどうぞ。

ターゲットとして前述のSNSトピックを設定しました。蛇足ですが、このタイミングで該当SNSトピックのアクセスポリシーが自動更新され、EventBridgeからメッセージ発行ができるようになっています。Terraformなどでやる場合はこの部分も自分で設定する必要があるはずです。

動作確認

作成したルールに引っかかるリクエストをしてみます。

$ curl -X POST https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/putevent  --data '{"Source":"com.mycompany.myapp","Detail":"{\"key1\":\"value1\",\"key2\":\"value2\"}","Resources":["resource1","resource2"],"DetailType":"myDetailType"}'
{"Entries":[{"EventId":"a87936cb-2e85-d3e6-xxxx-5faf9bd369ca"}],"FailedEntryCount":0}

メールボックスを確認します。

メールが届きました!

次に、違うイベントをリクエストしてみましょう。DetailType値を変えてみました。

  {
      "Source":"com.mycompany.myapp",
      "Detail":"{ \"key1\": \"value1\", \"key2\": \"value2\" }",
      "Resources":[
          "resource1",
          "resource2"
      ],
+    "DetailType":"not-myDetailType"
-    "DetailType":"myDetailType"
  }
$ curl -X POST https://xxxxxxxxxx.execute-api.ap-nort-1.amazonaws.com/putevent  --data '{"Source":"com.mycompany.myapp","Detail":"{\"key1\":\"value1\",\"key2\":\"value2\"}","Resources":["resource1","resource2"],"DetailType":"not-myDetailType"}'
{"Entries":[{"EventId":"dec72bc2-bf74-88df-xxxx-f0d7e5af8266"}],"FailedEntryCount":0}

この場合、メールは飛んできません。イベントパターンに一致しなかったからですね。こんな感じで、発行するイベントの中身やイベントルールを工夫することで、AWSサービスの呼び出し分けができます。例えばLambda関数をトリガするとして、そのコード内が分岐によって大きく2系統の処理に書かれているような場合、関数をふたつに分けてしまって、イベントルールによってどちらを呼び出すかの分岐を処理させる、というようなこともできます。コードが簡潔になりますし、コード量が減ることでコールドスタート時の関数実行速度も上がるはずです。

まとめ

HTTP APIの新機能、EventBridgeとの統合をやってみました。非常に簡単に統合できて良い感じです。選択肢のひとつに加えていただければと思います。