先日、とあるWebAPIを設計していた時に学んだ、WebAPIの冪等性についてまとめました。
リソースの部分更新をどう設計すべきか?
そのWebAPIは、地物(ちぶつ)をリソースとして操作することができるよう設計されており、そこに新たにリソースの部分更新を実装することが今回の仕事でした。地物のデータ構造は位置情報と属性を持つ以下のような構成となっており、属性の1つの値を更新したいという要件です。
{
"id": 123,
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [136.15, 36.92]
},
"properties": {
"prop_1": "hoge",
"prop_2": 3,
"prop_3": 61224
}
}
上記のprop_1の値を”hoge”から”hogehoge”に更新するとか、prop_2の値を1インクリメントして3→4にするとか、そんな操作ですね。ちなみにPUTリクエストによる地物の更新は既に実装されていましたが、今回やりたかったのは部分更新であり、リソースの全置換え操作になるPUTとは別にインタフェースを用意する必要があります。
部分更新の実装としては以下の2パターンが考えられました。
- 地物を対象としたPATCHによる部分更新
- 地物の属性をリソースととらえPUTによる更新
PATCHは更新系メソッドの1つでリソースの部分置き換えのために定義されたメソッドなので、まさに今回のようなケースで採用される方法です。一方で、属性をリソースとして捉えることができるのであれば、PUTのみで更新系APIを実装できるので、こちらの方がシンプルなのか?という気もします。どちらで行くべきか非常に迷ったのですが、WebAPIにおける冪等性というものを学び、結論を出すことができました。
冪等性とは
冪等性とは、同じ操作を何度繰り返しても、同じ結果が得られるという性質です。RESTful APIについて言い換えるなら、「同じリクエストを何度繰り返しても同じリソース状態となること」ということです。
RESTfulでは、GETやPUTは冪等性があるメソッド、POSTやPATCHは冪等性がないメソッドとしてデザインすべきなようです。言われてみれば確かにこの辺りは納得できます。
- GET で何度参照してもリソースの状態は変わらない
- PUT で同じパラメータで何度更新をかけてもリソースの状態は変わらない
- POST はリソースを新規追加するため、リソースの状態が変わる
さて、今回の地物の部分更新を改めて振り返ると、属性値の置き換えの他にインクリメントが機能要件に含まれます。リクエストボディはおそらくこんな感じになります。
{
"action": "increment",
"path": "/properties/prop_2",
"value": 1
}
このリクエストを行うごとにリソースの状態は、属性の値が1加算される、つまり変化する訳で、インクリメントは冪等性のない操作と言えます。
そのため、今回のケースではPATCHによる部分更新の実装が望ましいと言えそうです。インクリメントが要件になければPUTでもよかったかもしれません。
まとめ
WebAPIの冪等性を意識して設計することで、APIに一貫性が生まれ使いやすいものになります。利用者が使いやすいAPIをデザインしていくためには、こういった細かな部分についても意識することが大切だなと思いました。
記事が面白かった方、参考になった方は、是非「イイね」お願いします。