冪等とは?
冪等とは、ある操作を1回行っても複数回行っても結果が同じこと、である。
HTTPメソッド
GET・HEAD
GET・HEADが冪等というのは、納得がいく。
確かに、同じリソースファイルのURLに何度GET・HEADリクエストしようとも、リソースの状態は変わらないだろう。
少し引っかかるのは、クライアントに返却されるレスポンスコードは変わるということだ。
GETのレスポンスは、リソースファイルがクライアントでキャッシュされているかによって、200(200)か304(Not Modified)になるだろう。
PUT・DELETE
PUT、DELETEについては疑問が残る。
PUTは、対象のリソースを更新するが、リソースがなければ作成する。
DELETEは、対象のリソースがあれば削除するが、リソースがなければ何もしない。
サーバーのリソースの状態を見ると、PUTの場合、1度目のリクエストでリソースが作成され、2度目のリクエストでリソースが更新される。
DELETEの場合、1度目のリクエストでリソースが削除され、2度目のリクエストはリソースが見つからず何もしない。
クライアントへのレスポンスを見ると、PUTの場合、1度目のリクエストで201 (Created)が返され、2度目のリクエストで200 (Ok)が返ってくる。
DELETEの場合、1度目のリクエストで200 (Ok)が返され、2度目のリクエストで404 (NotFound)が返ってくる。
つまり、1度目のリクエストと2度目のリクエストで、サーバー側で行われる処理(サーバー内部処理と、サーバーからクライアントへのレスポンス)が異なるのだ。
これでも、冪等(複数回行っても結果が同じ)と言っていいのだろうか?
答え
RFCの定義
4.2.2. Idempotent Methods
A request method is considered “idempotent” if the intended effect on
the server of multiple identical requests with that method is the
same as the effect for a single such request. Of the request methods
defined by this specification, PUT, DELETE, and safe request methods
are idempotent.
Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
RFCには、冪等なメソッド(Idempotent Methods)について上記の記述がある。
あるリクエストメソッドを使って、複数回の同じリクエストをした場合、サーバー上の結果が、1回のリクエストの結果と同じである場合、そのリクエストメソッドは「冪等」である。
つまり、まず「effect on the server」とあるので、クライアントへのレスポンス結果は無視して良い。
そしてサーバーの「結果」に着目すると、PUTの1回目の結果はリソースが存在するし、2回目も結果としてリソースが存在するので、サーバー上の「結果」としては同じ(=冪等)なのだ。
「effect on the server」のeffectを「効果」や「影響」の意味で捉えてしまうと、誤解してしまう。
また、当初の疑問のように、サーバーに通信した「結果」サーバー上で起こること、と捉えると混乱するので、サーバーに通信した後のサーバー上の「結果」と捉えればよい。
「安全」とは?
余談だが、PUT・DELETEは冪等であり「安全」でない、と定義されている。
「安全」とは「read-only」のことだ。
PUT・DELETEは読み込みだけでなく書き込みも行うため、当然「安全」ではない。