2017-06-01 2 views
1

Post Exactly Once (POE)の趣旨で、POSTの要求を重複して防御したいDjango Rest Frameworkを使用しているAPIがあります。特に、私が処理しようとしているシナリオは次のとおりです。DRFにPOST IDempotencyを適用する方法は?

  1. クライアントはオブジェクトを作成するためにHTTP POSTを送信します。
  2. APIバックエンドはオブジェクトを作成し、データベースにコミットします。
  3. クライアントのネットワーク接続が失われます。
  4. APIバックエンドは成功応答を返そうとしますが、クライアントがネットワークを失ったので、 を実行できません。
  5. クライアントは "成功"応答を得られないので、 要求が失敗すると仮定します。クライアントは要求を再試行し、複製された オブジェクトを作成します。

この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] 

答えて

1

私はカスタム権限クラスでこれを解決しました
関連する問題