はじめに
こんにちは。
HTTPの3つ目の記事です。
この記事では、HTTPメソッドの属性について調べていきます。
メソッドの属性
HTTP Methodは色んな属性を持っています。
その中でも、安全・冪等・Cacheableについて調べていきましょう。
- 安全 Safe
- 冪等 Idempotent
- キャッシュ可能 Cacheable
安全 Safe
HTTPメソッドの属性。
その1つ目は安全についてです。
ここでいう安全とは、リクエストを送信してもリソースは変更されないという意味です。
例えば、GET
メソッドは単純にデータを参照する作業を行うため、リソースの変更は起こりません。
つまり、GET
は安全属性を満足するメソッドといえます。
一方、
POST
PUT
DELETE
のようなメソッドでサーバーと通信すると、リソースの変更または、削除が起こるため、安全ではないメソッドといえます。
もちろん、多数のユーザーがGETでサーバーとの通信を行い、そのリクエストによってサーバーにログがつまり、そのログのせいで障害が発生する恐れがあります。
しかし、安全という属性はクライアントがアクセスするリソースの変更及び修正の有無についてのみ、考慮するため、このような危険性は排除されます。
安全属性を満足するメソッドはリソースの変更及び修正が起こらないため、データの一貫性を保つことを言い、このメソッドが全体的なシステムの障害から安全である意味を持ちます。
冪等 Idempotent
HTTPメソッドの属性。
2つ目は冪等についてです。
冪等は次のような数式でも表現することができます。
f(f(f(x)))=f(x)
冪等とは、同一パラメータで1回リクエストしようが、100回リクエストしようが、その結果が同じであることを言います。
ここで、重要なことは同じリクエストに対する結果が同じである場合、そのメソッドを冪等性があると表現できます。
冪等いう概念を安全と混同するかもしれませんが、簡単にその違いを説明すると、
- 安全:何回リクエストしても、リソースの変更及び修正が起こらないこと
- 冪等:リソースの変更及び修正が起きても、複数回リクエストした結果が1回リクエストしたの結果と同一であること
冪等性を満足するメソッド
まず、冪等属性を満足しているメソッドです。
- GET : データを参照するメソッドです
1回リクエストしても、100回リクエストしても、同じデータが参照されるため、GETメソッドは安全と冪等属性を両方満足するメソッドです
- PUT : PUTはBodyのデータをもとに、リソースを更新するメソッドです
何回リクエストしても、毎回Bodyのデータでリソースが更新されるため、冪等属性を満足するメソッドです
- DELETE : DELETEメソッドはリソースを削除するメソッドです
DELETEメソッドで削除リクエストを1回投げても、100回なげても、該当のリソースが削除されていて存在しない結果は同じであるため、冪等属性を満足するメソッドといえます。
冪等性を満足しないメソッド
では、POSTとPATCHはどうでしょうか?
-
POSTは冪等属性を満足していません
POSTが決済作業を行っていると想定してみましょう。POSTメソッドが何回もリクエストされると、その分支払いが行われるはずです。
つまり、リクエストごとの、結果が異なるため、冪等ではないメソッドです。 -
PATCHは設計によって、冪等属性を満足するケースも、満足しないケースもあります
例えば、{ name: "kim"}
をBodyに入れてPATCHでリクエストをすると、単純に既存リソースのnameをkimで変更するだけなので、冪等属性を満足していると言えます。
しかし、{"operation" : "add", "age" : 10}
のように、リクエストごと、ageに10を足す処理にしたい場合、1回のリクエストと100回のリクエストの結果が異なります。
この場合は、冪等属性を満足していなくなります。
💡冪等の活用
冪等という属性は、実際にHTTPメソッドを設計
するとき、役に立ちます。
冪等は、実際に自動復旧メカニズムや、サーバーがTIME OUTのような障害で正常レスポンスを返さないとき、クライアントが同じリクエストを再送信してもいいのか?の判断基準になります。
例えば、クライアントからDELETEメソッドでリクエストを投げ、リソースを削除するとき、サーバーからレスポンスが返ってこないなら?
冪等属性を満足するメソッドの場合、同じリクエストを投げることができます。
このように冪等属性は上記のようなケースでの重要な判断基準になる属性です。
⛔注意点
GETとPUT DELETEが冪等属性を満足しているとはいえ、どんな状況でもいつでも同じ結果を返すという考えはしてはいけません。
次のようなケースを想定してみましょう。
- ユーザー1: GETでAユーザーを参照、結果: {username:A, age:20}
- ユーザー2: PUTでAユーザーを変更 {username:A, age:30}
- ユーザー1: GETでAユーザーを参照、結果: {username:A, age:30}
上記のようにユーザー1がGETでAユーザーを参照します。その後、ユーザー2がAユーザーのageを30に変更します。
ユーザー1がAユーザーをまた参照すれば、ageが30のユーザー情報を受けることになります。
途中で外部によってリソースが変更され、結果が異なる場合もあります。
このような例外ケースも実際には多くあると思います。
しかし、冪等属性は外部要因による、リソースの変更は全く考慮しません。
つまり、同じユーザーが同じリクエストをする場合のみを考慮し、冪等属性を満足しているかを判断しましょう。
キャッシュ可能 Cacheable
最後に説明する属性はCacheableという属性です。
Cacheableはサーバーから返ってきたレスポンスをクライアントがキャッシュで保存し、以降同じリクエストに対して、再利用ができることを言います。
キャッシュは臨時で使えるストレージで、クライアントが1回リクエストを投げて受けたデータに対して、毎回リクエストを投げずに、以前リクエストで受けたデータを保存する場所です。
サイズが大きいIMAGEやJS CSSなどを保存します。
このようにWEBブラウザがリソースを保存できるかで、Cacheableを満足するメソッドを区分することができます。
HTTPのSPEC上、GET
HEAD
POST
PATCH
メソッドはキャッシュすることができます。
しかし、実際の業務ではGET
とHEAD
だけキャッシュとして使われるそうです。
POST
やPATCH
は主にリソースを変更する作業を行います。
冪等属性がないため、リソースが変更されている恐れがあります。
キャッシュされているリソースが変更前の古いリソースの場合、間違ったデータをユーザーに提供する危険性があります。
また、POST
には重要度が高い個人情報などが含まれる可能性があるため、キャッシュするには不適切です。
一方、GET
メソッドはURLをキーで同一リソースなのかが判断できるため、キャッシュに適切なメソッドです。
終わりに
HTTPメソッドの属性について調べてきました。
少し難しい内容でしたが、HTTPについてもっと分かった気がします。
冪等性を勉強して、次のような疑問が浮かびました。
POSTをGETみたいに、データを参照するだけの作業を行うメソッドで定義すれば、POSTは冪等属性を満足していると言えるのではないか?
なので、少しググってみました。
自分と同じ疑問を持っているエンジニアがいて、そのエンジニアがあげた質問に対して、他のエンジニアさんが回答した内容を簡単に説明すると、
冪等性はHTTPメソッドを定まれているHTTP SPECに合わせて設計した場合のみ、保証される属性です。
上記のようにHTTPメソッドの目的にあってない方法では、設計した場合は想定していないみたいです。
そのため、HTTPのAPIを設計するとき、なるべくHTTPメソッドが作られた目的に合わせて設計するのが、服作業を最小限にする方法だと思いました。