フィヨルドブートキャンプの「TwitterのURLを設計する」という課題を合格したので、URL設計について学んだことをまとめた。
URL設計とは
1. リソースにどんな名前をつけるか(どんなURLにするのか) 2. 決めたURLに対して、どのHTTPメソッドを使うか
を決めること。
例
Method | Path | Description |
---|---|---|
GET | /foo | fooの一覧を表示。 |
POST | /foo | fooを受け取って追加する。 |
DELETE | /foo/123 | fooのidを受け取って削除する。 |
GET | /bar | barの一覧を表示。 |
URL設計について書く前に、リソース,URL,HTTPメソッドについて説明する。
URLとは、リソースに名前を付けたもの
リソースとは
- Web上に存在する、名前をもったありとあらゆる情報。
URLと聞くと、Webページのアドレスを思い浮かべがちだが、他にも色々ある。
例えば、Web上にある、- 写真
- 文献・論文
- 自分が登録したブックマーク
なども全てリソースである。
リソースは、人の名前などと違って必ず一意の名前(その情報だけを指す名前)でなければならない。
URLとは
- リソースに名前をつけたもの。
- URLの基本的な仕様:
uriスキーム/ホスト名/パス
。もっと複雑な仕様もある。 - TwitterのURL設計の課題では、このパスの部分を設計した。
- ホスト名が一意であること & URLがそのWebサービスの中で一意になるように設計することで、リソースは世界で一意になっている。
HTTPメソッドとは
リクエストのどこに当たるのか
(HTTP入門 - とほほのWWW入門 より引用)
リクエストは以下の3つの部品から構成されている。
1. リクエストライン
2. リクエストヘッダ
3. リクエストメッセージボディこの2. リクエストヘッダの中にHTTPメソッドが含まれている。
メソッド パス名 HTTP/バージョン
HTTPメソッド一覧
- お願いには色んな種類がある。
メソッド | 何をするか |
---|---|
GET | リソースの取得 |
POST | 子リソースの作成、リソースへのデータ追加、その他処理 |
PUT | リソースの全部更新、リソースの作成 |
PATCH | リソースの部分更新 |
DELETE | リソースの削除 |
HEAD | リソースのヘッダ (メタデータ)の取得 |
OPTIONS | リソースがサポートしているメソッドの取得 |
TRACE | プロキシ動作の確認 |
CONNECT | プロキシ動作のトンネル接続への変更 |
※ LINK / UNLINK は、HTTP/1.1 ~廃止された。
POSTとPUTの違いは、URIの決定権
- POST
- サーバー側が決める
- PUT
(鬼滅の刃 - Wikipediaより引用)
- Twitterの設計では、クライアント側がURLを決める必要性を感じなかったため、PUTを使った。
PUTは全部更新、PATCHは部分更新
PATCHメソッドは『Webを支える技術』には載っていなかったので、PUTとの違いを調べた。
PUTメソッド
- べき等である
- リソースの全部を更新
ブログの記事に例えると、記事の内容を全部変えるのがPUT。
PATCHメソッド
- べき等でない
- リソースの一部分を更新
ブログの記事に例えると、記事の台頭だけを変えるのがPATCH。
- リソースの一部更新をする場合には、そのリソース (URL)へPATCHリクエストを投げるのが、最も自然な設計。
PATCHはべき等が必ずしも保証されていないメソッドのため、PUTとDELETEを組み合わせた設計のほうが、シンプルでねき等性のある設計になることもある。
Twitterの設計では、リソースを部分的に更新するような機能の設計はしなかったので、PATCHメソッドは使わなかった。
URL設計で気をつけること
- パスのネストは最小限に抑える
- 名詞を使う
- ホスト名がこの世に一意であることと、URLが一意であることで、リソースは世界で一意となる。なので、URLを設計する時は、一意を示す設計をしなくてはいけない。
- メソッドとパスの掛け合わせが重複しないようにする
メソッドとパスの掛け合わせが重複しないようにする
最初、以下のように提出した(一部抜粋)
Method | Path | Description |
---|---|---|
GET | /user_id | ユーザーを表示する |
GET | /tweet_id | ツイートを表示する |
レビューで以下のようにご指摘をいただいた。
- この
user_id
,tweet_id
には、シンプルに考えると数字が入ってくる。 - ユーザーのプロフィール画面を表示するURLと特定のツイートを表示するURLは別物だが、数字を入れてみると、URLとメソッドの掛け合わせが重複してしまうことが分かる。
Method | Path | Description | → | 数字入り想定Path |
---|---|---|---|---|
GET | /user_id | ユーザーを表示する | → | /128 |
GET | /tweet_id | ツイートを表示する | → | /128 |
- この設計は一見、
/user_id
と/tweet_id
で区別できているように見えるが、リクエストを処理するサーバにとってはまったく同じものに見えて区別ができない。 - この問題を解決するために、サーバーがどのテーブル(リソース)を参照すれば良いか把握できるようにしてあげる必要がある。
このため、最終的に以下の設計にした。
Method | Path | Description |
---|---|---|
GET | /users/:user_id | ユーザーを表示する |
GET | /tweets/:tweet_id | 特定のツイートを表示する |
これなら、idの部分が重複しても、
/users/123
/tweets/123
となり、区別できる。
感想
- 最初、Twitterの何がリソースに当たるか分からず、混乱した。
- ツイートの新規作成画面を取得するリクエストと、ツイートを行うリクエストは、ブートキャンプの日報作成時のURLを参考にさせていただいた。
- URL設計は、Sinatraのメモアプリ作成課題でも行うので、大事。
- 設計はコードを書く時と同じで正解が一つでないので、
課題修正時に、「なぜその設計にしようと思ったか?」を述べるようにしたら、メンターさんから、以下のように仰っていただけたのが嬉しかった🥰- 理由を述べることができるというのはとても大事な能力
- ぜひ今後も「どうしてこういう設計/実装になったの?」と聞かれた時に答えられる姿勢で進めてほしい
参考書籍・記事
- 『Webを支える技術 -HTTP、URI、HTML、そしてREST 』(山本陽平 著,技術評論社,2010年出版,全400ページ)
- Minimize path nesting · HTTP API Design
- リソースの一部更新におけるURL設計
- HTTPメソッド(CRUD)についてまとめた
- REST入門 基礎知識 - Qiita
- HTTPリクエスト - 「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
- 初めてのLT - 柴ブログ
- Rails のルーティング - Railsガイド