annotate roundup/rate_limit.py @ 8580:5cba36e42b8f

chore: refactor replace urlparse with urlsplit and use urllib_ Python docs recommend use of urlsplit() rather than urlparse(). urlsplit() is a little faster and doesn't try to split the path into path and params using the rules from an obsolete RFC. actions.py, demo.py, rest.py, client.py Replace urlparse() with urlsplit() actions.py urlsplit() produces a named tuple with one fewer elements (no .param). So fixup calls to urlunparse() so they have the proper number of elements in the tuple. also merge url filtering for param and path. demo.py, rest.py: Replace imports from urlparse/urllib.parse with roundup.anypy.urllib_ so we use the same interface throughout the code base. test/test_cgi.py: Since actions.py filtering for invali urls not split by path/param, fix tests for improperly quoted url's.
author John Rouillard <rouilj@ieee.org>
date Sun, 19 Apr 2026 22:58:59 -0400
parents 224ccb8b49ca
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
1 # Originaly from
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
2 # https://smarketshq.com/implementing-gcra-in-python-5df1f11aaa96?gi=4b9725f99bfa
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
3 # with imports, modifications for python 2, implementation of
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
4 # set/get_tat and marshaling as string, support for testonly
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
5 # and status method.
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
6
8472
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 7590
diff changeset
7 from datetime import datetime, timedelta
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
8
7590
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
9 try:
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
10 # used by python 3.11 and newer use tz aware dates
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
11 from datetime import UTC
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
12 dt_min = datetime.min.replace(tzinfo=UTC)
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
13 # start of unix epoch
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
14 dt_epoch = datetime(1970, 1, 1, tzinfo=UTC)
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
15 fromisoformat = datetime.fromisoformat
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
16 except ImportError:
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
17 # python 2.7 and older than 3.11 - use naive dates
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
18 dt_min = datetime.min
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
19 dt_epoch = datetime(1970, 1, 1)
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
20 def fromisoformat(date):
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
21 # only for naive dates
8472
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 7590
diff changeset
22 return datetime.strptime(date, "%Y-%m-%dT%H:%M:%S.%f")
7590
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
23
7587
8f29e4ea05ce fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 5996
diff changeset
24 from roundup.anypy.datetime_ import utcnow
8f29e4ea05ce fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 5996
diff changeset
25
5996
69a35d164a69 Make rate_limit.py pass flake8.
John Rouillard <rouilj@ieee.org>
parents: 5937
diff changeset
26
5739
e225f403cc35 Run pylint and clean up it's issues. Also fix comment.
John Rouillard <rouilj@ieee.org>
parents: 5722
diff changeset
27 class RateLimit: # pylint: disable=too-few-public-methods
8472
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 7590
diff changeset
28
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 7590
diff changeset
29 __slots__ = ("count", "period")
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 7590
diff changeset
30
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
31 def __init__(self, count, period):
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
32 self.count = count
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
33 self.period = period
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
34
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
35 @property
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
36 def inverse(self):
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
37 return self.period.total_seconds() / self.count
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
38
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
39
5722
2f116ba7e7cf Rename Store class in rate_limit.py to Gcra. The name Store makes no
John Rouillard <rouilj@ieee.org>
parents: 5717
diff changeset
40 class Gcra:
8472
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 7590
diff changeset
41
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 7590
diff changeset
42 __slots__ = ("memory",)
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 7590
diff changeset
43
5739
e225f403cc35 Run pylint and clean up it's issues. Also fix comment.
John Rouillard <rouilj@ieee.org>
parents: 5722
diff changeset
44 def __init__(self):
e225f403cc35 Run pylint and clean up it's issues. Also fix comment.
John Rouillard <rouilj@ieee.org>
parents: 5722
diff changeset
45 self.memory = {}
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
46
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
47 def get_tat(self, key):
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
48 # This should return a previous tat for the key or the current time.
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
49 if key in self.memory:
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
50 return self.memory[key]
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
51 else:
7590
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
52 return dt_min
5996
69a35d164a69 Make rate_limit.py pass flake8.
John Rouillard <rouilj@ieee.org>
parents: 5937
diff changeset
53
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
54 def set_tat(self, key, tat):
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
55 self.memory[key] = tat
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
56
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
57 def get_tat_as_string(self, key):
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
58 # get value as string:
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
59 # YYYY-MM-DDTHH:MM:SS.mmmmmm
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
60 # to allow it to be marshalled/unmarshaled
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
61 if key in self.memory:
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
62 return self.memory[key].isoformat()
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
63 else:
7590
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
64 return dt_min.isoformat()
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
65
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
66 def set_tat_as_string(self, key, tat):
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
67 # Take value as string and unmarshall:
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
68 # YYYY-MM-DDTHH:MM:SS.mmmmmm
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
69 # to datetime
7590
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
70 self.memory[key] = fromisoformat(tat)
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
71
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
72 def update(self, key, limit, testonly=False):
5739
e225f403cc35 Run pylint and clean up it's issues. Also fix comment.
John Rouillard <rouilj@ieee.org>
parents: 5722
diff changeset
73 '''Determine if the item associated with the key should be
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
74 rejected given the RateLimit limit.
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
75 '''
7587
8f29e4ea05ce fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 5996
diff changeset
76 now = utcnow()
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
77 tat = max(self.get_tat(key), now)
5996
69a35d164a69 Make rate_limit.py pass flake8.
John Rouillard <rouilj@ieee.org>
parents: 5937
diff changeset
78 separation = (tat - now).total_seconds()
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
79 max_interval = limit.period.total_seconds() - limit.inverse
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
80 if separation > max_interval:
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
81 reject = True
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
82 else:
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
83 reject = False
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
84 if not testonly:
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
85 new_tat = max(tat, now) + timedelta(seconds=limit.inverse)
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
86 self.set_tat(key, new_tat)
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
87 return reject
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
88
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
89 def status(self, key, limit):
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
90 '''Return status suitable for displaying as headers:
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
91 X-RateLimit-Limit: calls allowed per period. Period/window
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
92 is not specified in any api I found.
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
93 X-RateLimit-Limit-Period: Non standard. Defines period in
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
94 seconds for RateLimit-Limit.
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
95 X-RateLimit-Remaining: How many calls are left in this window.
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
96 X-RateLimit-Reset: window ends in this many seconds (not an
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
97 epoch timestamp) and all RateLimit-Limit calls are
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
98 available again.
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
99 Retry-After: if user's request fails, this is the next time there
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
100 will be at least 1 available call to be consumed.
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
101 '''
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
102
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
103 ret = {}
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
104 tat = self.get_tat(key)
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
105 # static defined headers according to limit
5937
5d0873a4de4a fix rate limit headers - were ints/floats need to be strings
John Rouillard <rouilj@ieee.org>
parents: 5739
diff changeset
106 # all values are strings as that is required when used as headers
5d0873a4de4a fix rate limit headers - were ints/floats need to be strings
John Rouillard <rouilj@ieee.org>
parents: 5739
diff changeset
107 ret['X-RateLimit-Limit'] = str(limit.count)
5d0873a4de4a fix rate limit headers - were ints/floats need to be strings
John Rouillard <rouilj@ieee.org>
parents: 5739
diff changeset
108 ret['X-RateLimit-Limit-Period'] = str(
5d0873a4de4a fix rate limit headers - were ints/floats need to be strings
John Rouillard <rouilj@ieee.org>
parents: 5739
diff changeset
109 int(
5d0873a4de4a fix rate limit headers - were ints/floats need to be strings
John Rouillard <rouilj@ieee.org>
parents: 5739
diff changeset
110 limit.period.total_seconds())
5d0873a4de4a fix rate limit headers - were ints/floats need to be strings
John Rouillard <rouilj@ieee.org>
parents: 5739
diff changeset
111 )
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
112
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
113 # status of current limit as of now
7587
8f29e4ea05ce fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 5996
diff changeset
114 now = utcnow()
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
115
5996
69a35d164a69 Make rate_limit.py pass flake8.
John Rouillard <rouilj@ieee.org>
parents: 5937
diff changeset
116 current_count = int((limit.period - (tat - now)).total_seconds() /
69a35d164a69 Make rate_limit.py pass flake8.
John Rouillard <rouilj@ieee.org>
parents: 5937
diff changeset
117 limit.inverse)
69a35d164a69 Make rate_limit.py pass flake8.
John Rouillard <rouilj@ieee.org>
parents: 5937
diff changeset
118 ret['X-RateLimit-Remaining'] = str(min(current_count, limit.count))
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
119
5739
e225f403cc35 Run pylint and clean up it's issues. Also fix comment.
John Rouillard <rouilj@ieee.org>
parents: 5722
diff changeset
120 # tat_in_epochsec = (tat - datetime(1970, 1, 1)).total_seconds()
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
121 seconds_to_tat = (tat - now).total_seconds()
5937
5d0873a4de4a fix rate limit headers - were ints/floats need to be strings
John Rouillard <rouilj@ieee.org>
parents: 5739
diff changeset
122 ret['X-RateLimit-Reset'] = str(max(seconds_to_tat, 0))
5996
69a35d164a69 Make rate_limit.py pass flake8.
John Rouillard <rouilj@ieee.org>
parents: 5937
diff changeset
123 ret['X-RateLimit-Reset-date'] = "%s" % tat
7590
5fbd3af526bd fix: issue2551278 - datetime.datetime.utcnow deprecation.
John Rouillard <rouilj@ieee.org>
parents: 7587
diff changeset
124 ret['Now'] = str((now - dt_epoch).total_seconds())
5996
69a35d164a69 Make rate_limit.py pass flake8.
John Rouillard <rouilj@ieee.org>
parents: 5937
diff changeset
125 ret['Now-date'] = "%s" % now
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
126
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
127 if self.update(key, limit, testonly=True):
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
128 # A new request would be rejected if it was processes.
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
129 # The user has to wait until an item is dequeued.
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
130 # One item is dequeued every limit.inverse seconds.
5937
5d0873a4de4a fix rate limit headers - were ints/floats need to be strings
John Rouillard <rouilj@ieee.org>
parents: 5739
diff changeset
131 ret['Retry-After'] = str(int(limit.inverse))
5996
69a35d164a69 Make rate_limit.py pass flake8.
John Rouillard <rouilj@ieee.org>
parents: 5937
diff changeset
132 ret['Retry-After-Timestamp'] = "%s" % \
8472
224ccb8b49ca refactor: change some classes to use __slots__
John Rouillard <rouilj@ieee.org>
parents: 7590
diff changeset
133 (now + timedelta(seconds=limit.inverse))
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
134 else:
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
135 # if we are not rejected, the user can post another
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
136 # attempt immediately.
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
137 # Do we even need this header if not rejected?
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
138 # RFC implies this is used with a 503 (or presumably
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
139 # 429 which may postdate the rfc). So if no error, no header?
5937
5d0873a4de4a fix rate limit headers - were ints/floats need to be strings
John Rouillard <rouilj@ieee.org>
parents: 5739
diff changeset
140 # ret['Retry-After'] = '0'
5d0873a4de4a fix rate limit headers - were ints/floats need to be strings
John Rouillard <rouilj@ieee.org>
parents: 5739
diff changeset
141 # ret['Retry-After-Timestamp'] = str(ret['Now-date'])
5717
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
142 pass
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
143
cad18de2b988 issue2550949: Rate limit password guesses/login attempts.
John Rouillard <rouilj@ieee.org>
parents:
diff changeset
144 return ret

Roundup Issue Tracker: http://roundup-tracker.org/