HTTPメソッドの活用とHTTP API 設計２（CollectionとStore）

# はじめに

こんにちは。
HTTP、その４つ目の記事です。

この記事では、今までの勉強した内容を活用して**HTTP API**を実際に設計していきたいと思います。

# クライアントからサーバーへのデータ転送方法

以前の記事ではHTTP通信を行うときに、サーバからクライアントへのレスポンスボディーにデータを入れて通信する例について調べました。

この記事では、逆に**クライアントからサーバにリクエストを投げる**ときの例について調べていきます。

## データ転送方法
### ①クエリパラメータ

１つ目はURIを定義するときに、URIの最後に`key-value`形式で**クエリパラメータ**を付けて、データを渡す方法です。
この方法は、主に**GETメソッド**で使われ、`並び替え`や`検索時のフィルター`機能に使われます。

```
GET /search?q=hello&hl=jp HTTP/1.1
Host: www.google.com

```

上記のように、**GETメソッド**の後ろに**クエリパラメータ**（`?q=hello&hl=jp`）を付けてサーバーに渡すことができます。
例では`helloに関する日本語検索結果を参照`するためのクエリパラメータです。

もちろん、GETメソッドもBodyにデータを付けて渡すこともできますが、サポートしていないサーバもあるため、推奨されません。

### ②Message Body

二つ目は、**HTTP Message Body**にデータを入れて渡す方法です。
主に、`POST` `PUT` `PATCH`メソッドで使われます。

```
POST /members HTTP/1.1
Content-Type: application/json

{
    "username": "young",
    "age": 20
}
```

上記のようにPOSTメソッドと一緒に`Body`にデータを入れてサーバに渡すことで、
新しいリソースを登録するリクエストであることを推測できます。

## リクエストの４つのケース

実際に上記の方法を通じて、クライアントからサーバにデータを渡すケースについて説明します。


>**📌クライアントからサーバへデータを渡す４つのケース**
>
>- **静的データ参照**
>- **動的データ参照**
>- **HTML Form**
>- **HTTP API**

### 静的データ参照

１つ目は**静的データ**を参照するケースです。

実際に、静的データを参照するときは、サーバにデータを渡す必要はないが、以降のケースの理解を深めるために追加しました。

**静的データ**を参照は、主に`イメージ`や`静的テキスト`などを求めるケースを意味します。
この時、GETメソッドを使い、**静的データ**はクエリパラメータを使わずに**リソースがある場所をURIで指定**することで、簡単にリソースを取得することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/999b57f0-e540-fcd6-43f0-ec59878835e5.png)

上記ではクライアントがクエリパラメータやBodyデータの指定しなくて、`/static/start.jpg`というリソースの場所を指定しています。
クライアントから受け取ったリクエストをもとにサーバーはイメージをBodyに入れて返してくらます。

この時、レスポンスの`Body`の文字列は**イメージファイルのバイナリーデータ**です。

### 動的データ参照

**動的データ**参照は、特定の`条件`や基準によってデータを`フィルタリング`したり、`並び替え`したりする過程で、ユーザーの入力によって**動的に結果が変わる参照方法**を言います。

この場合、指定したい条件を`クエリパラメータ`や`Body`にデータを入れてサーバーに渡します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/ee9696f2-04d1-1fe9-5c85-d19defc6d410.png)

上記のようにクライアントからサーバーへ`HTTPメッセージ`を渡すと、サーバーはクエリパラメータをもとに検索結果を作成してそのデータをクライアントに返すことになります。

### HTML Form

次は**HTML Form**の`formタグ`を使ってサーバーにデータを渡す例です。

usernameとageにデータを入れて、そのデータをサーバーに渡せるボタンを持つformを作ってみました。

```html
<form action="/save" method="post">
    <input type="text" name="username" />
    <input type="text" name="age" />
    <button type="submit">Submit</button>
</form>
```
上記のように作成すると、下記のように入力フォームが作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/792f7c52-caa8-316d-7683-51b486cc7bfa.png)

