POSTリクエストを冪等処理可能にするIdempotency-Keyヘッダの提案仕様

はじめに

HTTPリクエストには冪等なものと非冪等なものがあります。

仕様上、GETやOPTIONSは冪等であり、同じリクエストであれば何度行っても問題ありません。そのため通信上エラーが起こっても自動的にリトライすることが出来ます。

一方で、POSTリクエストは冪等ではありません。同じリクエストでも複数回行うと、結果が変わってしまいます。投稿や課金APIであれば2重に処理されてしまいます。

POSTリクエスト中にタイムアウトが発生した時に、サーバに処理される前にタイムアウトしたのか、サーバが処理したあとにレスポンスを返そうとしたところでタイムアウトしたのかクライアントは区別できません。そのため、POSTリクエストを一概にリトライすることは出来ません。

そこで、リトライにより複数回同じPOSTリクエストを受け取っても、同じものと識別できるように識別子をHTTPリクエストに付加できるようにする提案が行われています。

Idempotency-Keyヘッダ

PayPalのJayadeba Jena氏らに提出された「The Idempotency HTTP Header Field」では、冪等処理用の識別子としてIdempotency-Keyヘッダを定義しています。

   Idempotency-Key: "8e03978e-40d5-43e8-bc93-6894a57f9324"

クライアントはランダムな値(UUID)などを、ヘッダ値をセットします。

サーバはこのIdempotency-Keyを元に複数回同じリクエストを受け取っても冪等処理を行います。2回目以降のリクエストに対しては、初回と同じレスポンスを返します。

サーバは一定期間後に受け取ったIdempotency-Keyの値を忘却しても問題ありません。

Idea

この提案のアイデアは様々なところで似たような事が行われています。まさに、Idempotency-Keyという名前を使ってる他、リクエストIDという名前のものからあります。

参考までに、提案仕様の中で紹介されています

  • StripeのIdempotency-Keyヘッダ
  • PayPalPayPal-Request-Idヘッダ
  • Google Standard Payments APIのrequestId

などなど。。。

おまけ

余談ですが

HTTPのリトライ/リプレイに関しては、用語及び各実装の状況に整理している Mnot先生のドキュメントが学びになります

「Retrying HTTP Requests」