encore-go-webhook について
Encore Go 開発者向けの Webhook エンドポイントスキルです。生の HTTP リクエストの受信と署名検証を扱い、迅速に応答して時間のかかる処理を Pub/Sub に任せる方法を示します。
主な機能
- 01生の HTTP エンドポイント定義
- 02プロバイダー署名の検証
- 03迅速な 2xx 応答
- 04時間のかかる処理を Pub/Sub に委譲
活用シーン
- 01Stripe や GitHub の Webhook 受信
- 02Slack や Shopify のリクエスト検証
- 03検証済みイベントの非同期処理への登録
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ encoredev/ skills --skill encore-go-webhookインストール後、Claude Code で/encore-go-webhookを入力して読み込まれたか確認します。
詳細
Encore Go Webhook エンドポイント
手順
//encore:api raw を使用して、サードパーティサービスからの受信 Webhook を受け取ります。raw エンドポイントでは、http.ResponseWriter と *http.Request に直接アクセスできます。これは署名検証に必要であり、検証には通常、解析されていない生のボディが必要です。
1. //encore:api raw でエンドポイントを定義する
package webhooks
import (
"io"
"net/http"
)
//encore:api public raw path=/webhooks/stripe method=POST
func StripeWebhook(w http.ResponseWriter, req *http.Request) {
sig := req.Header.Get("Stripe-Signature")
// Read the raw body — needed for signature verification.
body, err := io.ReadAll(req.Body)
if err != nil {
http.Error(w, "could not read body", http.StatusBadRequest)
return
}
// Verify signature, parse event, handle, then respond...
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"received":true}`))
}
2. 署名を検証する
ほとんどのプロバイダーは Webhook に署名します。secrets でシークレットを読み取り(encore-go-secret スキルを参照)、ペイロードを信頼する前に検証してください。
package webhooks
import (
"github.com/stripe/stripe-go/v76/webhook"
)
var secrets struct {
StripeWebhookSecret string
}
//encore:api public raw path=/webhooks/stripe method=POST
func StripeWebhook(w http.ResponseWriter, req *http.Request) {
body, _ := io.ReadAll(req.Body)
sig := req.Header.Get("Stripe-Signature")
event, err := webhook.ConstructEvent(body, sig, secrets.StripeWebhookSecret)
if err != nil {
http.Error(w, "signature verification failed", http.StatusBadRequest)
return
}
// event is now trusted — handle it.
_ = event
w.WriteHeader(http.StatusOK)
}
GitHub の場合は、Webhook シークレットを使用して、X-Hub-Signature-256 ヘッダーの HMAC-SHA256 を生のボディと照合して検証します。
一般的なプロバイダー
| プロバイダー | 署名ヘッダー | 検証 |
|---|---|---|
| Stripe | Stripe-Signature | stripe.webhook.ConstructEvent(rawBody, sig, secret) |
| GitHub | X-Hub-Signature-256 | 生のボディに対する HMAC-SHA256 |
| Slack | X-Slack-Signature | v0:{timestamp}:{rawBody} に対する HMAC-SHA256 |
| Shopify | X-Shopify-Hmac-Sha256 | 生のボディに対する HMAC-SHA256(base64) |
| Twilio | X-Twilio-Signature | URL + ソート済みフォームフィールドに対する HMAC-SHA1 |
常に迅速に応答する
Webhook の送信元は、非 2xx または遅い応答に対してリトライします。ペイロードが検証されたらすぐに 2xx で確認応答し、実際の処理はリクエストハンドラー内で行うのではなく、Pub/Sub 経由でキューに投入してください(encore-go-pubsub を参照)。
package webhooks
import (
"encore.dev/pubsub"
"net/http"
)
type StripeEvent struct {
ID string `json:"id"`
Type string `json:"type"`
Data any `json:"data"`
}
var StripeEvents = pubsub.NewTopic[*StripeEvent]("stripe-events", pubsub.TopicConfig{
DeliveryGuarantee: pubsub.AtLeastOnce,
})
//encore:api public raw path=/webhooks/stripe method=POST
func StripeWebhook(w http.ResponseWriter, req *http.Request) {
// ... verify signature, parse event ...
_, _ = StripeEvents.Publish(req.Context(), &StripeEvent{
ID: event.ID, Type: string(event.Type), Data: event.Data,
})
w.WriteHeader(http.StatusOK)
}
ガイドライン
//encore:api rawは Webhook やその他の低レベルな HTTP 連携にのみ使用してください。- ペイロードを信頼する前に、常にプロバイダーの署名を検証してください。
- 常に迅速に 2xx を返してください — 遅い処理は Pub/Sub に任せてください。
- 署名シークレットは
secrets struct{...}に保存してください。インラインで記述しないでください。 - 自分のサービス内で型付き JSON エンドポイントを使用する場合は、
encore-go-apiスキルの通常の//encore:apiを使用してください。
コメント
Markdown 対応