Webhook

服屋のショッピングモールを運営していると考えてみてください。新しい商品を登録するたびに、毎回自分で対応しなければならない裏方の作業があります。商品説明を別の国の言葉に翻訳しておいたり、登録したことを社内メッセンジャーに知らせたりするような作業です。こうした裏方の作業を人が毎回手作業でやるのではなく、商品が登録された瞬間に外部にあるプログラムへ自動で知らせて、代わりに処理させることができます。この「何かが起きたら、あらかじめ決めておいた場所へ自動で知らせてくれる仕組み」が Webhook です。

店のドアに取り付けた呼び鈴にたとえることができます。お客さんがドアを開けて入ってくると(商品が登録されると)、呼び鈴がひとりでに鳴って、奥にいる従業員(外部プログラム)が「お客さんが来たな」とすぐに動き出します。誰かがずっとドアの前を見張っている必要はありません。Webhook はその呼び鈴のように、決めておいた出来事が起きた瞬間に、決めておいた動作を自動で開始します。

このページでは、Webhook が何であり、どんなときに使うのかをまず見てから、服屋の SpaceWebhook を実際に作ってみます。

Webhook がすること

Webhook は、三つのことをあらかじめ決めておくことで成り立ちます。

  • いつ: どんな出来事が起きたときに反応するかを決めます。たとえば「商品(Content)が新しく登録されたとき」と決めることができます。
  • 何をするか: 二つのうち一つを決めます。外部プログラムのインターネットのアドレス(URL)へリクエストを送るか、Space の中に作っておいた Script を実行します。
  • オンにするかオフにするか: この Webhook を今オンにしておくか(Active)、しばらくオフにしておくか(Inactive)を決めます。オフにしておくと、決めておいた出来事が起きても何も動作しません。

決めておいた出来事が実際に起きると、Webhook は決めておいた動作を実行します。外部のアドレスへ送る場合、リクエストには、何が起きたのか、どの商品で起きたのかといった情報が含まれて送られます。リクエストを受け取った外部プログラムは、その情報を見て自分の仕事をします。

どんな変化でリクエストを送るか

リクエストを呼び起こす「出来事」は、Space の中のリソースに起こる変化です。商品のような Content、アップロードしたファイルである Media、ひな形である Content Type に何かが起きたときを選べます。

リソースごとに選べる変化は次のとおりです。

変化いつ起きるか服屋の例
Create新しく作られたとき新しい商品を登録する
Save内容を直して保存したとき商品説明を直して保存する
Delete削除されたとき廃番になった商品を消す
Publish発行して外部に公開したとき商品をサイトに公開する
Unpublish発行を取り消したとき品切れ商品をサイトから下げる
Archive保管処理したとき前シーズンの商品を保管する
Unarchive保管を解除したとき保管していた商品を戻す

たとえば「商品が新しく登録されるたびにリクエストを送れ」というのは、「商品(Content)の Create」を選ぶことです。

一つの Webhook に複数の変化をまとめて選ぶこともできます。「商品が登録されたとき」と「商品が修正されたとき」の両方を選ぶと、どちらが起きてもリクエストが送られます。

条件をつけて絞り込む

選んだ変化が起きたからといって、必ずリクエストを送りたいわけではないときがあります。たとえば「すべての Content ではなく『商品』というひな形で作った Content が登録されたときだけ」受け取りたいことがあります。こういうときは フィルター をかけて、リクエストを送る場合を絞り込みます。

フィルター一つは、「何を基準に、どう比較するか」を一行で表したものです。何を基準に絞り込むかは、次の四つから選びます。

  • どのひな形で作った項目か: たとえば「商品」Content Type で作った Content にだけリクエストを送ります。最もよく使う条件です。
  • 特定の項目一つか: 決めておいたその項目一つで起きた変化にだけリクエストを送ります。
  • 誰が作った項目か: 特定の人が作った項目にだけリクエストを送ります。
  • 誰が最後に直した項目か: 特定の人が最後に修正した項目にだけリクエストを送ります。