formタグの`action`と`method`属性で**URI**と**HTTPメソッド**を定義します。
そして、`name`属性が**username**と**age**のinputタグを作ります。

inputタグにデータを入力し、Submitボタンを押下すると、**WEBブラウザ**がformのデータを読み込んで下記のように**HTTPメッセージを作ってくれます**。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/1c131651-1dcb-f5ae-443f-01072497a7f4.png)

`form`の場合、content-typeは**application/x-www-form-urlencoded**で設定され、`メッセージBody`にクエリパラメータと同じ`key-value`形式でデータが渡されます。
この時keyはinputタグのname属性で設定されます。


#### ✅ formの methodを GETに変更すると？

上記のようにformでもGETメソッドを使用することができます。

```html
<form action="/save" method="get">
    <input type="text" name="username" />
    <input type="text" name="age" />
    <button type="submit">Submit</button>
</form>
```
この場合、HTTPメッセージは下記のように作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/a4b18721-f1e6-e761-8e8a-cd35ab6aebc8.png)

GETの場合は、データはクエリパラメータ形式でサーバーに渡されます。

:::note warn
HTML Formは GET, POSTのみサポートされます。
:::

### HTTP API

最後は**HTTP API**を設計してデータを渡すケースです。

HTTP APIの場合、Androidやiosなどの**モバイルアプリケーション**や、HTMLが存在しない**バックエンドシステム間**の**通信**で使用されます。

また、WEBクライアントの`AJAX`のようにJavaScriptを利用した**非同期通信**でもhtml formの代わりに**HTTP API**が使用されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678234/7fe113fa-ba5f-a919-c876-bb38735a15ef.png)

API通信の`GET`以外にも`POST` `PUT` `PATCH`のようなメソッドを使えることができます。
- GET: 参照、クエリパラメータでデータ転送
- POST, PUT, PATCH: メッセージBodyでデータ転送

**HTTP API**を使ってデータを渡す場合、Content-Typeは**application/json**を使います。

# HTTP API　設計

## HTTP API 設計 - Collection

### 会員管理システム - POST基盤リソース登録

まず、会員管理システムの５つの機能を**HTTP API**で設計する例です。

良い設計をするため、各機能からリソースを把握したうえで`URI`を設計しなければならないし、そのリソースで行われたい行動によって適切なメソッドを使用して、次のように設計することができます。

✅ 会員リスト参照 /members GET
✅ 会員登録 /members POST
✅ 会員参照 /members/{id} GET
✅ 会員修正 /members/{id} PATCH PUT POST
✅ 会員削除 /members/{id} DELETE

上記の設計で重要な点は次のようです。
- 各URIは'members' 'members/{id}'のように**リソースを抽出**して設計
- 'members/{id}'のように**階層構造**で設計
- **登録**は**POSTメソッド**を使用
- **修正**は**PATCHメソッド**を使用

まず、リソース抽出については前の記事で説明をしました。
`URI設計`で重要な点は各機能から**リソースを抽出**することです。

よって、`会員参照` `会員修正` `会員削除`機能で`'会員'`が**リソース**となり、`参照` `削除`のような行為を**HTTPメソッド**で定義することが理想的な設計方法になります。

`会員リスト参照`の場合は`'/members'`で定義し、リストの中の`１つの会員`については`{id}`を通じてリソースの位置を指定するように設計をしました。

次は、`会員修正`を`PATCH`メソッドで定義したところです。

修正の場合、`PATCH`または`PUT` `POST`を使用できます。
しかし、`PATCH`メソッドを使用した理由は渡したデータに該当するカラムだけ**部分的に修正できる**メソッドであるためです。

`PUT`メソッドは**既存データを削除**したうえで、新しいデータで置き換えるため、部分的に修正したい場合にも、すべてのデータを渡さなければなりません。
もし、エンジニアのミスで一部のデータが抜けてしまうと、そのデータは削除されるため、**PATCHメソッドで修正するのが、一番安全な方法**といえます。

