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