bottleneck 0.4.2 → 0.4.3
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/.travis.yml +4 -0
- data/Gemfile.lock +6 -1
- data/README.md +13 -8
- data/bottleneck.gemspec +3 -1
- data/lib/bottleneck/core.rb +18 -2
- data/lib/bottleneck/version.rb +1 -1
- data/lib/bottleneck.rb +18 -4
- metadata +31 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22d916e42ef02a5ad281db4499e3d3e35855b34b
|
4
|
+
data.tar.gz: f61fe13668ac348fc40040df8f90f0f5eed1c2f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29f95a6863d82b3d7b4a34c5ed3c8683858592b517c39a42c0d85503c4027c7189d7a80d2c980f3624de4d931b01b31e82fe04d5f80dbbbf7d24c168b2ae4647
|
7
|
+
data.tar.gz: d75e87c21de2d47e6bfe429a9805d7f98cbb352bee9a1f5fee89c0cb05a4c11525524bfe08e7545240e8440afb0de46e37b84c8a7acb775c5bd7a7b54551e5e1
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bottleneck (0.4.
|
4
|
+
bottleneck (0.4.2)
|
5
5
|
redis (~> 4.0)
|
6
6
|
redis-namespace (~> 1.6.0)
|
7
7
|
|
@@ -10,12 +10,15 @@ GEM
|
|
10
10
|
specs:
|
11
11
|
ast (2.4.0)
|
12
12
|
diff-lcs (1.3)
|
13
|
+
fakeredis (0.7.0)
|
14
|
+
redis (>= 3.2, < 5.0)
|
13
15
|
parallel (1.12.1)
|
14
16
|
parser (2.5.0.2)
|
15
17
|
ast (~> 2.4.0)
|
16
18
|
powerpack (0.1.1)
|
17
19
|
rainbow (3.0.0)
|
18
20
|
rake (10.5.0)
|
21
|
+
rdoc (6.0.1)
|
19
22
|
redis (4.0.1)
|
20
23
|
redis-namespace (1.6.0)
|
21
24
|
redis (>= 3.0.4)
|
@@ -48,7 +51,9 @@ PLATFORMS
|
|
48
51
|
DEPENDENCIES
|
49
52
|
bottleneck!
|
50
53
|
bundler (~> 1.16)
|
54
|
+
fakeredis (~> 0.6)
|
51
55
|
rake (~> 10.0)
|
56
|
+
rdoc (~> 6.0.1)
|
52
57
|
rspec (~> 3.0)
|
53
58
|
rubocop (~> 0.52.1)
|
54
59
|
|
data/README.md
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
|
1
|
+
[](https://travis-ci.org/maratgaliev/bottleneck)
|
2
2
|
|
3
|
-
Bottleneck
|
3
|
+
# Bottleneck
|
4
4
|
|
5
|
-
|
6
|
-
* max_requests_count: 100
|
5
|
+
Bottleneck - simple Redis based requests limiter.
|
7
6
|
|
8
7
|
## Installation
|
9
8
|
|
@@ -27,29 +26,35 @@ Create two yaml files in config dir:
|
|
27
26
|
|
28
27
|
**bottleneck.yml**
|
29
28
|
|
29
|
+
```ruby
|
30
30
|
limits:
|
31
31
|
time_period_seconds: 3600
|
32
32
|
max_requests_count: 100
|
33
|
-
|
33
|
+
```
|
34
34
|
**redis.yml**
|
35
|
+
|
36
|
+
```ruby
|
35
37
|
host: 'localhost'
|
36
38
|
port: 6379
|
39
|
+
```
|
37
40
|
|
38
|
-
Add before action:
|
41
|
+
Add before action to your controller:
|
42
|
+
```ruby
|
39
43
|
class ApplicationController < ActionController::API
|
40
44
|
before_action :check_limit
|
41
45
|
|
42
46
|
private
|
43
47
|
|
44
48
|
def check_limit
|
45
|
-
result = Bottleneck.check(request)
|
49
|
+
result = Bottleneck.check(request.remote_ip)
|
46
50
|
render status: result[:status], json: { message: result[:message] }
|
47
51
|
end
|
48
52
|
end
|
53
|
+
```
|
49
54
|
|
50
55
|
## Contributing
|
51
56
|
|
52
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/maratgaliev/bottleneck
|
57
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/maratgaliev/bottleneck](https://github.com/maratgaliev/bottleneck).
|
53
58
|
|
54
59
|
## License
|
55
60
|
|
data/bottleneck.gemspec
CHANGED
@@ -25,6 +25,8 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
26
26
|
spec.add_development_dependency "rspec", "~> 3.0"
|
27
27
|
spec.add_development_dependency "rubocop", "~> 0.52.1"
|
28
|
+
spec.add_development_dependency "rdoc", "~> 6.0"
|
29
|
+
spec.add_development_dependency "fakeredis", "~> 0.6"
|
28
30
|
spec.add_dependency "redis", "~> 4.0"
|
29
|
-
spec.add_dependency "redis-namespace", "~> 1.6
|
31
|
+
spec.add_dependency "redis-namespace", "~> 1.6"
|
30
32
|
end
|
data/lib/bottleneck/core.rb
CHANGED
@@ -2,15 +2,22 @@ require "bottleneck/constants"
|
|
2
2
|
|
3
3
|
module Bottleneck
|
4
4
|
class Core
|
5
|
+
# Create a Core object.
|
6
|
+
#
|
7
|
+
# @param [String] ip A name to uniquely identify this rate limit. For example, '127.0.0.1'
|
8
|
+
#
|
9
|
+
# @return [Core] Core instance
|
5
10
|
def initialize(ip)
|
6
11
|
@ip = ip.to_s
|
7
12
|
@storage = Bottleneck.storage
|
8
13
|
@limits = Bottleneck.config["limits"]
|
9
14
|
end
|
10
15
|
|
16
|
+
# Run main logic initialization, set and read Redis keys and validation requests count and time limit.
|
17
|
+
#
|
18
|
+
# @return [Hash] Hash with :status and :message keys
|
11
19
|
def run
|
12
20
|
client_ip = @ip
|
13
|
-
# create key in redis, based on client's IP
|
14
21
|
key = "request_count:#{client_ip}"
|
15
22
|
result = { status: Constants::SUCCESS_STATUS, message: Constants::OK_MESSAGE }
|
16
23
|
requests_count = @storage.get(key)
|
@@ -29,11 +36,20 @@ module Bottleneck
|
|
29
36
|
|
30
37
|
private
|
31
38
|
|
39
|
+
# Get remaining time in seconds for key.
|
40
|
+
#
|
41
|
+
# @param [String] key A unique key in Redis store
|
42
|
+
#
|
43
|
+
# @return [Integer] Countdown in seconds
|
32
44
|
def period(key)
|
33
|
-
# get remaining seconds with TTL from redis
|
34
45
|
@storage.ttl(key)
|
35
46
|
end
|
36
47
|
|
48
|
+
# Return string message for 429 status
|
49
|
+
#
|
50
|
+
# @param [Integer] secs Remaining seconds
|
51
|
+
#
|
52
|
+
# @return [String] Rate limit message with seconds
|
37
53
|
def message(secs)
|
38
54
|
"Rate limit exceeded. Try again in #{secs} seconds"
|
39
55
|
end
|
data/lib/bottleneck/version.rb
CHANGED
data/lib/bottleneck.rb
CHANGED
@@ -6,33 +6,47 @@ require "redis-namespace"
|
|
6
6
|
|
7
7
|
module Bottleneck
|
8
8
|
class << self
|
9
|
+
# Run method call on Core object
|
10
|
+
#
|
11
|
+
# @param [String] A name to uniquely identify this rate limit. For example, '127.0.0.1'
|
9
12
|
def check(ip)
|
10
13
|
Core.new(ip).run
|
11
14
|
end
|
12
15
|
|
16
|
+
# Init Redis Namespace storage
|
17
|
+
#
|
18
|
+
# @return [Redis::Namespace] Redis::Namespace instance
|
13
19
|
def storage
|
14
20
|
init_storage
|
15
21
|
end
|
16
22
|
|
23
|
+
# Init Redis instance
|
24
|
+
#
|
25
|
+
# @return [Redis] Redis instance
|
17
26
|
def redis_conn
|
18
27
|
redis_conf = load_config("redis.yml")
|
19
28
|
Redis.new(host: redis_conf["host"], port: redis_conf["port"])
|
20
29
|
end
|
21
30
|
|
22
|
-
# Init
|
31
|
+
# Init Redis Namespace storage
|
32
|
+
#
|
33
|
+
# @return [Redis::Namespace] Redis::Namespace instance
|
23
34
|
def init_storage
|
24
35
|
Redis::Namespace.new(:bottleneck, redis: redis_conn)
|
25
36
|
end
|
26
37
|
|
27
|
-
#
|
38
|
+
# Load limits config file
|
39
|
+
#
|
40
|
+
# @return [Hash] Hash for bottleneck.yml file
|
28
41
|
def config
|
29
42
|
load_config("bottleneck.yml")
|
30
43
|
end
|
31
44
|
|
32
45
|
private
|
33
|
-
|
46
|
+
# Load config file
|
47
|
+
#
|
48
|
+
# @return [Hash] Hash with configuration
|
34
49
|
def load_config(file)
|
35
|
-
# Check for Rails defined, or use current path
|
36
50
|
root = (defined?(Rails) && Rails.respond_to?(:root) && Rails.root) || Dir.pwd
|
37
51
|
path = "#{root}/config/#{file}"
|
38
52
|
raise "No #{file} file found in your config directory!" unless File.exist?(path)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bottleneck
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marat Galiev
|
@@ -66,6 +66,34 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.52.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rdoc
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '6.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '6.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: fakeredis
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.6'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.6'
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: redis
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,14 +114,14 @@ dependencies:
|
|
86
114
|
requirements:
|
87
115
|
- - "~>"
|
88
116
|
- !ruby/object:Gem::Version
|
89
|
-
version: 1.6
|
117
|
+
version: '1.6'
|
90
118
|
type: :runtime
|
91
119
|
prerelease: false
|
92
120
|
version_requirements: !ruby/object:Gem::Requirement
|
93
121
|
requirements:
|
94
122
|
- - "~>"
|
95
123
|
- !ruby/object:Gem::Version
|
96
|
-
version: 1.6
|
124
|
+
version: '1.6'
|
97
125
|
description: Simple Redis based Rate Limiter for Rails applications
|
98
126
|
email:
|
99
127
|
- kazanlug@gmail.com
|