grape-throttle 0.0.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 +7 -0
- data/lib/grape-throttle.rb +8 -0
- data/lib/grape/extensions/throttle_extension.rb +14 -0
- data/lib/grape/middleware/throttle_middleware.rb +39 -0
- data/spec/simple_api_spec.rb +30 -0
- data/spec/spec_helper.rb +16 -0
- metadata +135 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e419d5ca87035a859306e47417bbe6be06d92193
|
4
|
+
data.tar.gz: f5713a6a7001d0a7299f020d479a0068b37f1147
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cdb974ec369262a56552f919ffd0b9b1d40f63f7796f2a9271e2bc74f8c57173e77c599c0d31d21f3629ae06f9351f12d430c07db2408a0f5911721f88d4cff3
|
7
|
+
data.tar.gz: 522e49d89f4dacda20ca044f8e1370f7287886ebf21250fa8380b99b8a9b4027dda1c947782a0cf1350788ecdcd6304bd2b6bbf97ed131c50e3aeda1b7da70e3
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Grape
|
2
|
+
module Middleware
|
3
|
+
class ThrottleMiddleware < Grape::Middleware::Base
|
4
|
+
def before
|
5
|
+
endpoint = env['api.endpoint']
|
6
|
+
return unless throttle_options = endpoint.route_setting(:throttle)
|
7
|
+
|
8
|
+
if limit = throttle_options[:hourly]
|
9
|
+
period = 1.hour
|
10
|
+
elsif limit = throttle_options[:daily]
|
11
|
+
period = 1.day
|
12
|
+
elsif limit = throttle_options[:monthly]
|
13
|
+
period = 1.month
|
14
|
+
end
|
15
|
+
|
16
|
+
user_key = options[:user_key]
|
17
|
+
user_value = nil
|
18
|
+
user_value = user_key.call(env) unless user_key.nil?
|
19
|
+
user_value ||= "ip:#{env['REMOTE_ADDR']}"
|
20
|
+
|
21
|
+
r = endpoint.routes.first
|
22
|
+
rate_key = "#{r.route_method}:#{r.route_path}:#{user_value}"
|
23
|
+
|
24
|
+
redis = options[:cache]
|
25
|
+
current = redis.get(rate_key).to_i
|
26
|
+
if !current.nil? && current >= limit
|
27
|
+
endpoint.error!("too many requests, please try again later", 403)
|
28
|
+
else
|
29
|
+
redis.multi do
|
30
|
+
redis.incr(rate_key)
|
31
|
+
redis.expire(rate_key, period.to_i)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "ThrottleHelper" do
|
4
|
+
subject do
|
5
|
+
Class.new(Grape::API) do
|
6
|
+
use Grape::Middleware::ThrottleMiddleware, cache: Redis.new
|
7
|
+
|
8
|
+
throttle daily: 3
|
9
|
+
get('/throttle') do
|
10
|
+
"step on it"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def app
|
16
|
+
subject
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#throttle" do
|
20
|
+
it "is not throttled within the rate limit" do
|
21
|
+
3.times { get "/throttle" }
|
22
|
+
expect(last_response.status).to eq(200)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "is throttled beyond the rate limit" do
|
26
|
+
4.times { get "/throttle" }
|
27
|
+
expect(last_response.status).to eq(403)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'grape-throttle'
|
2
|
+
require 'fakeredis'
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler'
|
6
|
+
|
7
|
+
Bundler.setup :default, :test
|
8
|
+
|
9
|
+
require 'rack/test'
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
require 'rspec/expectations'
|
13
|
+
config.include RSpec::Matchers
|
14
|
+
config.mock_with :rspec
|
15
|
+
config.include Rack::Test::Methods
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: grape-throttle
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alejandro Wainzinger
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: grape
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.10.0
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.10.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack-test
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
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: fakeredis
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.3.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.3.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: redis
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: A middleware for Grape to add endpoint-specific throttling.
|
98
|
+
email:
|
99
|
+
- alejandro.wainzinger@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- lib/grape-throttle.rb
|
105
|
+
- lib/grape/extensions/throttle_extension.rb
|
106
|
+
- lib/grape/middleware/throttle_middleware.rb
|
107
|
+
- spec/simple_api_spec.rb
|
108
|
+
- spec/spec_helper.rb
|
109
|
+
homepage: https://github.com/xevix/grape-throttle
|
110
|
+
licenses:
|
111
|
+
- MIT
|
112
|
+
metadata: {}
|
113
|
+
post_install_message:
|
114
|
+
rdoc_options: []
|
115
|
+
require_paths:
|
116
|
+
- lib
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
requirements: []
|
128
|
+
rubyforge_project:
|
129
|
+
rubygems_version: 2.4.4
|
130
|
+
signing_key:
|
131
|
+
specification_version: 4
|
132
|
+
summary: A middleware for Grape to add endpoint-specific throttling.
|
133
|
+
test_files:
|
134
|
+
- spec/simple_api_spec.rb
|
135
|
+
- spec/spec_helper.rb
|