gitlab-labkit 5.2.0 → 5.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/labkit/rate_limit/README.md +9 -2
- data/lib/labkit/rate_limit/rule.rb +14 -4
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6a73e80c74e6f2578a9a86a5ad9c76c3c3c9ff4afc8c1deea262408763e84588
|
|
4
|
+
data.tar.gz: e7e1d625f3c634a04fd9a6aea0036270966c3b3a6e924edfebfd56713ede00ef
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 77d32a2075415b452d10b1b01a4ef3679d46bbaacd1bef798ce2b17b0b0109a9ec26565f8065600df41f1090752ae311b5a90fadfd434b4e39025d57dcf2f46f
|
|
7
|
+
data.tar.gz: c8e099df23ea1312476d3d1301044f5de159b6ed25098d755b47df2b7653b8958a9f30c778d5742620c4d804255ac31250f7834e090981803e54d26f4ab6f67b
|
|
@@ -171,8 +171,8 @@ A `Rule` is a `Data.define` value object with the following fields:
|
|
|
171
171
|
|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
172
172
|
| `name` | Stable identifier used in Redis keys and metric labels. Must match `/\A[a-z0-9_]+\z/`, max 64 chars. Renaming a rule abandons its in-flight counters. |
|
|
173
173
|
| `match` | Hash of identifier key/value predicates that must **all** be satisfied for the rule to apply. Empty hash matches anything. See [Matchers](#matchers). |
|
|
174
|
-
| `limit` | Integer request threshold per `period
|
|
175
|
-
| `period` | Window length in seconds. May be a callable resolved on every check.
|
|
174
|
+
| `limit` | Integer request threshold per `period`, at least 1. May be a callable resolved on every check. |
|
|
175
|
+
| `period` | Window length in seconds, at least 1; a fraction truncates to whole seconds. May be a callable resolved on every check. |
|
|
176
176
|
| `action` | What the rule does when it matches. One of `:limit`, `:log`, `:skip`. Default `:limit`. See [Actions](#actions). |
|
|
177
177
|
| `characteristics` | Array of identifier keys whose values are folded into the Redis counter key. Each unique combination gets its own counter. |
|
|
178
178
|
| `count_distinct` | Optional identifier key. When set, the rule counts distinct values seen for that key within the window, backed by a Redis SET rather than a counter. Must not overlap `characteristics`. |
|
|
@@ -190,6 +190,13 @@ Labkit::RateLimit::Rule.new(
|
|
|
190
190
|
)
|
|
191
191
|
```
|
|
192
192
|
|
|
193
|
+
`Rule.new` raises `ArgumentError` for a static `limit` under 1 or a static
|
|
194
|
+
`period` under one second, except on `:skip` rules where both are inert.
|
|
195
|
+
Callables are not validated: a `limit` resolving to `0` blocks every matching
|
|
196
|
+
request, which is how to express "deny all" dynamically, and a `period`
|
|
197
|
+
resolving under one second reaches `EXPIRE` as `0` and deletes the counter on
|
|
198
|
+
every write.
|
|
199
|
+
|
|
193
200
|
### Matchers
|
|
194
201
|
|
|
195
202
|
A `match` hash gates whether a rule applies. Each value is normalised through
|
|
@@ -10,8 +10,8 @@ module Labkit
|
|
|
10
10
|
# name - stable identifier used in Redis keys and log entries
|
|
11
11
|
# match - hash of identifier key/value pairs that must all match for
|
|
12
12
|
# the rule to apply; empty hash matches any identifier
|
|
13
|
-
# limit - request threshold; may be a callable (resolved per check)
|
|
14
|
-
# period - window in seconds; may be a callable (resolved per check)
|
|
13
|
+
# limit - request threshold, at least 1; may be a callable (resolved per check)
|
|
14
|
+
# period - window in seconds, at least 1; may be a callable (resolved per check)
|
|
15
15
|
# action - :limit (enforce; the result blocks when the rule is over
|
|
16
16
|
# its limit, which also terminates evaluation), :log (count
|
|
17
17
|
# and log only, never blocks and never terminates),
|
|
@@ -56,6 +56,16 @@ module Labkit
|
|
|
56
56
|
raise ArgumentError, "ban_for must be a Numeric of at least 1 second or a callable, got #{value.inspect}"
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
+
# A static limit under 1 blocks every request, and a period under a second
|
|
60
|
+
# reaches EXPIRE as 0, deleting the counter on every write. A :skip rule
|
|
61
|
+
# counts nothing, and a callable may still resolve to 0 to mean "deny all".
|
|
62
|
+
def self.normalize_numeric(field, value, action_sym)
|
|
63
|
+
return value if action_sym == :skip || value.respond_to?(:call)
|
|
64
|
+
return value if value.is_a?(Numeric) && value >= 1
|
|
65
|
+
|
|
66
|
+
raise ArgumentError, "#{field} must be a Numeric of at least 1 or a callable, got #{value.inspect}"
|
|
67
|
+
end
|
|
68
|
+
|
|
59
69
|
def self.normalize_count_distinct(value, characteristics_arr)
|
|
60
70
|
sym =
|
|
61
71
|
case value
|
|
@@ -94,8 +104,8 @@ module Labkit
|
|
|
94
104
|
super(
|
|
95
105
|
name: name_str.freeze,
|
|
96
106
|
match: match.transform_keys(&:to_sym).transform_values { |v| Matcher.build(v) }.freeze,
|
|
97
|
-
limit: limit,
|
|
98
|
-
period: period,
|
|
107
|
+
limit: self.class.normalize_numeric(:limit, limit, action_sym),
|
|
108
|
+
period: self.class.normalize_numeric(:period, period, action_sym),
|
|
99
109
|
action: action_sym,
|
|
100
110
|
characteristics: characteristics_arr,
|
|
101
111
|
count_distinct: count_distinct_sym,
|