もちろん、場合によってはPUTメソッドでデータを修正することもできます。

最後に、`POST`メソッドを使った**会員登録**機能について説明します。

**会員登録**機能は`POST`メソッドを使用するように設計されています。
しかし、`URI`を核にすると`'/members'`でリソースの識別子を指定していないことが確認できます。

では、登録される会員のidはどこで指定してくれるのでしょうか？
その答えは、以前の記事で説明下通り、`POST`で**リソースを登録**するときは**リソースの識別子はサーバーが指定**してくれます。

つまり、`クライアント`は**新規リソースのURIが分からない**ため、会員情報が管理されるコレクション（Collection）のURIのみ指定すれば、**該当リソースの識別子はサーバーが作成**してくれます。

### コレクション（Collection）

このように、会員情報が管理されるリポジトリを`コレクション（Collection）`といいます。

`コレクション（Collection）`は**同じ種類のリソースが含まれた集合**を意味します。
これを通じて、クライアントは特定種類のリソースリストを参照したり、新しいリソースを追加することができます。

一般的に`コレクション（Collection）`は**URIパターンで表現**されます。

✅**コレクション（Collection）の役割**
1. **リソースの集合を提供**
コレクション（Collection）URIを通じて特定種類のリソースを参照できる
2. **リソース作成**
クライアントはコレクション（Collection）URIにPOSTリクエストを投げて新しいリソースが作成できます。作成されたリソースはサーバーによって唯一のURIを付与され、クライアントはこのURIで新しいリソースにアクセスできるようになります
3. **リソース参照**
個別のリソースはコレクション（Collection）の下位URIで識別されます。このURIで特定の会員情報を参照できます

✅**URI パータン**
- **コレクション URI**：コレクションを表す`URI`は一般的に**複数形名詞**でリソースの集合を表現する
  - 例：/members, /orders, /comments
- **個別リソース URI**：個別リソースの`URI`は**コレクションURIにリソース識別子を付けて**表現する
  - 例：/products/567 (IDが567の製品), /orders/890 (IDが890の注文)

上記の設計では'/members'が会員のコレクションを表現し、該当URIを通じて会員リストを参照することができます。

また、'/members/{id}'を通じて、個別リソースを参照することができ、コレクションURIにPOSTリクエストを投げて、新しいリソースを作成し、サーバーはそのリソースをlocationsヘッダーに入れてクライアントに渡します。

## HTTP API 設計 - Store
### ファイル管理システム - PUT基盤リソース登録

コレクションでAPIを設計する場合は、POSTメソッドでリソースを登録しました。
今回は`PUT`メソッドで**リソースを登録**するときの、**API設計**について調べていきます。

ファイル管理システムの５つ機能をHTTP APIで設計する例です。

✅ ファイルリスト参照 /files GET
✅ ファイル参照 /files/{filename} GET
✅ ファイル登録 /files/{filename} PUT
✅ ファイル削除 /files/{filename} DELETE
✅ ファイルBULK登録 /files  POST

ファイル管理システムもリソースである'ファイル'をもとに`URI`を設計しました。

それでは、会員管理システムとの違いは何でしょうか？
最も大きい差は**新規リソース登録**が`PUT`メソッドで行われることです。

新しいファイルを作成するときを考えてみましょう。
**新しいファイルを作成**するとき、`同じ名前のファイルがあれば、置き換え`で作成します。また、`同じ名前のファイルがないと、新しいファイル`で作成されます。

これは、`PUT`メソッドの特徴と同じです。
なお、ファイルを登録するときは、**すでにファイルも持っている状態**なので、`クライアント`は`'/files/{filename}'`のように**URIを指定**することができます。

そうすると、POSTメソッドはほかの機能で使うことが可能となります。


### ストア(Store)

