rails_rate_limit 0.1.2 → 0.2.0
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/README.md +38 -22
- data/lib/rails_rate_limit/klass.rb +36 -0
- data/lib/rails_rate_limit/version.rb +1 -1
- 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: f84a9dd27c84c9d0519657dcdc6a03da54339a00951fba0e4dfe847e210bc416
|
4
|
+
data.tar.gz: 68ed631f37784ac86f12e261cd28e99caf879f4b604604f5c0717b9e9a071062
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d5822c1423345099c7d42a21ca11951720de2f9be00e7858fdf9ffee69b3e970454ed878e57e36c75ee74e49c213a0de1a079f2a476c52c95cdaabefdc34138
|
7
|
+
data.tar.gz: 736ce16dddb1b5e238e88570cd67cbce3895f2bb51a61a10a5d635112d4fe3d3489a33bf01735ddc67ebf350a669f668c3ce1952324a8ba5145649c0806cc379
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Rails Rate Limit
|
1
|
+
# **Rails Rate Limit**
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/rails_rate_limit)
|
4
4
|
[](https://github.com/kasvit/rails_rate_limit/actions)
|
@@ -99,23 +99,33 @@ end
|
|
99
99
|
|
100
100
|
### Rate Limiting Methods
|
101
101
|
|
102
|
-
You can limit
|
102
|
+
You can limit both instance and class methods in your classes:
|
103
103
|
|
104
104
|
```ruby
|
105
105
|
class ApiClient
|
106
|
-
include RailsRateLimit::Klass
|
106
|
+
include RailsRateLimit::Klass
|
107
107
|
|
108
|
+
# Instance method
|
108
109
|
def make_request
|
109
110
|
# Your API call logic here
|
110
111
|
end
|
111
112
|
|
112
|
-
#
|
113
|
-
|
113
|
+
# Class method
|
114
|
+
def self.bulk_request
|
115
|
+
# Your API call logic here
|
116
|
+
end
|
117
|
+
|
118
|
+
# Rate limit for instance method
|
114
119
|
set_rate_limit :make_request,
|
115
120
|
limit: 100,
|
116
121
|
period: 1.minute
|
117
122
|
|
118
|
-
#
|
123
|
+
# Rate limit for class method
|
124
|
+
set_rate_limit :bulk_request,
|
125
|
+
limit: 10,
|
126
|
+
period: 1.hour
|
127
|
+
|
128
|
+
# Advanced usage with all options (instance method)
|
119
129
|
set_rate_limit :another_method,
|
120
130
|
limit: 10, # Maximum calls allowed
|
121
131
|
period: 1.hour, # Time window for the limit
|
@@ -128,21 +138,26 @@ class ApiClient
|
|
128
138
|
nil # Method will return nil
|
129
139
|
}
|
130
140
|
|
131
|
-
#
|
132
|
-
set_rate_limit :
|
133
|
-
limit: 5,
|
134
|
-
period: 1.
|
135
|
-
|
136
|
-
#
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
141
|
+
# Advanced usage with all options (class method)
|
142
|
+
set_rate_limit :another_class_method,
|
143
|
+
limit: 5, # Maximum calls allowed
|
144
|
+
period: 1.day, # Time window for the limit
|
145
|
+
by: -> { "global:#{name}" }, # Method call identifier
|
146
|
+
store: :redis, # Override default store
|
147
|
+
on_exceeded: -> { # Custom error handler
|
148
|
+
log_exceeded_event
|
149
|
+
"Rate limit exceeded" # Return custom message
|
150
|
+
}
|
151
|
+
|
152
|
+
# Direct rate limit setting
|
153
|
+
# You can also set rate limits directly if you have both instance and class methods with the same name
|
154
|
+
set_instance_rate_limit :process, # For instance method
|
155
|
+
limit: 10,
|
156
|
+
period: 1.hour
|
157
|
+
|
158
|
+
set_class_rate_limit :process, # For class method
|
159
|
+
limit: 5,
|
160
|
+
period: 1.hour
|
146
161
|
end
|
147
162
|
```
|
148
163
|
|
@@ -153,7 +168,8 @@ For both controllers and methods:
|
|
153
168
|
- `period`: (Required) Time period for the limit (in seconds or ActiveSupport::Duration)
|
154
169
|
- `by`: (Optional) Lambda/Proc to generate unique identifier
|
155
170
|
- Default for controllers: `"#{controller.class.name}:#{controller.request.remote_ip}"`
|
156
|
-
- Default for methods: `"#{self.class.name}##{method_name}:#{respond_to?(:id) ? 'id='+id.to_s : 'object_id='+object_id.to_s}"`
|
171
|
+
- Default for instance methods: `"#{self.class.name}##{method_name}:#{respond_to?(:id) ? 'id='+id.to_s : 'object_id='+object_id.to_s}"`
|
172
|
+
- Default for class methods: `"#{class.name}.#{method_name}"`
|
157
173
|
- `store`: (Optional) Override default storage backend (`:redis`, `:memcached`, `:memory`)
|
158
174
|
- `on_exceeded`: (Optional) Custom handler for rate limit exceeded
|
159
175
|
|
@@ -8,6 +8,18 @@ module RailsRateLimit
|
|
8
8
|
def set_rate_limit(method_name, limit:, period:, by: nil, store: nil, on_exceeded: nil)
|
9
9
|
Validations.validate_options!(limit: limit, period: period, by: by, store: store)
|
10
10
|
|
11
|
+
if method_defined?(method_name) || private_method_defined?(method_name)
|
12
|
+
set_instance_rate_limit(method_name, limit: limit, period: period, by: by, store: store,
|
13
|
+
on_exceeded: on_exceeded)
|
14
|
+
elsif singleton_class.method_defined?(method_name) || singleton_class.private_method_defined?(method_name)
|
15
|
+
set_class_rate_limit(method_name, limit: limit, period: period, by: by, store: store,
|
16
|
+
on_exceeded: on_exceeded)
|
17
|
+
else
|
18
|
+
raise ArgumentError, "Method #{method_name} is not defined"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_instance_rate_limit(method_name, limit:, period:, by:, store:, on_exceeded:)
|
11
23
|
original_method = instance_method(method_name)
|
12
24
|
|
13
25
|
define_method(method_name) do |*args, &block|
|
@@ -30,6 +42,30 @@ module RailsRateLimit
|
|
30
42
|
end
|
31
43
|
end
|
32
44
|
end
|
45
|
+
|
46
|
+
def set_class_rate_limit(method_name, limit:, period:, by:, store:, on_exceeded:)
|
47
|
+
original_method = singleton_class.instance_method(method_name)
|
48
|
+
|
49
|
+
singleton_class.define_method(method_name) do |*args, &block|
|
50
|
+
limiter = RateLimiter.new(
|
51
|
+
context: self,
|
52
|
+
by: by || lambda {
|
53
|
+
"#{name}.#{method_name}"
|
54
|
+
},
|
55
|
+
limit: limit,
|
56
|
+
period: period.to_i,
|
57
|
+
store: store
|
58
|
+
)
|
59
|
+
|
60
|
+
begin
|
61
|
+
limiter.perform!
|
62
|
+
original_method.bind(self).call(*args, &block)
|
63
|
+
rescue RailsRateLimit::RateLimitExceeded
|
64
|
+
handler = on_exceeded.nil? ? RailsRateLimit.configuration.handle_klass_exceeded : on_exceeded
|
65
|
+
instance_exec(&handler)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
33
69
|
end
|
34
70
|
end
|
35
71
|
end
|