@@ -29,6 +29,9 @@ module ClassMethods
29
29
# datastore as your general caches, you can pass a custom store in the `store`
30
30
# parameter.
31
31
#
32
+ # If you want to use multiple rate limits per controller, you need to give each of
33
+ # them and explicit name via the `name:` option.
34
+ #
32
35
# Examples:
33
36
#
34
37
# class SessionsController < ApplicationController
@@ -44,14 +47,19 @@ module ClassMethods
44
47
# RATE_LIMIT_STORE = ActiveSupport::Cache::RedisCacheStore.new(url: ENV["REDIS_URL"])
45
48
# rate_limit to: 10, within: 3.minutes, store: RATE_LIMIT_STORE
46
49
# end
47
- def rate_limit ( to :, within :, by : -> { request . remote_ip } , with : -> { head :too_many_requests } , store : cache_store , **options )
48
- before_action -> { rate_limiting ( to : to , within : within , by : by , with : with , store : store ) } , **options
50
+ #
51
+ # class SessionsController < ApplicationController
52
+ # rate_limit to: 3, within: 2.seconds, name: "short-term"
53
+ # rate_limit to: 10, within: 5.minutes, name: "long-term"
54
+ # end
55
+ def rate_limit ( to :, within :, by : -> { request . remote_ip } , with : -> { head :too_many_requests } , store : cache_store , name : controller_path , **options )
56
+ before_action -> { rate_limiting ( to : to , within : within , by : by , with : with , store : store , name : name ) } , **options
49
57
end
50
58
end
51
59
52
60
private
53
- def rate_limiting ( to :, within :, by :, with :, store :)
54
- count = store . increment ( "rate-limit:#{ controller_path } :#{ instance_exec ( &by ) } " , 1 , expires_in : within )
61
+ def rate_limiting ( to :, within :, by :, with :, store :, name : )
62
+ count = store . increment ( "rate-limit:#{ name } :#{ instance_exec ( &by ) } " , 1 , expires_in : within )
55
63
if count && count > to
56
64
ActiveSupport ::Notifications . instrument ( "rate_limit.action_controller" , request : request ) do
57
65
instance_exec ( &with )
0 commit comments