rate_limiter_engine 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 25680fbf29d02bc0d1657d03a82074f66608db7115efa20387bb3d613a382d79
4
+ data.tar.gz: 39d2fe46ef92d55517bf070286157152888a2f3b654215f89a9d57fe0320b047
5
+ SHA512:
6
+ metadata.gz: 0ecd532d39f1d09de8db9f500a6b3e5ee03edfd7b801392cb996dce0f13e20085cfd9354b28f1454715ef5cf9563f66e27f2beffb3ddddc82e13e0d8a65c8bcd
7
+ data.tar.gz: 701c10ba0dee7ac5a9bdafaa7d79c2f013d59eab9035fadb92a73a9481c9d33394c45438e9b6bb0212d4e3685da94b22ca13cf8b2ae43e0cee3e2a42f203d2cd
@@ -0,0 +1,6 @@
1
+ require 'rate_limiter/configuration'
2
+ require 'rate_limiter/rate_limiter'
3
+ require 'rate_limiter/rate_limit'
4
+ require 'rate_limiter/engine'
5
+
6
+ module RateLimiter; end
@@ -0,0 +1,20 @@
1
+ module RateLimiter
2
+ class Configuration
3
+ attr_accessor :rate_default,
4
+ :period_default,
5
+ :force_rate_limit,
6
+ :force_period
7
+ end
8
+
9
+ class << self
10
+ def configure
11
+ yield(configuration)
12
+
13
+ configuration
14
+ end
15
+
16
+ def configuration
17
+ @configuration ||= Configuration.new
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ module RateLimiter
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace RateLimiter
4
+ end
5
+ end
@@ -0,0 +1,45 @@
1
+ module RateLimiter
2
+ module RateLimit
3
+ extend ActiveSupport::Concern
4
+
5
+ @@rate = {}
6
+ @@rate_default = ::RateLimiter.configuration.rate_default || 100
7
+ @@period = {}
8
+ @@period_default = ::RateLimiter.configuration.period_default || 100
9
+
10
+ included do
11
+ before_action :rate_limiter
12
+
13
+ def self.rate(rate)
14
+ @@rate[controller_name] = rate
15
+ end
16
+
17
+ def self.period(period)
18
+ @@period[controller_name] = period
19
+ end
20
+ end
21
+
22
+ protected
23
+
24
+ def rate_limiter
25
+ rate_limiter_object.count
26
+ rate_limiter_object.increment
27
+
28
+ render_limit_exceeded if rate_limiter_object.blocked?
29
+ end
30
+
31
+ def render_limit_exceeded
32
+ render json: {
33
+ message: "Rate limit exceeded. Try again in #{rate_limiter_object.cooldown_period} seconds"
34
+ }, status: :too_many_requests
35
+ end
36
+
37
+ def client_key
38
+ "#{request.env['REMOTE_IP']}_counter"
39
+ end
40
+
41
+ def rate_limiter_object
42
+ RateLimiter.new(client_key)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,70 @@
1
+ module RateLimiter
2
+ class RateLimiter
3
+ def initialize(client_key)
4
+ @client_key = client_key
5
+ end
6
+
7
+ attr_reader :client_key
8
+
9
+ def blocked?
10
+ counter.present? && limit_exceeded
11
+ end
12
+
13
+ def count
14
+ return if counter
15
+
16
+ set_client_key
17
+ set_expire
18
+ end
19
+
20
+ def increment
21
+ $redis.incr(client_key)
22
+ end
23
+
24
+ def cooldown_period
25
+ $redis.ttl(client_key)
26
+ end
27
+
28
+ private
29
+
30
+ def counter
31
+ $redis.get(client_key)
32
+ end
33
+
34
+ def limit_exceeded
35
+ counter.to_i > rate_limit.to_i
36
+ end
37
+
38
+ def set_client_key
39
+ $redis.set(client_key, 0)
40
+ end
41
+
42
+ def set_expire
43
+ $redis.expire(client_key, period)
44
+ end
45
+
46
+ def rate_limit
47
+ force_rate_limit || rate_default
48
+ end
49
+
50
+ def period
51
+ force_period || period_default
52
+ end
53
+
54
+ def force_rate_limit
55
+ ::RateLimiter.configuration.force_rate_limit
56
+ end
57
+
58
+ def rate_default
59
+ ::RateLimiter.configuration.rate_default
60
+ end
61
+
62
+ def force_period
63
+ ::RateLimiter.configuration.force_period
64
+ end
65
+
66
+ def period_default
67
+ ::RateLimiter.configuration.period_default
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,3 @@
1
+ module RateLimiter
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rate_limiter_engine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Vitor Oliveira
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 6.1.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 6.1.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: redis
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mock_redis
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pg
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Rate Limiter for Rails APIs
84
+ email:
85
+ - vbrazo@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - lib/rate_limiter.rb
91
+ - lib/rate_limiter/configuration.rb
92
+ - lib/rate_limiter/engine.rb
93
+ - lib/rate_limiter/rate_limit.rb
94
+ - lib/rate_limiter/rate_limiter.rb
95
+ - lib/rate_limiter/version.rb
96
+ homepage:
97
+ licenses: []
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubygems_version: 3.1.2
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: Rate Limiter for Rails APIs
118
+ test_files: []