冪等性とは?
冪等性(Idempotent)という言葉は初めて聞くかもしれませんが、一度理解すれば簡単です。コンピュータサイエンスの世界では、冪等性は、最初の実行後に何度も適用しても結果が変わらない操作または機能の特性を指します。つまり、冪等な操作の結果は、一度実行しても複数回実行しても同じです。
たとえば、ある数に1を掛ける操作は、何度も行っても最初に1を掛けたときと同じ数になるため、冪等です。同様に、絶対値関数も同じ値に対して複数回実行しても最初と常に同じ数値が返されるため、冪等関数と呼ばれます。
HTTPメソッドの冪等性
HTTPメソッドにも冪等性が存在します。たとえば、GETは複数回呼び出しても同じ結果が返され、リソースに変更を加えないため、冪等性が保証されているメソッドです。
PUTなどのリソースを置換または更新するメソッドも冪等性を持っています。PUTは複数回呼び出しても毎回同じリソースに更新されるため、結果が変わりません。DELETEも複数回呼び出しても削除されたリソースに対する結果は変わりません。一方、サーバーデータを変更するPOSTやPATCHは呼び出すたびに異なる応答が返るため、冪等なメソッドではありません。そのため、こうした冪等でないメソッドに冪等性を提供するためには、サーバー側で冪等性を実装する必要があります。
HTTPメソッドの安全性と冪等性の違い
HTTPメソッドの主要な特性には、冪等性に加えて安全性もあります。安全性が保証されたメソッドはリソースを変更しません。GET、HEAD、OPTIONSは安全なメソッドです。 安全性が保証されたメソッドは冪等性も保証しますが、冪等性を持つメソッドが常に安全性を保証するわけではありません。たとえば、PUTやDELETEは冪等なメソッドですが、リソースに変更を加えるため、安全なメソッドではありません。
APIの視点から見る
APIの観点から冪等性を見てみましょう。冪等なAPIは、同じ要求を2回以上行っても結果が最初の要求とまったく同じである必要があります。単に返される値だけでなく、サーバーの状態(DB)にも影響を与えません。したがって、予期せぬ問題を引き起こすことなく、要求を再試行できるため、冪等性は欠陥のない安全なAPIを作成する際に重要です。
ネットワークエラーやタイムアウトによって結果を受け取れない支払いのシナリオを考えてみましょう。冪等性が保証されていない支払いAPIの場合、実際に支払いが成功したか手動で確認する必要があり、確認してみると実際には支払いが成功していなかった場合、顧客は同じ支払いを再試行する必要があります。一方、支払いAPIが冪等であれば、前の要求と同じ支払いを再試行せずに結果だけを受け取ることができるため便利です。また、誤って重複要求がされた場合(いわゆる「ダブルスペンディング」)、実際には支払いがされないため、安心して何度も要求できます。
冪等な要求かどうかの判断方法
冪等性を保証するために、APIリクエストに冪等キーを含めれば十分です。以前の要求と同じ冪等キーを持つ要求が送信されると、サーバーはこの要求を重複と判断して、実際には処理せずに最初の要求と同じ応答を返します。リクエスト本文、URLクエリパラメータ、ヘッダーのいずれかに冪等キーを含めて送信すれば、問題ありません。IETFでは、リクエストヘッダーに含める方法を標準として提案しています。また、ドメインサーバーロジックが複雑な場合、冪等性のロジックを追加することでAPIのパフォーマンス向上にも役立つことがあります。冪等キーを持つ要求は、ドメインサーバーで直接処理されないためです。