HelloGitHub- dream chasers

Limiting, as the name suggests, limits the frequency of calls to the API. Each API call costs the server resources, so many apis are not open to users an infinite number of times, after a certain number of requests are no longer allowed to access, or for a period of time, only as many times as the API specifies.

Currently, our interface does not have any traffic limiting measures, and as soon as the user calls the interface, the server processes and returns data. To prevent the interface from being overrun by malicious users, we limit traffic on the interface.

In the previous article we cleaned up the interface and added the cache. Our traffic limiting policy can be determined according to the Settings of the cache. This can be relaxed for interfaces with long cache times, and restricted strictly for interfaces that may need to access the database.

Django-rest-framework provides two classes for limiting traffic, AnonRateThrottle and UserRateThrottle. The AnonRateThrottle command is used to restrict the access frequency of unauthenticated users based on their IP addresses. UserRateThrottle is used to restrict the authenticated user, that is, the registered user of the site (currently our blog does not support login registration, so this class is not useful). Both classes can be used in the same API to enforce different traffic limiting policies for different types of users.

The frequency limits of the two helper classes are specified in the format of “maximum access times/time interval”. For example, if set to 10/min, the interface is allowed to be called a maximum of 10 times in a minute. Calls that exceed the limit will throw exceptions.Throttled, and the client receives too many requests 429 in response.

Again, let’s analyze our traffic limiting policy based on the existing API list and cache:

The interface name URL Current limiting
The article lists /api/posts/ 10/min
The article details /api/posts/:id/ 10/min
Classification list /categories/ 10/min
The tag list /tags/ 10/min
List of archive dates /posts/archive/dates/ 10/min
Comment on the list /api/posts/:id/comments/ 10/min
Article Search Results /api/search/ 5/min

Supplementary notes:

  1. Home page article list API: there is cache, normal users will not visit too often, limit 10/min
  2. Article details API: there is cache, normal users will not access too often, limit 10/min
  3. List of categories, labels, archive dates, with cache, normal users will not access too often, limit 10/min
  4. List of comments, cached, not accessed too frequently by normal users, limited to 10/min
  5. Search the interface. Normal users will not visit it frequently. Limit 5/min

After the interface traffic limiting rules are established, it is ok to set the traffic limiting assistant class.

Traffic limiting can be enabled globally or in a single view. The setting of a single view overrides the global setting. Since almost all interfaces limit traffic to anonymous users, the global Settings are done first. Locate the REST_FRAMEWORK configuration item in the project configuration file common.py and add the following configuration:

# filename="common.py"
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle'.]. 'DEFAULT_THROTTLE_RATES': {  'anon': '10/min'. } } Copy the code

In this way, the access frequency of all interfaces is set to 10/min.

For the search interface, we set the limiting rule to 5/min, so we set the limiting class for this view set separately.

In the global configuration, the default limiting frequency is set to 10/min. In order to set the default limiting frequency to 5/min, we need to inherit the THROTTLE_RATES property of the original limiting class and override it. The code is very simple:

# filename="blog/views.py"
from rest_framework.throttling import AnonRateThrottle

class PostSearchAnonRateThrottle(AnonRateThrottle):
    THROTTLE_RATES = {"anon": "5/min"}
Copy the code

Then specify the throttle_classes class in the view set of the search interface:

# filename="blog/views.py"
class PostSearchView(HaystackViewSet):
    index_models = [Post]
    serializer_class = PostHaystackSerializer
    throttle_classes = [PostSearchAnonRateThrottle]
Copy the code

Let’s see if this really works.

< span style = “font-size: 10.5pt; color: RGB (74, 74, 74);

HTTP 429 Too Many Requests Allow: GET, HEAD, OPTIONS Content-Type: application/json Retry-After: 52 Vary: Accept

{“detail”: “The request exceeded the speed limit. Expected available in 52 seconds.” }

A minute later the access was restored.

Let’s test the search interface again, call/API /v1/search/? Text =markdown. After five consecutive refresh times, the interface returns the following result:

HTTP 429 Too Many Requests Allow: GET, HEAD, OPTIONS Content-Type: application/json Retry-After: 26 Vary: Accept

{“detail”: “The request exceeded the speed limit. Expected available in 26 seconds.” }

A minute later the access was restored.

!!!!!!!!! I need your attention.

Because the search function depends on Elasticsearch service, you need to run the Docker container when testing the interface. For details, see drF-Haystack.


Pay attention to the public account to join the communication group