はじめに
こんにちは。
HTTP、その4つ目の記事です。
この記事では、今までの勉強した内容を活用してHTTP APIを実際に設計していきたいと思います。
クライアントからサーバーへのデータ転送方法
以前の記事ではHTTP通信を行うときに、サーバからクライアントへのレスポンスボディーにデータを入れて通信する例について調べました。
この記事では、逆にクライアントからサーバにリクエストを投げるときの例について調べていきます。
データ転送方法
①クエリパラメータ
1つ目は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
にデータを入れてサーバに渡すことで、
新しいリソースを登録するリクエストであることを推測できます。
リクエストの4つのケース
実際に上記の方法を通じて、クライアントからサーバにデータを渡すケースについて説明します。
📌クライアントからサーバへデータを渡す4つのケース
- 静的データ参照
- 動的データ参照
- HTML Form
- HTTP API
静的データ参照
1つ目は静的データを参照するケースです。
実際に、静的データを参照するときは、サーバにデータを渡す必要はないが、以降のケースの理解を深めるために追加しました。
静的データを参照は、主にイメージ
や静的テキスト
などを求めるケースを意味します。
この時、GETメソッドを使い、静的データはクエリパラメータを使わずにリソースがある場所をURIで指定することで、簡単にリソースを取得することができます。
上記ではクライアントがクエリパラメータやBodyデータの指定しなくて、/static/start.jpg
というリソースの場所を指定しています。
クライアントから受け取ったリクエストをもとにサーバーはイメージをBodyに入れて返してくらます。
この時、レスポンスのBody
の文字列はイメージファイルのバイナリーデータです。
動的データ参照
動的データ参照は、特定の条件
や基準によってデータをフィルタリング
したり、並び替え
したりする過程で、ユーザーの入力によって動的に結果が変わる参照方法を言います。
この場合、指定したい条件をクエリパラメータ
やBody
にデータを入れてサーバーに渡します。
上記のようにクライアントからサーバーへHTTPメッセージ
を渡すと、サーバーはクエリパラメータをもとに検索結果を作成してそのデータをクライアントに返すことになります。
HTML Form
次はHTML Formのformタグ
を使ってサーバーにデータを渡す例です。
usernameとageにデータを入れて、そのデータをサーバーに渡せるボタンを持つformを作ってみました。
<form action="/save" method="post">
<input type="text" name="username" />
<input type="text" name="age" />
<button type="submit">Submit</button>
</form>
上記のように作成すると、下記のように入力フォームが作成されます。
formタグのaction
とmethod
属性でURIとHTTPメソッドを定義します。
そして、name
属性がusernameとageのinputタグを作ります。
inputタグにデータを入力し、Submitボタンを押下すると、WEBブラウザがformのデータを読み込んで下記のようにHTTPメッセージを作ってくれます。
form
の場合、content-typeはapplication/x-www-form-urlencodedで設定され、メッセージBody
にクエリパラメータと同じkey-value
形式でデータが渡されます。
この時keyはinputタグのname属性で設定されます。
✅ formの methodを GETに変更すると?
上記のようにformでもGETメソッドを使用することができます。
<form action="/save" method="get">
<input type="text" name="username" />
<input type="text" name="age" />
<button type="submit">Submit</button>
</form>
この場合、HTTPメッセージは下記のように作成されます。
GETの場合は、データはクエリパラメータ形式でサーバーに渡されます。
HTML Formは GET, POSTのみサポートされます。
HTTP API
最後はHTTP APIを設計してデータを渡すケースです。
HTTP APIの場合、Androidやiosなどのモバイルアプリケーションや、HTMLが存在しないバックエンドシステム間の通信で使用されます。
また、WEBクライアントのAJAX
のようにJavaScriptを利用した非同期通信でもhtml formの代わりにHTTP APIが使用されます。
API通信のGET
以外にもPOST
PUT
PATCH
のようなメソッドを使えることができます。
- GET: 参照、クエリパラメータでデータ転送
- POST, PUT, PATCH: メッセージBodyでデータ転送
HTTP APIを使ってデータを渡す場合、Content-Typeはapplication/jsonを使います。
HTTP API 設計
HTTP API 設計 - Collection
会員管理システム - POST基盤リソース登録
まず、会員管理システムの5つの機能を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'
で定義し、リストの中の1つの会員
については{id}
を通じてリソースの位置を指定するように設計をしました。
次は、会員修正
をPATCH
メソッドで定義したところです。
修正の場合、PATCH
またはPUT
POST
を使用できます。
しかし、PATCH
メソッドを使用した理由は渡したデータに該当するカラムだけ部分的に修正できるメソッドであるためです。
PUT
メソッドは既存データを削除したうえで、新しいデータで置き換えるため、部分的に修正したい場合にも、すべてのデータを渡さなければなりません。
もし、エンジニアのミスで一部のデータが抜けてしまうと、そのデータは削除されるため、PATCHメソッドで修正するのが、一番安全な方法といえます。
もちろん、場合によってはPUTメソッドでデータを修正することもできます。
最後に、POST
メソッドを使った会員登録機能について説明します。
会員登録機能はPOST
メソッドを使用するように設計されています。
しかし、URI
を核にすると'/members'
でリソースの識別子を指定していないことが確認できます。
では、登録される会員のidはどこで指定してくれるのでしょうか?
その答えは、以前の記事で説明下通り、POST
でリソースを登録するときはリソースの識別子はサーバーが指定してくれます。
つまり、クライアント
は新規リソースのURIが分からないため、会員情報が管理されるコレクション(Collection)のURIのみ指定すれば、該当リソースの識別子はサーバーが作成してくれます。
コレクション(Collection)
このように、会員情報が管理されるリポジトリをコレクション(Collection)
といいます。
コレクション(Collection)
は同じ種類のリソースが含まれた集合を意味します。
これを通じて、クライアントは特定種類のリソースリストを参照したり、新しいリソースを追加することができます。
一般的にコレクション(Collection)
はURIパターンで表現されます。
✅コレクション(Collection)の役割
-
リソースの集合を提供
コレクション(Collection)URIを通じて特定種類のリソースを参照できる -
リソース作成
クライアントはコレクション(Collection)URIにPOSTリクエストを投げて新しいリソースが作成できます。作成されたリソースはサーバーによって唯一のURIを付与され、クライアントはこのURIで新しいリソースにアクセスできるようになります -
リソース参照
個別のリソースはコレクション(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設計について調べていきます。
ファイル管理システムの5つ機能を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を設計するための、色んな例があるので、
下記のページを参照してください。
参考サイト