2017-06-01 62 views
1

我有一個使用Django Rest Framework的API,我想避免重複的POST請求(本着Post Exactly Once (POE)的精神)。特別是,我試圖處理的場景是:如何在DRF中強制執行POST冪等性?

  1. 客戶端發送HTTP POST來創建對象。
  2. API後端創建對象並將其提交給數據庫。
  3. 客戶端失去網絡連接。
  4. API後端嘗試發回成功響應,但無法執行 ,因爲客戶端丟失了網絡。
  5. 客戶端永遠不會獲得「成功」響應,因此假定 請求失敗。客戶端重試請求,創建一個重複的對象 。

關於這個on the mailing list有一些討論,但沒有物化代碼。人們現在如何解決這個問題?

回答

1

我解決了這個帶有自定義權限類:

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]