grape-throttler 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.fasterer.yml +19 -0
- data/.gitattributes +2 -0
- data/.gitignore +13 -0
- data/.irbrc +44 -0
- data/.reek.yml +22 -0
- data/.rspec +3 -0
- data/.rubocop.yml +39 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +8 -0
- data/README.md +127 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/rake +15 -0
- data/bin/setup +7 -0
- data/grape-throttler.gemspec +34 -0
- data/lib/grape-throttler.rb +17 -0
- data/lib/grape-throttler/extensions/throttle_extension.rb +16 -0
- data/lib/grape-throttler/middleware/throttle_middleware.rb +80 -0
- data/lib/grape-throttler/version.rb +5 -0
- metadata +205 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ff44f961112b47773a75e7c195b909e33938d0ada801d01ddd981f1f8ca8c854
|
4
|
+
data.tar.gz: e3422fd5c83dbec806d859f62c1bc5a6560fbe0da905b1fc4d6acbe13bb101b7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3ee5867e71b9de391fea4a5e37385b522abe52c724aa261f4f48510b30b076c417bd76eab1b1de27c1ee742096b3e493c7dcc92453242708574780873a8a216e
|
7
|
+
data.tar.gz: 47544b35bd03f981dd5c7dffa4f5c8cc8a9e155968507ded18c60e9971b9626f45e4f965382fc55b6af9e7c35be0d1c58e29eea0285df2f27a3c5bf932a6a054
|
data/.fasterer.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
speedups:
|
2
|
+
rescue_vs_respond_to: false
|
3
|
+
module_eval: true
|
4
|
+
shuffle_first_vs_sample: true
|
5
|
+
for_loop_vs_each: true
|
6
|
+
each_with_index_vs_while: false
|
7
|
+
map_flatten_vs_flat_map: true
|
8
|
+
reverse_each_vs_reverse_each: true
|
9
|
+
select_first_vs_detect: true
|
10
|
+
sort_vs_sort_by: true
|
11
|
+
fetch_with_argument_vs_block: true
|
12
|
+
keys_each_vs_each_key: true
|
13
|
+
hash_merge_bang_vs_hash_brackets: true
|
14
|
+
block_vs_symbol_to_proc: true
|
15
|
+
proc_call_vs_yield: true
|
16
|
+
gsub_vs_tr: true
|
17
|
+
select_last_vs_reverse_detect: true
|
18
|
+
getter_vs_attr_reader: true
|
19
|
+
setter_vs_attr_writer: true
|
data/.gitattributes
ADDED
data/.gitignore
ADDED
data/.irbrc
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Awesome print
|
4
|
+
begin
|
5
|
+
require 'awesome_print'
|
6
|
+
|
7
|
+
AwesomePrint.irb!
|
8
|
+
rescue LoadError => err
|
9
|
+
warn "Couldn't load awesome_print: #{err}"
|
10
|
+
end
|
11
|
+
|
12
|
+
# IRB
|
13
|
+
require 'irb/completion'
|
14
|
+
|
15
|
+
ARGV.concat %w[--readline --prompt-mode simple]
|
16
|
+
|
17
|
+
IRB.conf[:PROMPT_MODE] = :SIMPLE
|
18
|
+
IRB.conf[:EVAL_HISTORY] = 1000
|
19
|
+
IRB.conf[:SAVE_HISTORY] = 1000
|
20
|
+
IRB.conf[:HISTORY_FILE] = File.expand_path('.irbrc_history')
|
21
|
+
|
22
|
+
# Rails
|
23
|
+
railsrc_path = File.expand_path('.irbrc_rails')
|
24
|
+
|
25
|
+
if (ENV['RAILS_ENV'] || defined?(Rails)) && File.exist?(railsrc_path)
|
26
|
+
begin
|
27
|
+
load railsrc_path
|
28
|
+
rescue Exception => err
|
29
|
+
warn "Could not load: #{railsrc_path} because of #{err}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Object
|
34
|
+
class Object
|
35
|
+
|
36
|
+
def interesting_methods
|
37
|
+
case self.class
|
38
|
+
when Class then public_methods.sort - Object.public_methods
|
39
|
+
when Module then public_methods.sort - Module.public_methods
|
40
|
+
else public_methods.sort - Object.new.public_methods
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/.reek.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
---
|
2
|
+
detectors:
|
3
|
+
Attribute:
|
4
|
+
enabled: false
|
5
|
+
IrresponsibleModule:
|
6
|
+
enabled: false
|
7
|
+
MissingSafeMethod:
|
8
|
+
enabled: false
|
9
|
+
NilCheck:
|
10
|
+
enabled: false
|
11
|
+
TooManyInstanceVariables:
|
12
|
+
enabled: false
|
13
|
+
TooManyStatements:
|
14
|
+
max_statements: 10
|
15
|
+
exclude:
|
16
|
+
- 'GrapeThrottler::Middleware::ThrottleMiddleware#before'
|
17
|
+
UncommunicativeVariableName:
|
18
|
+
accept:
|
19
|
+
- '/^.$/'
|
20
|
+
- '/[0-9]$/'
|
21
|
+
UtilityFunction:
|
22
|
+
enabled: false
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
AllCops:
|
2
|
+
DisplayCopNames: true
|
3
|
+
DisplayStyleGuide: true
|
4
|
+
TargetRubyVersion: 2.5
|
5
|
+
Exclude:
|
6
|
+
- 'lib/**/**/templates/*'
|
7
|
+
- 'spec/**/**/*'
|
8
|
+
Layout/EmptyLinesAroundClassBody:
|
9
|
+
Enabled: false
|
10
|
+
Layout/EmptyLinesAroundModuleBody:
|
11
|
+
Enabled: false
|
12
|
+
LineLength:
|
13
|
+
Max: 100
|
14
|
+
Lint/AssignmentInCondition:
|
15
|
+
Enabled: false
|
16
|
+
Lint/RescueException:
|
17
|
+
Enabled: false
|
18
|
+
Lint/ScriptPermission:
|
19
|
+
Enabled: false
|
20
|
+
Metrics/AbcSize:
|
21
|
+
Enabled: false
|
22
|
+
Metrics/CyclomaticComplexity:
|
23
|
+
Enabled: false
|
24
|
+
Metrics/MethodLength:
|
25
|
+
Enabled: false
|
26
|
+
Metrics/PerceivedComplexity:
|
27
|
+
Enabled: false
|
28
|
+
Naming/FileName:
|
29
|
+
Enabled: false
|
30
|
+
Style/BracesAroundHashParameters:
|
31
|
+
Enabled: false
|
32
|
+
Style/Documentation:
|
33
|
+
Enabled: false
|
34
|
+
Style/ExpandPathArguments:
|
35
|
+
Enabled: false
|
36
|
+
Style/RescueModifier:
|
37
|
+
Enabled: false
|
38
|
+
Style/RescueStandardError:
|
39
|
+
Enabled: false
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.1
|
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
Grape Throttle
|
2
|
+
==============
|
3
|
+
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/grape-throttle.svg)](https://badge.fury.io/rb/grape-throttle)
|
5
|
+
[![Build Status](https://travis-ci.org/xevix/grape-throttle.svg)](https://travis-ci.org/xevix/grape-throttle)
|
6
|
+
|
7
|
+
**Deprecation Warning**
|
8
|
+
|
9
|
+
This gem is no longer being actively maintained. For similar throttle functionality see [rack-attack](https://github.com/kickstarter/rack-attack). Integration of this gem with rack-attack is a future consideration.
|
10
|
+
|
11
|
+
**Description**
|
12
|
+
|
13
|
+
The grape-throttle gem provides a simple endpoint-specific throttling mechanism for Grape.
|
14
|
+
|
15
|
+
## Requirements
|
16
|
+
|
17
|
+
* Grape >= 0.10.0
|
18
|
+
* Redis
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
### Build and Install
|
23
|
+
|
24
|
+
To use, just install the gem from RubyGems or via Bundler by requiring it in your Gemfile.
|
25
|
+
|
26
|
+
```
|
27
|
+
gem 'grape-throttle'
|
28
|
+
```
|
29
|
+
|
30
|
+
### Middleware Setup
|
31
|
+
|
32
|
+
Then in your Grape API, install the middleware which will do the throttling. At a minimum, it requires a Redis instance for caching as the `cache` parameter.
|
33
|
+
|
34
|
+
**Simple Case**
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
use Grape::Middleware::ThrottleMiddleware, cache: Redis.new
|
38
|
+
```
|
39
|
+
|
40
|
+
In this simple case, you just set up the middleware, and pass it a Redis instance.
|
41
|
+
|
42
|
+
**Advanced Case**
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
use Grape::Middleware::ThrottleMiddleware, cache: $redis, user_key: ->(env) do
|
46
|
+
# Use the current_user's id as an identifier
|
47
|
+
user = current_user
|
48
|
+
user.nil? ? nil : user.id
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
In this more advanced case, the Redis instance is in the global variable `$redis`.
|
53
|
+
|
54
|
+
The `user_key` parameter is a function that can be used to determine a custom identifier for a user. This key is used to form the Redis key to identify this user uniquely. It defaults to the IP address. The `env` parameter given to the function is the Rack environment and can be used to determine information about the caller.
|
55
|
+
|
56
|
+
**Logging**
|
57
|
+
|
58
|
+
The gem will log errors to STDOUT by default. If you prefer a different logger you can use the `logger` option to pass in your own logger.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
use Grape::Middleware::ThrottleMiddleware, cache: Redis.new, logger: Logger.new('my_custom_log.log')
|
62
|
+
```
|
63
|
+
|
64
|
+
### Endpoint Usage
|
65
|
+
|
66
|
+
This gem adds a `throttle` DSL-like method that can be used to throttle different endpoints differently.
|
67
|
+
|
68
|
+
The `throttle` method takes a Hash of the period to throttle, and the maximum allowed hits. After the maximum, the middleware throws an error with Grape's `error!` function.
|
69
|
+
|
70
|
+
Supported predefined periods are: `:hourly`, `:daily`, `:monthly`.
|
71
|
+
|
72
|
+
Example:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
class API < Grape::API
|
76
|
+
resources :users do
|
77
|
+
|
78
|
+
# Allow start of competition only every 10 minutes
|
79
|
+
desc "Start competition"
|
80
|
+
throttle period: 10.minutes, limit: 1
|
81
|
+
params do
|
82
|
+
requires :id, type: Integer, desc: "id"
|
83
|
+
end
|
84
|
+
post "/:id/competition" do
|
85
|
+
User.find(params[:id]).start_competition
|
86
|
+
end
|
87
|
+
|
88
|
+
# 3 times a day max
|
89
|
+
desc "Fetch a user"
|
90
|
+
throttle daily: 3
|
91
|
+
params do
|
92
|
+
requires :id, type: Integer, desc: "id"
|
93
|
+
end
|
94
|
+
get "/:id" do
|
95
|
+
User.find(params[:id])
|
96
|
+
end
|
97
|
+
|
98
|
+
# Once a month or the user will go crazy
|
99
|
+
desc "Poke a user"
|
100
|
+
throttle monthly: 1
|
101
|
+
params do
|
102
|
+
requires :id, type: Integer, desc: "id"
|
103
|
+
end
|
104
|
+
post "/:id/poke" do
|
105
|
+
User.find(params[:id]).poke
|
106
|
+
end
|
107
|
+
|
108
|
+
# No limit to the amount we can annoy users
|
109
|
+
desc "Annoy a user"
|
110
|
+
params do
|
111
|
+
requires :id, type: Integer, desc: "id"
|
112
|
+
end
|
113
|
+
post "/:id/annoy" do
|
114
|
+
User.find(params[:id]).annoy
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
```
|
119
|
+
|
120
|
+
## TODO
|
121
|
+
|
122
|
+
* Custom error handling and error strings, status etc.
|
123
|
+
* Allow use of something other than Redis for caching
|
124
|
+
|
125
|
+
## Thanks
|
126
|
+
|
127
|
+
Thanks to the awesome Grape community, and to @dblock for all the help getting this thing going.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'grape-throttler'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require 'pry'
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start
|
data/bin/rake
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# This file was generated by Bundler.
|
5
|
+
#
|
6
|
+
# The application 'rake' is installed as part of a gem, and
|
7
|
+
# this file is here to facilitate running it.
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', Pathname.new(__FILE__).realpath)
|
11
|
+
|
12
|
+
require 'rubygems'
|
13
|
+
require 'bundler/setup'
|
14
|
+
|
15
|
+
load Gem.bin_path('rake', 'rake')
|
data/bin/setup
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'grape-throttler/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'grape-throttler'
|
9
|
+
spec.version = GrapeThrottler::VERSION
|
10
|
+
spec.authors = ['Juan Gomez']
|
11
|
+
spec.email = ['j.gomez@drexed.com']
|
12
|
+
|
13
|
+
spec.summary = 'Gem for throttling grape requests.'
|
14
|
+
spec.description = 'A middleware for Grape to add endpoint-specific throttling.'
|
15
|
+
spec.homepage = 'http://drexed.github.io/grape-throttler'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
spec.bindir = 'exe'
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = %w[lib]
|
22
|
+
|
23
|
+
spec.add_runtime_dependency 'grape', '>= 0.16.0'
|
24
|
+
spec.add_runtime_dependency 'rails'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'bundler'
|
27
|
+
spec.add_development_dependency 'fakeredis'
|
28
|
+
spec.add_development_dependency 'fasterer'
|
29
|
+
spec.add_development_dependency 'rack-test'
|
30
|
+
spec.add_development_dependency 'rake'
|
31
|
+
spec.add_development_dependency 'reek'
|
32
|
+
spec.add_development_dependency 'rspec'
|
33
|
+
spec.add_development_dependency 'rubocop'
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
%w[grape logger].each do |file_name|
|
4
|
+
require file_name
|
5
|
+
end
|
6
|
+
|
7
|
+
%w[version extensions/throttle_extension].each do |file_name|
|
8
|
+
require "grape-throttler/#{file_name}"
|
9
|
+
end
|
10
|
+
|
11
|
+
module GrapeThrottler
|
12
|
+
module Middleware
|
13
|
+
|
14
|
+
autoload :ThrottleMiddleware, 'grape-throttler/middleware/throttle_middleware'
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GrapeThrottler
|
4
|
+
module Middleware
|
5
|
+
class ThrottleMiddleware < Grape::Middleware::Base
|
6
|
+
|
7
|
+
COUNTER_START ||= 0
|
8
|
+
|
9
|
+
def before
|
10
|
+
endpoint = env['api.endpoint']
|
11
|
+
logger = options[:logger] || Logger.new(STDOUT)
|
12
|
+
|
13
|
+
return unless throttle_options = endpoint.route_setting(:throttle)
|
14
|
+
|
15
|
+
limit, period = find_limit_and_period(throttle_options)
|
16
|
+
|
17
|
+
check_limit_and_period(limit, period)
|
18
|
+
|
19
|
+
limit = limit.call(env) if limit.is_a?(Proc)
|
20
|
+
return true if limit.negative?
|
21
|
+
|
22
|
+
user_value = find_user_value(options) || "ip:#{env['REMOTE_ADDR']}"
|
23
|
+
rate_key = generate_rate_key(endpoint, user_value)
|
24
|
+
|
25
|
+
begin
|
26
|
+
redis = options[:cache]
|
27
|
+
redis.ping
|
28
|
+
|
29
|
+
current = redis.get(rate_key).to_i
|
30
|
+
|
31
|
+
if !current.nil? && current >= limit
|
32
|
+
endpoint.error!('too many requests, please try again later', 429)
|
33
|
+
else
|
34
|
+
redis.multi do
|
35
|
+
redis.set(rate_key, COUNTER_START, { nx: true, ex: period.to_i })
|
36
|
+
redis.incr(rate_key)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
rescue Exception => e
|
40
|
+
logger.warn(e.message)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def check_limit_and_period(limit, period)
|
47
|
+
return unless limit.nil? || period.nil?
|
48
|
+
|
49
|
+
raise ArgumentError, 'Please set a period and limit (see documentation)'
|
50
|
+
end
|
51
|
+
|
52
|
+
def find_limit_and_period(throttle_options)
|
53
|
+
if limit = throttle_options[:hourly]
|
54
|
+
period = 1.hour
|
55
|
+
elsif limit = throttle_options[:daily]
|
56
|
+
period = 1.day
|
57
|
+
elsif limit = throttle_options[:monthly]
|
58
|
+
period = 1.month
|
59
|
+
elsif period = throttle_options[:period]
|
60
|
+
limit = throttle_options[:limit]
|
61
|
+
end
|
62
|
+
|
63
|
+
[limit, period]
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_user_value(options)
|
67
|
+
user_key = options[:user_key]
|
68
|
+
return if user_key.nil?
|
69
|
+
|
70
|
+
user_key.call(env)
|
71
|
+
end
|
72
|
+
|
73
|
+
def generate_rate_key(endpoint, user_value)
|
74
|
+
epoint = endpoint.routes.first
|
75
|
+
"#{epoint.request_method}:#{epoint.path}:#{user_value}"
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
metadata
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: grape-throttler
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Juan Gomez
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-09-18 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.16.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.16.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
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: bundler
|
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: fakeredis
|
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: fasterer
|
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
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rack-test
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: reek
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rubocop
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
description: A middleware for Grape to add endpoint-specific throttling.
|
154
|
+
email:
|
155
|
+
- j.gomez@drexed.com
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- ".fasterer.yml"
|
161
|
+
- ".gitattributes"
|
162
|
+
- ".gitignore"
|
163
|
+
- ".irbrc"
|
164
|
+
- ".reek.yml"
|
165
|
+
- ".rspec"
|
166
|
+
- ".rubocop.yml"
|
167
|
+
- ".ruby-version"
|
168
|
+
- ".travis.yml"
|
169
|
+
- CODE_OF_CONDUCT.md
|
170
|
+
- Gemfile
|
171
|
+
- README.md
|
172
|
+
- Rakefile
|
173
|
+
- bin/console
|
174
|
+
- bin/rake
|
175
|
+
- bin/setup
|
176
|
+
- grape-throttler.gemspec
|
177
|
+
- lib/grape-throttler.rb
|
178
|
+
- lib/grape-throttler/extensions/throttle_extension.rb
|
179
|
+
- lib/grape-throttler/middleware/throttle_middleware.rb
|
180
|
+
- lib/grape-throttler/version.rb
|
181
|
+
homepage: http://drexed.github.io/grape-throttler
|
182
|
+
licenses:
|
183
|
+
- MIT
|
184
|
+
metadata: {}
|
185
|
+
post_install_message:
|
186
|
+
rdoc_options: []
|
187
|
+
require_paths:
|
188
|
+
- lib
|
189
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
190
|
+
requirements:
|
191
|
+
- - ">="
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: '0'
|
194
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
195
|
+
requirements:
|
196
|
+
- - ">="
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: '0'
|
199
|
+
requirements: []
|
200
|
+
rubyforge_project:
|
201
|
+
rubygems_version: 2.7.7
|
202
|
+
signing_key:
|
203
|
+
specification_version: 4
|
204
|
+
summary: Gem for throttling grape requests.
|
205
|
+
test_files: []
|