mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-17 19:52:25 +03:00
feat: Add support for flexible throttling intervals
This commit introduces the ability to set custom time intervals for throttling, allowing users to specify intervals like per 5 minutes, per 2 hours, and per 5 days. This enhancement provides more flexibility in controlling request rates.
This commit is contained in:
parent
40eccb0d6c
commit
f23c37e76a
|
@ -196,6 +196,41 @@ For example, given the following views...
|
|||
User requests to either `ContactListView` or `ContactDetailView` would be restricted to a total of 1000 requests per-day. User requests to `UploadView` would be restricted to 20 requests per day.
|
||||
|
||||
---
|
||||
## Customizing Throttling Time
|
||||
|
||||
You can now set custom and flexible time periods for the throttling classes. This enhancement allows you to specify a time unit for throttling, giving you more control over how the rate limits are applied.
|
||||
|
||||
To set custom and flexible time periods for throttling, you can use the throttle_duration parameter. The throttle_duration parameter accepts a string that combines a numeric quantity and a time unit, similar to the style used in other Django settings. For example, you can set a throttling duration of "10s" for 10 seconds or "5m" for 5 minutes.
|
||||
|
||||
## Examples
|
||||
|
||||
1. Custom Time Period for User Throttling
|
||||
|
||||
To limit the rate of requests for authenticated users to 5 requests every 15 minutes, you can use the throttle_duration parameter as follows:
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_THROTTLE_RATES': {
|
||||
'user': '5/15m', # Allow 5 requests every 15 minutes for each user
|
||||
}
|
||||
}
|
||||
|
||||
2. Scoped Throttling with Custom Time
|
||||
|
||||
You can also apply custom throttling rates to specific views using the ScopedRateThrottle class. For example, to limit requests to the "write" scope to 3 requests every 30 seconds:
|
||||
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_THROTTLE_CLASSES': [
|
||||
'rest_framework.throttling.ScopedRateThrottle',
|
||||
],
|
||||
'DEFAULT_THROTTLE_RATES': {
|
||||
'user': '10/minute', # Default rate for all users
|
||||
'write': '3/30s', # Allow 3 requests every 30 seconds for "write" scope
|
||||
'custom_scope': '20/1h', # Allow 20 requests every 1 hour for a custom scope
|
||||
}
|
||||
}
|
||||
|
||||
With these enhancements, you can have more granular control over how you limit the rate of incoming requests to your API views in Django REST framework.
|
||||
|
||||
# Custom throttles
|
||||
|
||||
|
|
|
@ -94,6 +94,24 @@ class SimpleRateThrottle(BaseThrottle):
|
|||
msg = "No default throttle rate set for '%s' scope" % self.scope
|
||||
raise ImproperlyConfigured(msg)
|
||||
|
||||
def parse_quantity_and_unit(self, quantity_unit_string):
|
||||
"""
|
||||
Parse a combined quantity and unit string and return a tuple with parsed values.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the parsed values (quantity, unit).
|
||||
"""
|
||||
i = 0
|
||||
while i < len(quantity_unit_string) and quantity_unit_string[i].isnumeric():
|
||||
i += 1
|
||||
|
||||
if i == 0:
|
||||
return (1, quantity_unit_string)
|
||||
else:
|
||||
quantity = int(quantity_unit_string[:i])
|
||||
unit = quantity_unit_string[i:]
|
||||
return (quantity, unit)
|
||||
|
||||
def parse_rate(self, rate):
|
||||
"""
|
||||
Given the request rate string, return a two tuple of:
|
||||
|
@ -102,9 +120,11 @@ class SimpleRateThrottle(BaseThrottle):
|
|||
if rate is None:
|
||||
return (None, None)
|
||||
num, period = rate.split('/')
|
||||
quantity, unit = self.parse_quantity_and_unit(period)
|
||||
num_requests = int(num)
|
||||
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
|
||||
return (num_requests, duration)
|
||||
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[unit[0]]
|
||||
total_duration = duration * int(quantity)
|
||||
return (num_requests, total_duration)
|
||||
|
||||
def allow_request(self, request, view):
|
||||
"""
|
||||
|
|
|
@ -466,6 +466,14 @@ class SimpleRateThrottleTests(TestCase):
|
|||
rate = SimpleRateThrottle().parse_rate(None)
|
||||
assert rate == (None, None)
|
||||
|
||||
def test_parse_quantity_and_unit_parses_correctly(self):
|
||||
result = SimpleRateThrottle().parse_quantity_and_unit("5min")
|
||||
assert result == (5, 'min')
|
||||
result = SimpleRateThrottle().parse_quantity_and_unit("h")
|
||||
assert result == (1, 'h')
|
||||
result = SimpleRateThrottle().parse_quantity_and_unit("123s")
|
||||
assert result == (123, 's')
|
||||
|
||||
def test_allow_request_returns_true_if_rate_is_none(self):
|
||||
assert SimpleRateThrottle().allow_request(request={}, view={}) is True
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user