はじめに
こんにちは。
WEBエンジニアのための、HTTP。2つ目の記事です。
この記事では、HTTPのメソッドについて説明をしたいと思います。
今後、作成するHTTP APIでも使える重要な内容になるため、各メソッドが持っている特徴と、それらの違いについてしっかり把握しておくことが大事だと思います。
HTTP API 設計
各メソッドについて説明する前に、HTTP API
を設計する次の例を見て、どのように設計するのがいいのかを一緒に考えてみましょう。
要求事項は次のようです。
会員情報を管理するAPIを設計
- 会員リスト参照
- 会員参照
- 会員登録
- 会員修正
- 会員削除
設計1
API設計の経験がないエンジニアがいると、想定しましょう。
初級エンジニアはいろいろ工夫をしたうえで、各機能の名前を参考に次のようなAPIを作成しました。
- 会員リスト参照 /read-member-list
- 会員参照 /read-member-by-id
- 会員登録 /create-member
- 会員修正 /update-member
- 会員削除 /delete-member
上記のように設計したURIを見ると、各URIがどのような作業を行うのかを一目で分かると思います。
しかし、このような設計がほんとにいい設計でしょうか?
URI
とはWEB上にある資源。つまり、リソースの位置を表す唯一の住所です。
そのため、APIを設計するうえで、重要なのはリソースを識別することです。
リソースの識別
どうすれば、各機能からリソースが識別できるのでしょうか?
まず、要求事項について考えてみましょう。
- 会員リスト参照
- 会員参照
- 会員登録
- 会員修正
- 会員削除
よく見ると、参照・登録修正・削除などの行為が、会員を対象に行われていることが、分かります。
つまり、リソースを識別するためには、機能からリソースと、リソースを対象に行われる行為を分離することが重要です。
今回の要求事項は次のように分離することができます。
- リソース:会員
- 行為:参照・登録・修正・削除
設計2
要求事項の中で、会員がリソースであることが分かったので、再びAPIを設計してみましょう。
設計2ではURIにリソースをマッピングし、設計をしてみましょう。
リソースを識別し、URIを階層構造で設計してみました。
- 会員リスト参照 /members
- 会員参照 /members/{id}
- 会員登録 /members/{id}
- 会員修正 /members/{id}
- 会員削除 /members/{id}
上記のURIを見ると、会員リスト参照は/members
、単一会員の参照・登録・修正・削除については、/members
の後に、/{id}
を付けて設計を行いました。
しかし、この設計も完璧な設計ではあります。
よく見ると、参照・登録・修正・削除のURIが同一であることが分かります。
すると、これらをどうやって使い分けることができますか?
このような状況で使うのが、HTTP Methodです。
HTTP Method
- GET:リソース参照
- POST:リクエストのデータを処理 ※主に登録で使用
- PUT:リソースの置き換え ※リソースがない場合、リソースを生成
- PATCH:リソースの部分的な変更
- DELETE:リソース削除
上記のメソッド以外にも、HEAD
OPTIONS
CONNECT
TRACE
等もありますが、この記事では説明しません。
GET
GET /search?q=hello&hl=jp HTTP/1.1
Host: www.google.com
GET
メソッド名前通り、リソースを参照するために、使われます。
検索を行うときに、サーバーに送信したいデータはクエリ(クエリパラメータ、クエリストリング)を通じて送ることができます。
GETはMessage Bodyを用いてデータを渡す方法もありますが、サポートしないサーバーもあるため、推奨はされていません。
このようにGETでリソースを参照するとき、検索条件などがある場合、クエリパラメータを作成してリクエストを送ります。
GETを用いた会員参照機能の流れについて確認してみましょう。
クライアントからGETメソッドとURIで100番会員の情報をサーバーに要求しています。
サーバーはメッセージを受け取った後、メッセージに該当するリソースをDBから取り出します。
その後、取り出した、100番会員のリソースをBodyに入れて、レスポンスを作成し、クライアントに送ります。
今回の例ではJSON
を使いましたが、リソースタイプはHTML
IMAGE
XML
も使えます。
POST
次は、POSTメソッドです。
POST /members HTTP/1.1
Content-Type: application/json
{
"userName":"hello",
"age":20
}
POST
メソッドはクライアントがサーバーにデータを送信して、そのデータに対する処理を要求する際に使います。
つまり、Message Bodyにデータを入れて送信すると、サーバーはMessage Bodyを通じて送信されてデータを処理するすべての機能を行います。
サーバーで行われる処理はクライアントとサーバーが事前に定義した作業を意味し、主にリソースの登録やプロセスの処理を意味します。
上記のHTTPメッセージを見ると、POSTメソッドと、/members
を定義し、Bodyにデータが格納されていることが分かります。
事前にPOST
に対しての作業を会員登録と定義した場合、これは、クライアントが送信した、「Bodyのでーたを新規登録してほしい」という要求になります。
次の例で確認してみましょう。
クライアントはBodyにデータを入れてサーバーに送ります。
この時、/members
にPOSTメソッドでリクエストが送られたら、新規登録する行うと定義されていれば、サーバーはBodyのデータをもとに新規会員を登録するはずです。
サーバーはBodyのデータをDBに保存した後に、新規ID(識別子)を生成します。
ここで、IDが100の会員が作成されます。
会員を登録した後、サーバーはPOST処理の結果をレスポンセに入れてクライアントに返します。
POSTのデータ処理について
POST
のデータに対する処理は、特に決まっていません。各リソースごとに定義しないといけません。
POST
はクライアントとサーバーがリソースに対して、事前に定義した作業を行います。
つまり、POSTはリソースを登録する作業のみ、行われるわけではありません。
例えば、HTMLのFormタグに入力されたデータで会員登録・商品の注文、ブログやニュースのような記事の作成にも使われます。
また、新規のリソース作成し、既存のリソースにデータを追加する作業にも使うことができます。
POSTが使われるケースについて簡単に説明すると次のようです。
-
新規リソース生成(登録)
- サーバーでまだ、識別していない新規リソース生成
-
リクエストデータ処理
- プロセスを処理する場合
-
ほかのHTTPメソッドで処理が困難である場合
- JSONデータを送信するとき、GETメソッドを使えない場合
- まず、HTTPめっそどの選択が難しい場合、POSTを使う
- サーバー内部的にプロセスの変更がある場合
[注文画面から決済完了 -> 配達開始 -> 配達完了]上記のように単純にリソースの生成だけでなく、プロセスの状態が変更するときにも使えます。
このケースは、POSTの結果で新規リソースが生成されない場合もあります。
例) POST /orders/{orderId}/start-delivery
実際に、リソースだけでURIを設計することは難しくて、最後に動詞を加えてURIを設計する方法もあります。このようなURIをControl URI
といいます。
PUT
次はPUT
メソッドです。
PUT /members/100 HTTP/1.1
Content-Type: application/json
{
"userName":"hello",
"age":20
}
PUTはリソースを置き換える作業を行います。
つまり、リソースが存在すれば、Bodyのデータで既存のデータを置き換え、リソースが存在しなければ、新規リソースを作成します。
ファイルをコピペするときを思い出すと理解がつくと思います。
同じファイルがある場合は、そのファイルを置き換えて、なければペーストを行います。
PUTはリソースの部分的な修正ができない。
PUTメソッドはリソースをそのまま置き換えるため、既存リソースの部分的な修正のため、PUTを使うと、Bodyの入っているデータ以外のデータは削除されます。
そのため、PUTメソッドで部分的な修正を行いたい場合は、リソースのすべてのデータを作成してから送信しなければなりません。
また、PUTとPOSTの違いは、クライアントがリソースの識別子を知っているところです。
以前のPOSTの例では/members
でリソースの住所を指定してます。
一方、PUTは/members/100
で会員の識別子を知っていることが分かります。
では、次の例を通じてPUTについて説明します。
リソースが存在する場合
クライアントはリソースの住所を指定し、JSONデータをBodyに入れて送信しました。
既に、サーバーには100番会員のリソースが存在しています。
この場合、既存リソースは新しいデータで置き換えます。
注意!!リソースが置き換えます。
もし、何かの間違いで、クライアントから{"age":20}
のデータのみ送信されたら、usernameは削除され、ageのみ保存されるようになります。
リソースが存在しない場合
クライアントがデータをサーバーに送信しました。
サーバーには100番の会員が存在しないため、Bodyで送信されたデータをもとに新規リソースが作成されます。
PATCH
そうすると、リソースの部分的な修正が必要な場合はどうすればいいでしょうか?
この場合、PATCH
メソッドを使えます。
PATCH /members/100 HTTP/1.1
Content-Type: application/json
{
"age":50
}
PATCH
はリソースの部分的な修正が必要な場合使えるメソッドです。
修正したいデータをBodyでサーバーに送信すると、送信されたデータのみ修正され、他のデータは保持できます。
クライアントからURIを指定し、修正したいデータをBodyに入れてサーバーに送信します。
サーバーは100番会員のageをBodyのデータで修正を行います。
データを部分的に修正したい場合は、PUTよりPATCHを使うのが、もっと修正に近い意味を伝えることができます。
しかし、PATCHをサポートしていない、サーバーも存在するはずです。
その場合はPOSTを使ってデータを修正することができます。
DELETE
最後にDELETE
メソッドについて説明します。
DELETE /members/100 HTTP/1.1
Host: localhost:8080
DELETE
メソッドは名前通り、リソースを削除する機能を行います。
では、次の例を見てみましょう。
クライアントは削除したいリソースの識別子を加えて、サーバーに送信します。
サーバーは送信されたリソースの識別子をもとに、リソースの削除を行います。
参考サイト