アプリの Webhook
最終更新日 2025年01月09日(木)
Table of Contents
アプリの Webhook を使用すると、Heroku アプリに特定の変更が加えられた場合は常に通知を受信できます。次のような、さまざまなイベントの通知を購読できます。
- ドメインの設定への変更
- アプリのビルド
- アプリのリリース
- アドオンの変更
- Dyno formation の変更
Webhook 通知は、希望する URL への HTTP POST リクエストとして送信されます。Webhook と統合するには、これらのリクエストを受信して処理するサーバーエンドポイントを実装する必要があります。
はじめに
できるだけ早く開始するには、Dashboard の Webhook インターフェースに移動するか、またはアプリの Webhook のチュートリアルに従ってください。そこでは、CLI で単純な Webhook サブスクリプションを作成する方法が説明されています。
そのチュートリアルを完了したら、この記事に戻り、Webhook を購読して通知を受信する方法についての詳細を参照してください。
Dashboard を使用した Webhook の購読
アプリの “Dashboard” (ダッシュボード) ページに移動し、"More" (詳細) の下のドロップダウンメニューを表示します。"View Webhooks" (Webhook の表示) オプションが表示されます。これをクリックすると、Webhook の作成および管理インターフェースが表示されます。
Heroku CLI を使用した Webhook の購読
手順 1: Heroku CLI を更新する
アプリの Webhook を管理するためのコマンドは、Heroku CLI のバージョン `heroku-cli/6.13.19` 以降で使用できます。最新バージョンの CLI を使用していることを確認するには、次のコマンドを実行します。 “`term $ heroku update ”`手順 2: どのイベントを購読するかを決定する
Webhook 通知は、購読するアプリに関連するイベントが発生した場合は常に送信されます。どのイベントにも、それに関連するエンティティに対して表すアクションに応じて、`create`、`destroy`、または `update` のタイプがあります。たとえば、`api:release create` イベントは、アプリの新しいリリースが開始された場合に発生します。 次のエンティティの任意の組み合わせの通知を購読できます。 エンティティ | イベントタイプ | 説明 — | — | — `api:addon-attachment` | `create`、`destroy` | アドオンがアプリにアタッチされたか、またはアプリから削除されました。 `api:addon` | `create`、`destroy`、`update` | アプリのアドオンが新しくプロビジョニングまたは削除されたか、あるいはその詳細が変更されました。 `api:app` | `create`、`destroy`、`update` | アプリ自体がプロビジョニングまたは削除されたか、あるいはその詳細が変更されました。 `api:build` | `create`、`update` | アプリの新しいビルドが開始されたか、またはビルドのステータスが最後の通知以降に変更されました。 `api:collaborator` | `create`、`destroy`、`update` | 共同作業者がアプリに追加または削除されたか、あるいは既存の共同作業者の詳細が変更されました。 `api:domain` | `create`、`destroy` | カスタムドメインの詳細がアプリに追加または削除されました。 `api:dyno` | `create` | 新しい dyno がアプリで実行を開始しました。 `api:formation` | `destroy`、`update` | 特定のプロセスタイプの Dyno formation が変更されました。 `api:release` | `create`、`update` | アプリの新しいリリースが開始されたか、またはリリースのステータスが最後の通知以降に変更されました。 `api:sni-endpoint` | `create`、`destroy`、`update` | SNI エンドポイントがアプリで指定または削除されたか、あるいは既存の SNI エンドポイントの詳細が変更されました。 購読するエンティティに関連するすべての該当するイベントタイプ (`create`、`destroy`、または `update`) の通知は自動的に受信されます。具体的には、少なくとも `api:release create` と `api:release update` の 2 つのイベントは、リリースのたびに必ず受信します。アプリケーションで[リリースフェーズ](release-phase)を使用している場合、リリースのたびに `create`、`update`、`update` の 3 つのイベントを受信します。`status`フィールドは当初 `pending` に設定されますが、最後の更新で、リリースフェーズプロセスの結果に応じて `succeeded` または `failed` に変わり、リリースが現在のリリースにプロモートされると `current` が `true` に設定されます。 すべてのイベントタイプの HTTP リクエスト本体の例については、「[Webhook Events](webhook-events)」(Webhook イベント) を参照してください。手順 3: 購読する
Webhook 通知を購読するには、`heroku webhooks:add` コマンドを使用します。このコマンドは次のフラグを受け付けます **(そのうちの一部は必須)**。 フラグ | 説明 — | — `-i`、`–include` **(必須)** | 通知を購読するエンティティのカンマ区切りのリスト。可能な値は、前の手順の表に一覧表示されています。 `-u`、`–url` **(必須)** | すべての Webhook 通知を受信するサーバーエンドポイントの URL。 `-l`、`–level` **(必須)** | `notify` または `sync` のどちらかである必要があります。`notify`の場合、Heroku は失敗した Webhook 通知を再試行しません。`sync`の場合、成功するか、または決定された制限に達するまで、Heroku は失敗したリクエストを再試行します。 `-a`、`–app` | 購読するアプリの名前。 `-t`、`–authorization` | Heroku がすべての Webhook 通知に含めるカスタム `Authorization` ヘッダー。 `-r`、`–remote` | このコマンドを実行する対象の Git リモートの名前。 `-s`、`–secret` | すべての Webhook 通知リクエストに署名するために Heroku が使用する値 (この署名はリクエストの `Heroku-Webhook-Hmac-SHA256` ヘッダーに含まれる)。この値を省略した場合は、生成された秘密鍵が CLI によって返されます。この値は再度取得することができないため、ただちに保存する必要があります。そうしないと、後で `heroku webhooks:update` を実行して秘密鍵を更新できてしまいます。 次の例は、dyno に関連するすべての Webhook 通知の購読を示しています。この例では、失敗しても通知は再試行*されず*、すべてのリクエストが `https://example.com/hooks` に送信されます。 “`term $ heroku webhooks:add -i api:dyno -l notify -u https://example.com/hooks Adding webhook to ⬢ app … done === Webhooks Signing Secret 475beb0bf7de962fb89878a767c22f7de22154dae1e6996b6b33299e7a0f ”` 上記の `–secret` フラグの説明で注記したように、コマンドに値が含まれていなかったため、CLI が生成された秘密鍵を返しています。 [下記](#introspecting-deliveries-with-the-cli)のように、`heroku webhooks:deliveries` コマンドを使用して通知の配信ステータスを確認できます。再試行と制限
1 つのアプリ、アドオン、パイプラインで最大 10 個の独立した Webhook サブスクリプションを設定できます。 再試行が有効な場合、Heroku は 72 時間までのみ再試行を試みます。Webhook 通知を処理するコードが 72 時間を超えて失敗する場合、配信を再試行せずに破棄します。 >note >通知の配信は順序付けるように考慮されているため、再試行中はその他のすべての通知が遅延されます。この遅延によって、アプリの通知バックログに 72 時間を超えたイベントが格納される場合、これらのイベントは 1 回のみ配信が試行され、失敗すると再試行されません。バックログが過剰に大きくなると、追加の Webhook イベントが失敗する可能性があります。全体的な失敗の比率が非常に高くなった場合は、Heroku が Webhook サブスクリプションを完全に無効にすることがあります。 Heroku では継続的に失敗する Webhook が削除されます。Webhook が 1 週間継続的に失敗する場合、Heroku では失敗を知らせるメール通知が送信されます。メールには、失敗し続ける場合の Webhook の削除日が記載されます。Webhook API を使用した購読
Webhook 通知を購読するには、Webhook API の Webhook の作成エンドポイントを使用します。必須パラメータとオプションパラメータの一覧については、そのリファレンスを参照してください。これらのパラメータほとんどは、CLI を使用して購読する場合に使用できるパラメータに対応しています。
Webhook API エンドポイントと通信する場合は、リクエストに値が application/vnd.heroku+json; version=3.webhooks
の Accept
ヘッダーが含まれている必要があります。
Webhook リクエストのセキュリティ保護
共有秘密鍵の使用
リクエストが Heroku から来ていることを証明するには、Webhook 作成の秘密鍵をリクエストヘッダーと組み合わせて使用して、そのリクエストが共有秘密鍵によって署名されたことを確認します。リクエストと秘密鍵を取得し、そのリクエストが Heroku から来ているかどうかを判定する Ruby on Rails のいくつかのサンプルコードを次に示します。webhook_secret
パラメータはアプリケーションコード内ではなく、Heroku 環境設定などの安全な場所に保存します。
def valid_signature?(request, webhook_secret)
calculated_hmac = Base64.encode64(OpenSSL::HMAC.digest(
OpenSSL::Digest.new('sha256'),
webhook_secret,
request.raw_post
)).strip
heroku_hmac = request.headers['Heroku-Webhook-Hmac-SHA256']
heroku_hmac && Rack::Utils.secure_compare(calculated_hmac, heroku_hmac)
end
共有承認の使用
リクエストが Heroku から来ていることを確認するために承認フラグを使用することもできます。設定されている場合、この承認値はリクエスト内の Authorization
ヘッダーに渡されます。この共有秘密鍵は変更なしで渡されるため、選択した承認メカニズムを使用して検証します。
サブスクリプションの管理
サブスクリプションを作成した後、それを確認したり、削除したりすることもできます。
Webhook の一覧表示エンドポイントまたは CLI を使用して、アクティブな Webhook サブスクリプションを一覧表示できます。
$ heroku webhooks
Webhook の削除エンドポイントまたは heroku webhooks:remove
CLI コマンドを使用して、Webhook サブスクリプションを削除できます。
Webhook の受信
購読している Webhook イベントが発生した場合、Heroku は、そのイベントの詳細を含むサーバーエンドポイントに POST リクエストを送信します。これらのリクエストの正当性は、次の方法で確認できます。
- リクエストの
Authorization
ヘッダーが、通知を購読するときに指定した値に一致している。 - リクエストの
Heroku-Webhook-Hmac-SHA256
ヘッダーに、リクエスト本体の (購読するときに指定したsecret
値で署名された) HMAC SHA256 署名が含まれている。
結果として得られる Webhook 通知リクエストは次のようになります。
POST https://example.com/hooks
Authorization: Bearer 01234567-89ab-cdef-0123-456789abcdef
Heroku-Webhook-Hmac-SHA256: cLM15U5x+jHEkANnVasRwBw2yEHu94pXdjcT9Hajc1M=
{
"action": "update",
"actor": {
"email": "user-0436@example.com",
"id": "096370c8-f3ad-4e20-a309-fb4f06ec0a89"
},
"created_at": "2016-10-26T22:50:14Z",
"id": "d472a8bb-1a3c-4f78-aad1-995e6d0022ec",
"data": {
"archived_at": null,
"buildpack_provided_description": "Ruby/Rails",
"build_stack": {
"id": "5e854079-da33-475b-a209-77f527c0e2fb",
"name": "heroku-18"
},
"created_at": "2016-10-26T22:50:14Z",
"id": "d4714cc8-aa56-4314-817c-0c6a66ff3d41",
"git_url": "https://git.heroku.com/sample-app-0301.git",
"maintenance": false,
"name": "sample-app-0301",
"owner": {
"email": "user-0436@example.com",
"id": "096370c8-f3ad-4e20-a309-fb4f06ec0a89"
},
"region": {
"id": "7044c05a-0873-42c2-abbe-6841c5481ba7",
"name": "us"
},
"organization": null,
"space": null,
"released_at": "2016-10-26T22:50:14Z",
"repo_size": 1048576,
"slug_size": null,
"stack": {
"id": "5e854079-da33-475b-a209-77f527c0e2fb",
"name": "heroku-18"
},
"updated_at": "2016-10-26T22:50:14Z",
"web_url": "https://sample-app-0301.herokuapp.com/"
},
"previous_data": {
},
"published_at": null,
"resource": "app",
"sequence": null,
"updated_at": "2016-10-26T22:50:14Z",
"version": "application/vnd.heroku+json; version=3",
"webhook_metadata": {
"attempt": {
"id": "8a44f820-2354-489d-9a11-a793cbf49979"
},
"delivery": {
"id": "d244009a-670f-4340-88e9-789a4f9002d5"
},
"event": {
"id": "d472a8bb-1a3c-4f78-aad1-995e6d0022ec",
"include": "api:app"
},
"webhook": {
"id": "01234567-89ab-cdef-0123-456789abcdef"
}
}
}
通知を受信したことを示すには、常に 200 レベルのステータスコードで応答します。Heroku では応答の本体が無視されるため、空の本体を持つ 204
ステータスが理想的です。
204 No Content
200 レベルのステータスコードを返さない場合、Heroku は失敗を記録します。この失敗は、CLI の配信ログで表示できます。
$ heroku webhooks:deliveries
sync
の通知レベルで購読した場合、成功するか、または再試行カウントがなくなるまで、Heroku は失敗したリクエストを再試行します。
配信ステータスの確認
Heroku が送信のためにキューに入れている通知のログを表示できます。各通知には status
(pending
、success
、failure
、skipped
のいずれか) があり、これを確認することによって通知の配信の現在のヘルスを監視できます。
ステータス | 説明 |
---|---|
pending |
この Webhook を配信する試行をキューに入れました。前のイベントについての保留中の配信が他にない場合に試行されます。 |
success |
設定されたエンドポイントに Webhook を配信する試行の結果、正常な HTTP 応答コード (2xx) が得られました。 |
failure |
過去 72 時間のイベントを配信するすべての試行が成功せず、このイベントはこれ以上再試行されません。Webhook の次のイベントの配信の試行を開始します。 |
skipped |
イベントが 72 時間以上前に発生した場合、配信が 1 回のみ試行されます。不成功の応答が返された場合、配信はスキップされたとマークされます。これは通常、エンドポイントが継続的に失敗している (前の配信のステータスが failed として表現される) 場合に発生します。 |
CLI を使用した配信の内観
次のコマンドを実行してください。
$ heroku webhooks:deliveries
Webhook API を使用した配信の内観
配信の一覧表示エンドポイントを使用します。
過去のイベントの検索
以前に送信された配信の id
がある場合は、そのイベントの詳細をもう一度フェッチできます。
CLI を使用したイベントの内観
次のコマンドを実行してください。
$ heroku webhooks:deliveries:info DELIVERY_ID
Webhook API を使用したイベントの内観
イベントの情報エンドポイントを使用します。