Home > front end >  How to allow throttle only if the response was successful?
How to allow throttle only if the response was successful?

Time:09-12

I'm trying to make throttling on OTP authentication so user can only send one message every minute

class BurstRateThrottle(AnonRateThrottle, UserRateThrottle):
    scope = 'burst'
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES':
    ('rest_framework_simplejwt.authentication.JWTAuthentication',),
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle'
    ],
    'DEFAULT_THROTTLE_RATES': {
        'burst': '1/min',
        'anon': '200/min',
        'user': '250/min',
    },
@api_view(['POST'])
@permission_classes([AllowAny])
@throttle_classes([BurstRateThrottle])
def login_send_token(request):
    ...

The problem with this is that the api gets throttled even when the phone number is wrong so I'm trying to only throttle when the OTP message is send or when the response is 200 or 201

Is there any way to access the response status code in allow_request method? or to manually execute the throttle from the function that call twilio api?

CodePudding user response:

The allow_request method is run before the method, so you only have the result of the API request after the framework decides whether the request can be run or not.

One way to do this might be to make the request to the API within the allow_request method and only add the request to the history of requests if the API request succeeded.

That does mix up where you would expect to find that code though, so an alternative would be to build the custom throttling directly into your login_send_token method.

CodePudding user response:

I solved this by converting login_send_token to a class based view

class LoginSendToken(APIView):
    permission_classes = [AllowAny]
    throttle_classes = [BurstRateThrottle]

after that I overrode initial method and commented out the self.check_throttles(request) calling

    def initial(self, request, *args, **kwargs):
        """
        Runs anything that needs to occur prior to calling the method handler.
        """
        self.format_kwarg = self.get_format_suffix(**kwargs)

        # Perform content negotiation and store the accepted info on the request
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg

        # Determine the API version, if versioning is in use.
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme

        # Ensure that the incoming request is permitted
        self.perform_authentication(request)
        self.check_permissions(request)
        # self.check_throttles(request)

and called check_throttles from my post method after serializer validation now it only checks throttling if the serializer was valid

  • Related