Webhook

Webhookとは

Webhook は、イベントが起きたときにサーバー側から相手のURLへ HTTP リクエストを送って通知する仕組みです。通常の [[REST API]] はクライアントが問い合わせて答えをもらう「呼び出し型」ですが、Webhook は逆にサービス側から自分のサーバーを呼んでもらうため、「逆向きの API」とも呼ばれます。

通常のAPI : 自分 →(問い合わせ)→ サービス
Webhook  : 自分 ←(イベント通知)← サービス

たとえば「決済が完了したら」「GitHub に push されたら」といったタイミングで、あらかじめ登録した URL に JSON を載せた POST リクエストが飛んできます。

ポーリングとの比較

Webhook が無い場合、変化を知るにはポーリング(定期的な問い合わせ)を繰り返すしかありません。

ポーリングWebhook
検知の速さ問い合わせ間隔に依存イベント発生とほぼ同時
無駄な通信変化がなくても発生イベント時のみ
受け側の準備不要公開URLの受信エンドポイントが必要

リアルタイム性と効率で Webhook が勝りますが、外部から呼ばれる URL を用意して守る責任が発生します。ブラウザの画面へ変化を届けたい場合は、つなぎっぱなしの接続を使う [[WebSocket]] が別の解になります — Webhook はサーバー間の非同期通知が主な出番です。

実装時の注意点

Webhook の受信側には、初学者がつまずきやすい定番の注意点があります。

  • 署名検証 — 誰でもその URL に POST できてしまうため、リクエストが本物か署名(シークレットによる HMAC など)で検証する
  • すばやく応答する — 受信したら即座に 200 を返し、重い処理は [[メッセージキュー]] に積んで後で行う。応答が遅いと送信側がタイムアウト・再送してしまう
  • 再送への備え — 送信側は失敗時に同じ通知を再送してくる。同じイベントを2回処理しても壊れないよう [[冪等性]] を確保する

初学者向けポイント

  • 開発中はローカルPCに公開URLが無いため、トンネリングツール(ngrok など)や Webhook テストサービスで受信を確認します
  • Stripe(決済)・GitHub・Slack など、主要なサービスはほぼ Webhook を提供しています — まずは受け取って中身をログに出すところから始めましょう
  • 通知は [[HTTP]] の POST + JSON という普通の形なので、特別なライブラリは不要です

関連技術とのつながり

  • [[REST API]] — 呼び出す API と呼ばれる Webhook はセットで使われる
  • [[HTTP]] — Webhook の通知は HTTP POST リクエストそのもの
  • [[冪等性]] — 再送された同じ通知を安全に処理するための鍵
  • [[メッセージキュー]] — 受信後の重い処理を非同期に逃がす定番の相方
  • [[エラーハンドリングとリトライ設計]] — 再送とタイムアウトを設計する側の作法
Q: Webhookの説明として正しいのはどれ?
- [ ] クライアントが定期的にサーバーへ問い合わせる仕組み
- [x] イベント発生時にサービス側から登録URLへHTTPリクエストが送られる仕組み
- [ ] データベース同士を直接同期する仕組み
解説: Webhook はサービス側からの通知です。クライアントが定期的に問い合わせるのはポーリングです。

Q: Webhook受信エンドポイントで署名検証が必要な理由はどれ?
- [x] 誰でもそのURLにPOSTできてしまうため、本物のリクエストか確かめる必要がある
- [ ] 署名がないとHTTP通信自体が確立できないため
- [ ] レスポンスの速度が上がるため
解説: 受信URLは外部に公開されるため、シークレットを使った署名検証でなりすましのリクエストを排除します。

Q: Webhook受信時の推奨される処理はどれ?
- [ ] 重い処理をすべて終えてから応答を返す
- [ ] 応答を返さずに接続を切る
- [x] 即座に200を返し、重い処理はキューに積んで後で行う
解説: 応答が遅いと送信側がタイムアウトして再送するため、まず素早く応答し重い処理は非同期に回します。