比較する方法もあわせて選びます。決めた値と等しいときだけ、異なるときだけ、決めておいた複数の値のいずれかに当てはまるときだけ、そのどれにも当てはまらないときだけ、または決めた形式(パターン)に合うとき・合わないときだけ、というように絞り込めます。

コンテンツスタジオのトリガー設定で フィルターを追加 から条件を一行ずつ追加します。フィルターを複数かけると、その条件を すべて満たす 場合にだけリクエストが送られ、一つもかけないと、選んだ変化が起きるたびにリクエストが送られます。

外部プログラムが求める形で送る

特に決めなければ、リクエストには変化が起きた項目の情報がまるごと含まれて送られます。たとえば商品「ステンレスタンブラー 500ml」が登録されると、リクエストに含まれて送られる内容はおおよそこのような形です。

{
  "sys": { "id": "3trmXRM3RqbgSnifyg7OGhwhlqvAvq", "type": "Content" },
  "fields": {
    "productName": { "ko-KR": "스테인리스 텀블러 500ml" }
  }
}

(実際にはもっと多くの情報が含まれており、上はその一部だけを抜き出した形です。)外部プログラムはこの中から必要な値を選んで使えばよいのです。しかし「この形でしか受け取らない」と形式が決まっているプログラムもあります。そういうときは、コンテンツスタジオの PayloadWebhook payload をカスタマイズ を選び、送る形を自分で書いておきます。

Webhook 作成画面のヘッダー・Payload 領域。リクエストボディを含めるをオンにし、Webhook payload をカスタマイズを選んだ状態で、下の JSON エディターに送る形を書く

送る形を書きますが、上のデータから値を引いて入れる場所には プレースホルダー を使います。プレースホルダーは { /payload/… } という形です。ここで payload は上に示したその項目全体を指し、その後ろのパスで望みの値をピンポイントに指し示します。

  • { /payload/sys/id } → 上のデータの sys の中の id(商品の固有番号)
  • { /payload/fields/productName/ko-KR }fields の中の productNameko-KR(韓国語の商品名)。fields/ の後ろには Field の ID(商品名なら productName)と言語コード(韓国語なら ko-KR)を順に付けます。

たとえば翻訳プログラムが「翻訳する文と商品番号をこの形でくれ」と言うなら、ペイロードはこのように書きます。

{
  "id": "{ /payload/sys/id }",
  "text": "{ /payload/fields/productName/ko-KR }"
}

すると、タンブラー商品が登録される瞬間に、プレースホルダーが実際の値に置き換わって、このように送られます。

{
  "id": "3trmXRM3RqbgSnifyg7OGhwhlqvAvq",
  "text": "스테인리스 텀블러 500ml"
}

同じプレースホルダーは、送るアドレス(URL)やヘッダーの値にも入れることができ、送る方法(method)や形式(JSON またはフォーム形式)もあわせて選べます。指し示したパスに値がなければ、その場所は空の値になります。

外部 API キーのように他人に見えてはいけない値は、ヘッダーを追加するときにタイプを Secret に指定しておきます。すると、その値は隠されて保存され、最終ユーザーには露出されません。

ヘッダーを追加するときにタイプのドロップダウンを開いた様子。Secret · HTTP Basic Auth · Custom の中から選ぶ

URL の代わりに Script を実行する

ここまでは、Webhook が外部のアドレス(URL)へリクエストを送る場合でした。Webhook は、その代わりに Space の中に作っておいた Script を実行させることもできます。Script は、外部に出ていくことなく Space の中で決めておいた作業(リソースを作る・直すなど)を代わりに行う仕組みです。外部プログラムを経由せずに Space の中で裏方の作業を済ませたいときに、この方式を使います。

一つの Webhook は、外部のアドレスへの 送信Script実行 のうち、正確に一つだけを行います。作成画面の リクエスト先 で決めます。URLを直接入力 を選ぶと、前と同じようにアドレスへリクエストを送り、代わりに一覧から Script を一つ選ぶと、その Script を実行します。

Script を選ぶと、その Script誰の身元で実行されるか を決める Run as もあわせて表示されます。二つのうち一つを選びます。

  • Webhook の作成者(既定): 実行中に作られたり変わったりしたリソースの「作った人」が、Webhook を作った人として残ります。
  • トリガーしたユーザー: その変化を引き起こしたユーザーとして残ります。

この設定は、リソースに残る「誰がやったか」の表示を決めるだけで、Script ができることを広げたり狭めたりはしません。Script ができることの範囲は、その Script を作るときにすでに決まっています。

実際に選んでみる手順は次のとおりです。

  1. 作成画面で リクエスト先 を押してください。
  2. 一覧から実行する Script を選んでください。URLを直接入力 の代わりに Script を選ぶということです。
  3. Run as で身元を選んでください。既定は Webhook の作成者 です。

Webhook 作成画面でリクエスト先として「商品説明の入力」 Script を選んだ状態。埋まった呼び出し URL と一緒に、Run as が Webhook の作成者・トリガーしたユーザーの二つの選択肢として表示されている様子

Script が何であり、どうやって作るのかは Script で扱います。

服屋の Webhook を作る

では、服屋の SpaceWebhook を一つ作ってみます。「新しい商品が登録されたら、あらかじめ用意しておいた外部の翻訳プログラムにその事実を知らせる」という Webhook です。リクエストを受け取る外部プログラムのアドレスは https://example.com/translate とします。

  1. 服屋の Space の設定で Webhook 画面を開いてください。
  2. 右上の 作成 ボタンを押してください。
  3. 名前の欄に 新商品の翻訳通知 を入力してください。この名前は、後でどの Webhook なのかを見分けるためのものです。
  4. リクエストを送る変化を決めてください。特定の変化にだけ送るなら 特定のトリガーイベントを選択 を選んでから、望みの変化(ここでは商品(Content)の Create)を指定し、すべての変化に送るなら すべてのイベントでトリガー を選びます。
  5. URL の欄に、リクエストを受け取る外部プログラムのアドレス https://example.com/translate を入力してください。
  6. 有効 をオンにしておくと、作った直後にリクエストを送ります(Active)。しばらく試すだけなら、オフにしておいてください(Inactive)。
  7. 作成 ボタンを押して Webhook を作ってください。

新しい Webhook 作成画面。名前・有効・トリガー選択・URL を埋めた様子

一覧に 新商品の翻訳通知Active の状態で現れたら、Webhook が作られたということです。

Webhook 一覧に「新商品の翻訳通知」が Active の状態で見える画面

作った後は、服屋に実際に新しい商品を一つ登録してみてください。登録する瞬間に Webhook が書いておいたアドレスへリクエストを送ります。リクエストがうまく届いたか、外部プログラムがどう応答したかは、Webhook の呼び出し履歴で確認できます。

オン・オフと修正

Webhook は、作った後でもいつでもオン・オフできます。しばらくリクエストを止めたいときは、削除せずに Inactive にしてオフにしておいてください。オフにしている間は、新しい商品を登録してもリクエストは送られません。再び Active にしてオンにすると、そこから再びリクエストを送ります。

作った Webhook を再び開くと、有効 をオフにしたり、再びオンにしたりできます。名前、リクエストを送るアドレス、呼ぶ変化といった内容も後で修正でき、もう使わない Webhook は削除すればよいです。

次にすること

  • Content モデリング: Webhook がリクエストを呼び起こす対象である「商品」のような Content のひな形を作る方法を扱います。
  • Content を作成する: 実際に商品を登録して、Webhook が動作するか確認してみることができます。
  • Script: Webhook が URL の代わりに実行できる、Space の中で動く作業を作る方法を扱います。
  • API リファレンス: Webhook をプログラムから直接作成・管理するときに使うリクエスト・応答の形式とフィールドの仕様を扱います。