Mercurial > p > roundup > code
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 |
| 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 |
