-
Notifications
You must be signed in to change notification settings - Fork 54
API THROTTLING
Also called Rate limiting.
It is controlling the rate of requests that clients can make to an API. This can be done for various reasons but mainly to prevent abuse of an API.
The IP address of an incoming request is used to generate a unique key to throttle against. For authenticated users, the user id is used to generate a unique key to throttle against.
In this implementation I assume you know how to setup a django project. I have setup a project with a blog app.
Throttling classes are inbuilt into the Django Rest Framework hence no library needs to be installed.
In the settings.py file add this.
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.UserRateThrottle',
'rest_framework.throttling.AnonRateThrottle'
],
'DEFAULT_THROTTLE_RATES': {
'user': '40/minute',
'anon': '20/minute'
}
From this example Unauthenticated users will only be able to make 20 requests per minute while authenticated users can make 40 requests per minute.
You pass a throttle class to the throttle_clasess attribute for class based views.
from rest_framework.generics import ListAPIView
from blog.serializers import BlogSerializer
from rest_framework.throttling import UserRateThrottle
class Blogview(ListAPIView):
serializer_class = BlogSerializer
throttle_classes = [UserRateThrottle]
In function based views use the throttle_classes decorator.
@api_view(['GET'])
@throttle_classes([UserRateThrottle])
def blog_view(request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
Now for either of these views the authenticated users will be limited to only 40 requests per minute.
You can use a throttles.py file in the app folder to write a custom throttling class for specific views as shown.
from rest_framework.throttling import UserRateThrottle
class BlogRateThrottle(UserRateThrottle):
scope = 'blog'
You also need to update the _**settings.py**_ file to this.
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.UserRateThrottle',
'rest_framework.throttling.AnonRateThrottle',
'blog.throttles.BlogRateThrottle', #new line
],
'DEFAULT_THROTTLE_RATES': {
'user': '40/minute',
'anon': '20/minute' ,
'blog': '10/minute', #new line
}
}
You can then add this custom throttle class to your view.
from rest_framework.generics import ListAPIView
from blog.serializers import BlogSerializer
from .throttles import BlogRateThrottle
class BlogView(ListAPIView):
serializer_class = BlogSerializer
throttle_classes = [BlogRateThrottle]
For this view only , authenticated users will now be limited to 10 requests per minute.
In the example below only the post request in the viewset is throttled.
from rest_framework import viewsets
from blog.serializers import BlogSerializer
from blog.models import Blog
from rest_framework.throttling import UserRateThrottle
class BlogViewSet(viewsets. ModelViewSet):
queryset = Blog.objects.all()
serializer_class = BlogSerializer
def get_throttles (self):
if self.action == 'create':
throttle_classes = [UserRateThrottle]
else:
throttle_classes = []
return [throttle() for throttle in throttle_classes]
API throttling is a cool and powerful feature , however you shouldn’t treat it as a security feature against brute forcing or denial-of-service attacks due to reasons like spoofing of IP origins.