1
Post Exactly Once (POE)の趣旨で、POST
の要求を重複して防御したいDjango Rest Frameworkを使用しているAPIがあります。特に、私が処理しようとしているシナリオは次のとおりです。DRFにPOST IDempotencyを適用する方法は?
- クライアントはオブジェクトを作成するためにHTTP POSTを送信します。
- APIバックエンドはオブジェクトを作成し、データベースにコミットします。
- クライアントのネットワーク接続が失われます。
- APIバックエンドは成功応答を返そうとしますが、クライアントがネットワークを失ったので、 を実行できません。
- クライアントは "成功"応答を得られないので、 要求が失敗すると仮定します。クライアントは要求を再試行し、複製された オブジェクトを作成します。
このon the mailing listに関する議論がありましたが、コードは具体化されていません。どのように人々は今この問題を解決していますか?
class IsIdempotent(permissions.BasePermission):
message = 'Duplicate request detected.'
def has_permission(self, request, view):
if request.method != 'POST':
return True
ival = request.META.get('HTTP_X_IDEMPOTENCY_KEY')
if ival is None:
return True
ival = ival[:128]
key = 'idemp-{}-{}'.format(request.user.uniuser.pk, ival)
is_idempotent = bool(cache.add(key, 'yes',
settings.IDEMPOTENCY_TIMEOUT))
if not is_idempotent:
logger.info(u'Duplicate request (non-idempotent): %s', key)
return is_idempotent
私はそうのように私のビューに追加することができます:
class MyViewSet(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet):
permission_classes = [permissions.IsAuthenticated,
IsIdempotent]