Custom throttle response in django rest system

I use DRF to rest apis, so now I am applying throttling to my apis. To do this, I created the following throttle areas

  • userRateThrottle

  • anonRateThrottle

  • burstRateThrottle

  • perViewsThrottles (view dependent)

I am currently getting the below answer:

{"detail":"Request was throttled. Expected available in 32.0 seconds."}

I want to answer something like this:

{"message":"request limit exceeded","availableIn":"32.0 seconds","throttleType":"type"}

There is nothing to configure in DRF documents. How can I customize my answer as required?

+4
source share
2 answers

, Throttled .

from rest_framework.views import exception_handler
from rest_framework.exceptions import Throttled

def custom_exception_handler(exc, context):
    # Call REST framework default exception handler first,
    # to get the standard error response.
    response = exception_handler(exc, context)

    if isinstance(exc, Throttled): # check that a Throttled exception is raised
        custom_response_data = { # prepare custom response data
            'message': 'request limit exceeded',
            'availableIn': '%d seconds'%exc.wait
        }
        response.data = custom_response_data # set the custom response data on response object

  return response

DRF.

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}

, throttleType, DRF, DRF Throttled , - Throttle . Throttled , throttle_class .

+10

, , , Rahul , throttleType :

:

  • rest_exceptions.py :

    import math
    import inspect
    from django.utils.encoding import force_text
    from django.utils.translation import ungettext
    from rest_framework import exceptions, throttling
    
    class CustomThrottled(exceptions.Throttled):
    
        def __init__(self, wait=None, detail=None, throttle_instance=None):
            if throttle_instance is None:
                self.throttle_instance = None
            else:
                self.throttle_instance = throttle_instance
    
            if detail is not None:
                self.detail = force_text(detail)
            else:
                self.detail = force_text(self.default_detail)
    
            if wait is None:
                self.wait = None
            else:
                self.wait = math.ceil(wait)
    

    kwarg , ( ). , , wait. , .

  • , . rest_viewsets.py :

    from rest_framework import viewsets
    from .rest_exceptions import CustomThrottled
    
    class ThrottledViewSet(viewsets.ViewSet):
        """
        Adds customizability to the throtted method for better clarity.
        """
    
        throttled_exception_class = CustomThrottled
    
        def throttled(self, request, wait, throttle_instance=None):
            """
            If request is throttled, determine what kind of exception to raise.
            """
            raise self.get_throttled_exception_class()(wait, detail=self.get_throttled_message(request),
                                                       throttle_instance=throttle_instance)
    
        def get_throttled_message(self, request):
            """
            Add a custom throttled exception message to pass to the user.
            Note that this does not account for the wait message, which will be added at the
            end of this message.
            """
            return None
    
        def get_throttled_exception_class(self):
            """
            Return the throttled exception class to use.
            """
            return self.throttled_exception_class
    
        def check_throttles(self, request):
                """
                Check if request should be throttled.
                Raises an appropriate exception if the request is throttled.
                """
                for throttle in self.get_throttles():
                    if not throttle.allow_request(request, self):
                        self.throttled(request, throttle.wait(), throttle_instance=throttle)
    
  • , , , viewet, , , , , . views.py, ( , MyViewset):

    from .rest_viewsets import ThrottledViewSet
    from rest_framework import throttling
    
    class MyViewset(ThrottledViewSet):
        throttle_classes = (throttling.userRateThrottle,)  # Add more here as you wish
        throttled_exception_class = CustomThrottled  # This is the default already, but let be specific anyway
    
        def get_throttled_message(self, request):
            """Add a custom message to the throttled error."""
            return "request limit exceeded"
    
  • , , . , . , , . :

    from rest_framework.views import exception_handler
    from .rest_exceptions import CustomThrottled
    
    def custom_exception_handler(exc, context):
        # Call REST framework default exception handler first,
        # to get the standard error response.
        response = exception_handler(exc, context)
    
        if isinstance(exc, CustomThrottled): # check that a CustomThrottled exception is raised
            custom_response_data = { # prepare custom response data
                'message': exc.detail,
                'availableIn': '%d seconds'%exc.wait,
                'throttleType': type(exc.throttle_instance).__name__
            }
            response.data = custom_response_data # set the custom response data on response object
    
      return response
    

    , .

  • , : DRF:

    REST_FRAMEWORK = {
        'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
    }
    
0

Source: https://habr.com/ru/post/1610155/


All Articles