英文のページを写真に撮ると、読解ガイドと単語テストが1ページぶん出来上がるアプリ。 出来たページは音声・持ち出し用ファイル・学習記録・単語帳として使い回される。
抽象度 Lv.4(技術用語+システム上のやりとりまで/製品名・ライブラリ名は書かない)枠が太く、タイトルに下線のある箱は押せます。 そのブロックの中で何工程に分かれ、誰と何をやりとりしているかの詳しい解説へ進みます。 いまは 1番・2番・3番 の3つ。
ここから下は、上の図で矢印1本になっている所が、実際にはどういう通信で行われているかです。 図が「誰が何をするか」、ここが「どうやり取りしているか」にあたります。
画面(ブラウザ)とサーバーの間は、すべて HTTP でやり取りします。 取ってくるだけなら GET、送りつけて何かを起こすなら POST、 すでにあるものを丸ごと置き換えるなら PUT、一部だけ直すなら PATCH、消すなら DELETE、 という使い分けになっています。
| メソッド・パス | 担当 | 受け取る形式 | 返す形式 | 主なステータス |
|---|---|---|---|---|
POST /api/auth/login | 12番 | application/json(PIN) | application/json+Set-Cookie | 200 / 400 / 401 / 429 |
POST /api/auth/logout | 12番 | なし | 303 リダイレクト+Cookie失効 | 303 |
POST /api/extract | 1番 | multipart/form-data(画像1〜4枚+種類) | application/json | 200 / 400 / 401 / 500 |
POST /api/generate | 2〜7 | application/json(本文・タイトル・画像の鍵) | application/json(ページID) | 200 / 401 / 500 |
GET /api/guides/{id}/speech?sentence=N | 8番 | クエリ文字列 | audio/mpeg | 200 / 400 / 401 / 404 / 500 |
GET /api/guides/{id}/html | 9番 | なし | text/html(添付扱い) | 200 / 401 / 404 |
PUT /api/guides/{id}/progress | 10番 | application/json(完了日・難易度) | application/json | 200 / 400 / 401 / 500 |
PUT /api/vocabulary/mastery | 5番 | application/json(語句・覚えた/解除) | application/json | 200 / 400 / 401 / 500 |
PUT /api/vocabulary/scores | 13番 | application/json(語句ID・正誤) | application/json | 200 / 400 / 401 / 500 |
PATCH /api/guides/{id} | 7番 | application/json(タイトル・ページ番号) | application/json | 200 / 400 / 401 / 404 / 500 |
DELETE /api/guides/{id} | 7・10 | なし | application/json | 200 / 401 / 404 / 500 |
GET /api/health | ― | なし | application/json | 200 |
401 が全部の行に並んでいるのが要点です。 どのAPIも最初に「あなたは誰か」を確かめ、確かめられなければ中身の処理に入りません。 12番がすべての矢印の手前に立っている、というのはこのことです。
画面そのもの(トップ、ページ表示、単語帳、クイズ)は、サーバー側でHTMLを組み立てて
GET で返しています。上の表のAPIは、その画面から呼ばれる裏方です。
OAuth 2.0 のような外部の認可のしくみは使っていません。 GoogleやAppleに「この人を認証してください」と任せる方式ではなく、 家族で共有する暗証番号(4〜12桁の数字)1つだけで入る、自前の簡素なしくみです。 家族向けの小さなアプリなので、外部の認可基盤を持ち込むより単純にした、という判断だと読めます。
POST /api/auth/login にPINをJSONで送る。
サーバーはPINを SHA-256(どんな長さの文字列でも決まった長さの値に潰す一方向の計算。
元に戻せない)でハッシュし、あらかじめ環境変数に入れてある正解のハッシュと比べる。
PIN そのものはどこにも保存していない。HttpOnly(ページ内のJavaScriptから読めない=盗み出しにくい)、
SameSite=Lax(他サイトから飛んできた通信には付けない=なりすまし対策)、
Secure(HTTPSのときだけ送る)、有効期限180日。401。サーバー側にログイン状態の一覧は持っていない
(=どこかにセッションの表があるわけではなく、Cookieの値が正しく署名されているかだけを見る)。429(回数が多すぎます)を返す。
このカウンタはメモリ上にあるので、サーバーを再起動すると消える。この方式の帰結として、家族全員が「同じ1人の利用者」として扱われます。 誰が操作したかの区別は付きません。データも家族で1セットです。
data: 形式でJSONの中に埋め込んで送る。Cache-Control: private, max-age=31536000, immutable が付く。
「本人だけ、1年間、中身は変わらない」という意味で、2回目からは通信すら起きない。private, no-store +
Content-Disposition: attachment。毎回作り直し、ブラウザは表示せず保存する。※ この図は、2026年8月14日時点の studyguide のプログラムを読んで作成しました。
※ 抽象度は Lv.4 で統一しています。通信の方式・データの形式・認証のしくみ・ステータスコードまでは書き、製品名やライブラリ名、関数名までは踏み込みません(そこは Lv.5)。
※ 箱の隅の「元表現」は、先に作った擬人化版の解説(12人の「係」)での呼び名です。番号もそちらと同じものを使っています。13番だけは擬人化版に無い、あとから足された処理です。