上記のようにPUTメソッドで**新気リソースを登録**するときは、**作成されるリソースのURIをクライアント側でURIを指定**してくれます。これを`ストア(Store)`といいます。

`ストア(Store)`は**クライアント**が**明示的にリソースのURIを指定**してサーバーにリクエストを投げることを意味します。
このような方法はリソースの登録とアップデートを明確に処理することができます。

上記の例では、`'/files'`が`ストア(Store)`となり、**リソースを登録**する場合にはクライアントからリソースのURIを`'/files/{filename}'`のように指定しています。


## まとめ

📌 **コレクション（Collection）**

コレクション（Collection）は**同じ種類の複数リソースが含まれている集合**を意味します。
コレクション（Collection）を通じてクライアントは特定種類のリソースリストを参照したり、新しいリソースを登録します。一般的にコレクション（Collection）はURIパターンで表現します。

> **サーバーでリソースのURIを作成する（POSTでリソース登録）**

📌 **ストア（Store）**

ストア（Store）は**クライアントが明示的にリソースのURIを指定**して、サーバーにリクエストを投げる方法を意味します。
この方法は、リソースの登録とアップデートを明確に処理することができます。

> **クライアントがリソースのURIを作成する（PUTでリソース登録）**

# HTML Form 設計

最後に`HTML Form`について説明します。

`HTML Form`の場合、`GET`と`POST`メソッドのみ使用できます。
もちろん、`AJAX`のように技術を使うと、他のメソッドも使用できますが、この記事ではHTML Formのみ説明します。

それでは、`GET`と`POST`メソッドだけなのに、`修正`や`削除`のような機能は**どのように実装**することができますでしょうか？


その答えは、`POST`メソッドにあります。

次は、`GET`と`POST`メソッドを使用してAPIを設計した例です。

✅ 会員理卒参照 /members GET
✅ 会員登録フォーム /members/new GET
✅ 会員登録 /members/new, /members POST
✅ 会員参照 /members/{id} GET
✅ 会員修正フォーム /members/{id}/edit GET
✅ 会員修正 /members/{id}, /members/{id}/edit POST
✅ 会員削除 /members/{id}/delete post

前の例に比べると、多少複雑ですが`GET`と`POST`メソッドで`API`を設計しました。

まず、`GET`メソッドを使用した**機能**から確認してみましょう。

`会員リスト参照`と`会員登録フォーム` `会員参照` `会員修正フォーム`はデータやフォーム画面を要求する作業なので、`GET`メソッドでAPIを設計しました。

次は、`POST`メソッドを使用した機能です。

`会員登録` `修正` `削除`の機能は`POST`メソッドで設計され、各機能を分けるために、URIに`/new` `/edit` `/delete`を追加しました。

このようにメソッド使用に**制約**があったり、**あいまいなケース**は`POST`メソッドを使って機能の実装ができます。

### コントロール URI (Control URI)

しかし、ここで疑問がわくと思います。

確かに、`URI`を設計*するときは、**リソース**だけを**抽出**して**APIを設計**し、遂行する**行為**については**HTTPメソッド**で表現と説明しましたが、HTML formを使った例では`/new` `/edit` `/delete` のように**行為がURIに含まれている**ことが分かります。

HTML formのように、**API設計するにある制約がある場合**は、これを解決するために、**動詞のリソースを使って設計されたURI**を`コントロール URI (Control URI)`といいます。

実際に、実務では色んな状況での制約事項が存在するため、このようなコントロール URI (Control URI)をよく使うらしいです。
これはHTTP APIを設計するときも同じです。

しかし、できる限り、`APIを設計``するときは**リソースだけを使ってURIを設計知ることを推奨**します。
リソースだけではURIが設計できない場合のみコントロール URI (Control URI)を使うことにしましょう。

# 良いAPI設計するための例

最後に、良いAPIを設計するための、色んな例があるので、
下記のページを参照してください。

https://restfulapi.net/resource-naming/


# 参考サイト
https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC