最後の一席が、イトの画面で青く光っていた。
最終話上映 残り1席
上映まで、あと三分。
ピコルート・ラボの小さな上映室には、椅子が十二脚しかない。
イトは12番席の仮札を持っていた。受付を手伝い終えたら、ずっと待っていたアニメの最終話を、その席で見るつもりだった。
「間に合った」
イトは予約ボタンへ指を置く。
その瞬間、画面の端で細い光が走った。
別の場所から届いた予約が、先に12番席へ入った。
けれど、イトの画面はまだ「残り1席」のままだ。
イト
僕の画面では、まだ一席あるよ
ユイ
その表示は、ページを開いた時の数かもしれません
ピコ
今の席を確かめるお願いを、API受付へ送ってみよう
上映まで、あと二分四十五秒。
開いたページの数字は、古くなる
イトがページを開いたとき、残席は確かに1だった。
その数字は、最初に届いたHTMLと一緒に画面へ置かれている。
しかし、ページを開いた後も、ほかの人の予約は動く。
誰かが最後の席を取っても、イトの手元にある古い数字が自分で0へ変わるわけではない。
画面の見た目と、予約側が持つ現在の状態が離れた。
イトが予約ボタンを押す。
JavaScript操作室から、小さなrequestが飛び出した。
{
"screeningId": "finale",
"seatId": 12
}
requestは、映画一覧でもニュース一覧でもない。12番席を予約するための窓口へ向かう。
APIは、アプリやサービスが決まった窓口へrequestを送り、dataや機能のresponseを受け取るための接点だ。
どの窓口に何を頼めるかは同じではない。OpenAPI Specificationのような記述形式では、HTTP APIのoperation、parameter、request body、possible responsesを、人とcomputerが理解できる形で表せる。
ただし、すべてのAPIがOpenAPIを使うわけではない。ここで大切なのは、お願い先と頼み方がAPIごとの約束で決まることだ。
返事は、完成した画面ではなかった
光の道からresponseが戻った。
中に、上映ページは入っていない。
入っていたのは、短いdataだった。
{
"reserved": false,
"remaining": 0,
"reason": "already_taken"
}
JSONは、nameとvalue、object、arrayなどを使ってstructured dataを表せるtext formatだ。RFC 8259に基本の表現規則がある。
APIのresponseがJSONとは限らない。画像、text、file、空のbodyなど、別の返し方もある。
今回のresponseが伝えたことは三つだ。
イトの予約は成立していない 現在の残席は0 12番席は先に取られた
イトの画面では、青い「残り1席」がまだ点灯している。
response cardには、赤い「残り0席」がある。
上映まで、あと一分五十九秒。
うまくいかなかった返事も、現在のdata
「エラーなら、もう一回押せば取れるかも」
イトが予約ボタンへ戻ろうとする。
マコトが、二枚の札を並べた。
古い画面には1。
APIの現在の返事には0。
マコト
同じrequestを急いで繰り返す前に、なぜ成立しなかったかを見よう
ピコ
今の状態とぶつかって完了できないrequestには、conflictを示す返し方もあるよ
ユイ
失敗のresponseも、利用者へ次の行動を伝えるdataなんですね
HTTPの409 Conflictは、requestが対象resourceの現在状態と衝突して完了できない場合に使える。RFC 9110では、利用者が衝突の原因を認識できる情報をresponse contentへ含めることが望まれている。
この上映室APIはフィクションで、競合時に409を使う一つの設計例だ。実際の予約serviceがすべて同じstatusやdataを返すわけではない。
赤いresponseは、イトを困らせるための札ではなかった。
古い1席をもう誰かが取ったという、現在の状態を知らせている。
イトが選べる三つの道
ピコが、三枚の札を机へ置いた。
- 古い席を取る
- 返事を隠す
- ゼロへ直す
一枚目なら、手元の「残り1席」を根拠に12番へ座れる。けれど、同じ席を予約した人と重なる。
二枚目なら、赤いresponseを画面から消せる。けれど、次にページを見る人にも古い1が残る。
三枚目なら、現在のresponseをJavaScriptへ渡し、残席だけを0へ直す。ページ全体を閉じる必要はない。
イトは、手にある12番席の仮札を見た。
上映まで、あと一分二十一秒。
仮札を折り、受付の未成立箱へ入れた。
「ゼロへ直す」
イトはresponse cardを、残席counterへ差し込んだ。
青い1が消える。
赤い0が点灯する。

予約ボタンは、「満席」に変わった。
12番席の背には、別の場所から届いた青い予約札がついた。
二重予約は起きなかった。
ページ全部ではなく、残席だけが変わった
上映作品の絵。
開始時刻。
上映室の案内。
ページのほかの部分は、そのまま残っている。
変わったのは、残席counterと予約ボタンだけだ。
Fetch Standardは、Web platformにおけるrequest、response、それらを結ぶfetching processを定めている。JavaScriptはこうした仕組みを使ってdataを取りに行き、届いた値を必要な画面部品へ反映できる。
これは「APIを使えば常にreloadしない」という意味ではない。serviceの作り方や操作によって、ページ遷移や全体reloadが起きることもある。
今回、イトの画面で起きた順番は短い。
予約ボタンを押す JavaScriptがAPIへrequestを送る APIが現在のresponseを返す JavaScriptが残席counterを1から0へ変える
最初に見えていた1は、嘘ではなかった。
ただ、今の数字ではなくなった。
イトの席は、画面からも消えた
上映開始の音が鳴った。
12番席には、予約した人が座った。
イトの仮札は、未成立箱の中にある。
「映写操作、僕がやる」
イトは客席の後ろにある小さな操作室へ入った。
映像を送るmonitorは見える。
けれど、客席の大きなscreenは、イトの背中側だ。
最終話が始まると、操作室の窓にだけ青い光が反射した。
壁の残席counterは0のまま。
途中で1へ戻ることはなかった。
イトは、破棄した仮札と赤いresponse cardを操作卓の横へ置いた。
古い表示と現在の返事が違うとき、自分に都合のよい古い数字へ画面を戻さない。
上映室から笑い声が聞こえた。
イトは振り返らず、次の映像を送るleverへ手を置いた。
次回:返事を作るサーバーはどこにいる?
上映が終わり、イトは最後のresponse cardを裏返した。
そこには、席のdataを返した窓口の先へ続く道がある。
「この0は、誰がどこで数えて返したんだろう」
ピコが、API受付の奥へ続く重い扉を示した。
次回、ピコルート第12話。
返事を用意するサーバーは、どこで待っている?
画面のむこう側をもっと知る
物語で見たrequest、response、endpoint、JSONを用語として整理するなら、APIとはで図と一緒に確かめられます。

