nexaas-throttle 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9cb1900d065141e8dc4b5384ff4b10c21dfdf043
4
+ data.tar.gz: 618e61a05861dadcd008de417c9dc2e849db9184
5
+ SHA512:
6
+ metadata.gz: 97f5de60d31737b5ac144e9142933cc85717b4fc643ef8face97a2cc6c25245aec597f3a9483eac0705c4b032791dc1c5617200737d45946ec52bd1bb5fed11c
7
+ data.tar.gz: 1f2227b57f27d51ba9c2085a9f581a4bbe70b09b8b61ac7fff20e12878c95a46d17346dc989748592020a63aad444ea1999abdf53f6adab787ceb53f3ab93a29
data/.codeclimate.yml ADDED
@@ -0,0 +1,16 @@
1
+ ---
2
+ engines:
3
+ duplication:
4
+ enabled: true
5
+ config:
6
+ languages:
7
+ - ruby
8
+ fixme:
9
+ enabled: true
10
+ rubocop:
11
+ enabled: true
12
+ ratings:
13
+ paths:
14
+ - "**.rb"
15
+ exclude_paths:
16
+ - spec/
data/.gitignore ADDED
@@ -0,0 +1,52 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ /Gemfile.lock
46
+ /.ruby-version
47
+ /.ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
51
+ *.log
52
+ /log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,31 @@
1
+ AllCops:
2
+ Exclude:
3
+ - "nexaas-throttle.gemspec"
4
+
5
+ Metrics/LineLength:
6
+ StyleGuide: "https://github.com/bbatsov/ruby-style-guide#80-character-limits"
7
+ Max: 120
8
+
9
+ Style/Alias:
10
+ EnforcedStyle: "prefer_alias_method"
11
+
12
+ Style/AsciiComments:
13
+ StyleGuide: "https://github.com/bbatsov/ruby-style-guide#english-comments"
14
+ Enabled: false
15
+
16
+ Style/Documentation:
17
+ Enabled: false
18
+
19
+ Style/DotPosition:
20
+ EnforcedStyle: trailing
21
+
22
+ Style/ParallelAssignment:
23
+ StyleGuide: "https://github.com/bbatsov/ruby-style-guide#parallel-assignment"
24
+ Enabled: false
25
+
26
+ Style/SpaceAroundEqualsInParameterDefault:
27
+ EnforcedStyle: space
28
+
29
+ Style/StringLiterals:
30
+ StyleGuide: "https://github.com/bbatsov/ruby-style-guide#consistent-string-literals"
31
+ EnforcedStyle: double_quotes
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.5
5
+ - 2.3.1
6
+ before_install: gem install bundler -v 1.12.5
7
+ script: bundle exec rake spec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in throttle.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Myfreecomm
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # Nexaas::Throttle
2
+
3
+ [![Build Status](https://travis-ci.org/myfreecomm/nexaas-throttle.svg?branch=master)](https://travis-ci.org/myfreecomm/nexaas-throttle)
4
+ [![Test Coverage](https://codeclimate.com/github/myfreecomm/nexaas-throttle/badges/coverage.svg)](https://codeclimate.com/github/myfreecomm/nexaas-throttle/coverage)
5
+ [![Code Climate](https://codeclimate.com/github/myfreecomm/nexaas-throttle/badges/gpa.svg)](https://codeclimate.com/github/myfreecomm/nexaas-throttle)
6
+
7
+ A configurable Rails engine that provides a common way of reducing API abuse, throttling consumers' requests and blocking undesired pentesters and robots.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'nexaas-throttle'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install nexaas-throttle
24
+
25
+ ## Usage
26
+
27
+ In a Rails initializer file such as `config/initializers/nexaas_throttle.rb`, put something like this:
28
+
29
+ ```ruby
30
+ require "nexaas/throttle"
31
+
32
+ Nexaas::Throttle.configure do |config|
33
+ config.throttle = true
34
+ config.track = true
35
+ config.period = 1.minute
36
+ config.limit = 2
37
+ config.request_identifier = MyRequestIdentifier
38
+ config.redis_options = {
39
+ host: "localhost",
40
+ port: 6379,
41
+ db: 0,
42
+ namespace: "nexaas:throttle"
43
+ }
44
+ end
45
+ ```
46
+
47
+ ### Configuration
48
+
49
+ <table>
50
+ <tr>
51
+ <th>Option</th>
52
+ <th>Description</th>
53
+ <th>Default</th>
54
+ </tr>
55
+ <tr>
56
+ <td><code>throttle</code></td>
57
+ <td>Whether or not requests are throttled.</td>
58
+ <td><code>true</code></td>
59
+ </tr>
60
+ <tr>
61
+ <td><code>track</code></td>
62
+ <td>Whether or not requests are tracked.</td>
63
+ <td><code>true</code></td>
64
+ </tr>
65
+ <tr>
66
+ <td><code>period</code></td>
67
+ <td>The size of the throttle window.</td>
68
+ <td><code>1 minute</code></td>
69
+ </tr>
70
+ <tr>
71
+ <td><code>limit</code></td>
72
+ <td>How many requests a consumer can do during a window until he starts being throttled.</td>
73
+ <td><code>60 requests</code></td>
74
+ </tr>
75
+ <tr>
76
+ <td><code>request_identifier</code></td>
77
+ <td>The class that will handle request identification. See <a href="#request-identification">Request Identification</a> for more details.</td>
78
+ <td><code>nil</code></td>
79
+ </tr>
80
+ <tr>
81
+ <td><code>redis_options</code></td>
82
+ <td>Redis hash configuration where requests counters are persisted.</td>
83
+ <td>
84
+ <pre>
85
+ {
86
+ host: "localhost",
87
+ port: 6379,
88
+ db: 0,
89
+ namespace: "nexaas:throttle"
90
+ }
91
+ </pre>
92
+ </td>
93
+ </tr>
94
+ </table>
95
+
96
+ ### Request Identification
97
+
98
+ `Nexaas::Throttle` doesn't know how to identify a consumer. Some applications might rely on request IP, others on an API TOKEN. You must provide a way of getting an unique token
99
+ that identify a request consumer.
100
+
101
+ `Nexaas::Throttle` do this by providing a configuration `request_identifier`, a class where your application would keep the logic that identifies a consumer. This class must have the following
102
+ interface:
103
+
104
+ ```ruby
105
+ class MyRequestIdentifier
106
+ def initialize(request)
107
+ @request = request
108
+ end
109
+
110
+ def token
111
+ @request.ip
112
+ # or @request.env["HTTP_AUTHORIZATION"]
113
+ # or User.find_by(token: @request.params[:token])
114
+ # or Cache.read(@request.params[:token])
115
+ end
116
+ end
117
+ ```
118
+
119
+ ### Tracking requests
120
+
121
+ In order to track your requests, you must subscribe to a event triggered by `Rack::Attack` gem as below:
122
+
123
+ ```ruby
124
+ ActiveSupport::Notifications.subscribe("rack.attack") do |name, start, finish, request_id, request|
125
+ if request.env["rack.attack.matched"] == "nexaas/track" && request.env["rack.attack.match_type"] == :track
126
+ # Put your tracking logic here
127
+ # You can use request.env["nexaas.token"] to obtain the token provided by your request_identifier
128
+ end
129
+ end
130
+ ```
131
+
132
+ If you want, you can access the request token by inspecting `request.env["nexaas.token"]`. This is the token your `request_identifier` provided after evaluating the request.
133
+
134
+ ## Development
135
+
136
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
137
+
138
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
139
+
140
+ ## Contributing
141
+
142
+ Bug reports and pull requests are welcome on GitHub at https://github.com/myfreecomm/nexaas-throttle.
143
+
144
+
145
+ ## License
146
+
147
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
148
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rails/all"
5
+ require "nexaas/throttle"
6
+
7
+ require_relative "../spec/support/dummy_app"
8
+
9
+ # You can add fixtures and/or initialization code here to make experimenting
10
+ # with your gem easier. You can also use a different console, if you like.
11
+
12
+ # (If you use this, don't forget to add pry to your Gemfile!)
13
+ # require "pry"
14
+ # Pry.start
15
+
16
+ require "irb"
17
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,17 @@
1
+ require "nexaas/throttle/version"
2
+ require "nexaas/throttle/configuration"
3
+ require "nexaas/throttle/engine"
4
+ require "nexaas/throttle/guardian"
5
+
6
+ module Nexaas
7
+ module Throttle
8
+ def self.configure
9
+ yield(configuration) if block_given?
10
+ configuration.check!
11
+ end
12
+
13
+ def self.configuration
14
+ @configuration ||= Configuration.new
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,79 @@
1
+ module Nexaas
2
+ module Throttle
3
+ class Configuration
4
+ # Whether or not requests are throttled.
5
+ # @return [Boolean]
6
+ attr_accessor :throttle
7
+
8
+ # Whether or not requests are tracked.
9
+ # @return [Boolean]
10
+ attr_accessor :track
11
+
12
+ # The size of the throttle window.
13
+ # Example: 1.minute, 1.hour, 60(s)
14
+ # @return [Integer]
15
+ attr_accessor :period
16
+
17
+ # How many requests a consumer can do during a window until he starts being throttled.
18
+ # Example: 60
19
+ # @return [Integer]
20
+ attr_accessor :limit
21
+
22
+ # The class that will handle request identification.
23
+ # Each application handle with different domains on identifying a request,
24
+ # so they have to provide information on who is the requester based on their domain.
25
+ # This class MUST have the following interface:
26
+ # MyRequestIdentifier#initialize(request)
27
+ # MyRequestIdentifier#token
28
+ # Where MyRequestIdentifier#token must be a UNIQUE identifier from the requester.
29
+ # @return [Class]
30
+ attr_accessor :request_identifier
31
+
32
+ # Redis hash configuration with the following default values:
33
+ # - host => localhost
34
+ # - port => 6379
35
+ # - db => 0
36
+ # - namespace => nexaas:throttle
37
+ # @return [Hash]
38
+ attr_reader :redis_options
39
+
40
+ alias_method :throttleable?, :throttle
41
+ alias_method :trackable?, :track
42
+
43
+ def initialize
44
+ @throttle = true
45
+ @track = true
46
+ @period = 1.minute
47
+ @limit = 60
48
+ @request_identifier = nil
49
+ @redis_options = default_redis_options
50
+ end
51
+
52
+ def check!
53
+ required_options.each do |option|
54
+ raise ArgumentError, "You must provide a `#{option}` configuration." if send(option).blank?
55
+ end
56
+ end
57
+
58
+ def redis_options=(options)
59
+ options ||= {}
60
+ @redis_options = default_redis_options.merge(options)
61
+ end
62
+
63
+ private
64
+
65
+ def required_options
66
+ %w(period limit request_identifier redis_options)
67
+ end
68
+
69
+ def default_redis_options
70
+ {
71
+ host: "localhost",
72
+ port: 6379,
73
+ db: 0,
74
+ namespace: "nexaas:throttle"
75
+ }
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,10 @@
1
+ module Nexaas
2
+ module Throttle
3
+ class Engine < ::Rails::Engine
4
+ initializer "nexaas.throttle.insert_middleware", before: "initialize_cache" do |app|
5
+ require "nexaas/throttle/middleware"
6
+ app.middleware.use Nexaas::Throttle::Middleware
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,47 @@
1
+ require "base64"
2
+
3
+ module Nexaas
4
+ module Throttle
5
+ class Guardian
6
+ def initialize(request, request_identifier)
7
+ @request = request
8
+ @token = request_identifier.new(request).token
9
+ end
10
+
11
+ def throttle!
12
+ validate { token }
13
+ end
14
+
15
+ def track!
16
+ validate { true }
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :request, :token
22
+
23
+ def validate
24
+ return if assets? || !api? || token.blank?
25
+ request.env["nexaas.token"] = token
26
+ yield if block_given?
27
+ end
28
+
29
+ def assets?
30
+ path = request.path
31
+ path.match(/\/assets/).present? || path.match(extensions_regexp).present?
32
+ end
33
+
34
+ def api?
35
+ content_type = (request.media_type || request.env["Content-Type"]).to_s
36
+ %w(application/json application/xml).include?(content_type)
37
+ end
38
+
39
+ def extensions_regexp
40
+ @assets_extensions ||= begin
41
+ extensions = %w(css js png jpg gif)
42
+ /\.(#{extensions.join("|")})/
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,97 @@
1
+ require "redis-activesupport"
2
+ require "rack/attack"
3
+
4
+ module Rack
5
+ class Attack
6
+ def self.configuration
7
+ @configuration ||= Nexaas::Throttle.configuration
8
+ end
9
+
10
+ def self.guardian(request)
11
+ Nexaas::Throttle::Guardian.new(request, configuration.request_identifier)
12
+ end
13
+
14
+ def self.throttled?(req)
15
+ throttled = throttles.any? do |name, throttle|
16
+ throttle[req]
17
+ end
18
+
19
+ throttled && configuration.throttleable?
20
+ end
21
+
22
+ self.cache.store = ActiveSupport::Cache::RedisStore.new(configuration.redis_options)
23
+ self.throttled_response = lambda do |env|
24
+ headers = {
25
+ "Content-Type" => (env["CONTENT_TYPE"] || env["Content-Type"]).to_s,
26
+ "Retry-After" => (env["rack.attack.match_data"] || {})[:period].to_s
27
+ }
28
+
29
+ [429, headers, ["Retry later\n"]]
30
+ end
31
+
32
+ throttle("nexaas/throttle", limit: configuration.limit, period: configuration.period) do |request|
33
+ guardian(request).throttle!
34
+ end
35
+
36
+ track("nexaas/track") do |request|
37
+ guardian(request).track! if configuration.trackable?
38
+ end
39
+ end
40
+ end
41
+
42
+ module Nexaas
43
+ module Throttle
44
+ class Middleware
45
+ def initialize(app)
46
+ @app = app
47
+ end
48
+
49
+ def call(env)
50
+ status, headers, body = Rack::Attack.new(@app).call(env)
51
+ headers.merge!(rate_limit_headers(env)) if rate_limit_available?(env)
52
+ [status, headers, body]
53
+ end
54
+
55
+ private
56
+
57
+ def rack_attack_key
58
+ "rack.attack.throttle_data"
59
+ end
60
+
61
+ def rate_limit_available?(env)
62
+ env.key?(rack_attack_key) && env[rack_attack_key].key?("nexaas/throttle")
63
+ end
64
+
65
+ def rate_limit_headers(env)
66
+ data = limit_data(env)
67
+ return {} if data[:period].nil?
68
+
69
+ {
70
+ "X-RateLimit-Limit" => limit(data),
71
+ "X-RateLimit-Reset" => reset(data),
72
+ "X-RateLimit-Remaining" => remaining(data)
73
+ }
74
+ end
75
+
76
+ def limit_data(env)
77
+ data = env["rack.attack.match_data"]
78
+ data ||= (env["rack.attack.throttle_data"] || {})["nexaas/throttle"]
79
+ data || {}
80
+ end
81
+
82
+ def limit(limit_data)
83
+ limit_data[:limit].to_s
84
+ end
85
+
86
+ def reset(limit_data)
87
+ now = Time.now.utc
88
+ period = limit_data[:period]
89
+ (now + (period - now.to_i % period)).iso8601.to_s
90
+ end
91
+
92
+ def remaining(limit_data)
93
+ (limit_data[:limit].to_i - limit_data[:count].to_i).to_s
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,5 @@
1
+ module Nexaas
2
+ module Throttle
3
+ VERSION = "0.1.0".freeze
4
+ end
5
+ end
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "nexaas/throttle/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "nexaas-throttle"
8
+ spec.version = Nexaas::Throttle::VERSION
9
+ spec.authors = ["Wanderson Policarpo"]
10
+ spec.email = ["wanderson.policarpo@myfreecomm.com.br"]
11
+
12
+ spec.summary = %q{A tiny engine to allow throttling and blacklisting requests.}
13
+ spec.description = %q{A tiny engine to allow throttling and blacklisting requests.}
14
+ spec.homepage = "https://nexaas.com"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the "allowed_push_host"
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
21
+ else
22
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_development_dependency "bundler", "~> 1.12"
31
+ spec.add_development_dependency "rake", "~> 10.0"
32
+ spec.add_development_dependency "rspec-rails", "~> 3.5"
33
+ spec.add_development_dependency "rails"
34
+ spec.add_development_dependency "fakeredis"
35
+ spec.add_development_dependency "codeclimate-test-reporter", "~> 0.6"
36
+ spec.add_development_dependency "simplecov", "~> 0.12"
37
+
38
+ spec.add_dependency "rack-attack", "~> 4.4"
39
+ spec.add_dependency "redis-activesupport", "~> 5.0"
40
+ end
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nexaas-throttle
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Wanderson Policarpo
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-08-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rails
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'
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: codeclimate-test-reporter
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'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.12'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.12'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rack-attack
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '4.4'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '4.4'
125
+ - !ruby/object:Gem::Dependency
126
+ name: redis-activesupport
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '5.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '5.0'
139
+ description: A tiny engine to allow throttling and blacklisting requests.
140
+ email:
141
+ - wanderson.policarpo@myfreecomm.com.br
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".codeclimate.yml"
147
+ - ".gitignore"
148
+ - ".rspec"
149
+ - ".rubocop.yml"
150
+ - ".travis.yml"
151
+ - Gemfile
152
+ - LICENSE
153
+ - README.md
154
+ - Rakefile
155
+ - bin/console
156
+ - bin/setup
157
+ - lib/nexaas/throttle.rb
158
+ - lib/nexaas/throttle/configuration.rb
159
+ - lib/nexaas/throttle/engine.rb
160
+ - lib/nexaas/throttle/guardian.rb
161
+ - lib/nexaas/throttle/middleware.rb
162
+ - lib/nexaas/throttle/version.rb
163
+ - nexaas-throttle.gemspec
164
+ homepage: https://nexaas.com
165
+ licenses:
166
+ - MIT
167
+ metadata:
168
+ allowed_push_host: https://rubygems.org
169
+ post_install_message:
170
+ rdoc_options: []
171
+ require_paths:
172
+ - lib
173
+ required_ruby_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ version: '0'
183
+ requirements: []
184
+ rubyforge_project:
185
+ rubygems_version: 2.5.1
186
+ signing_key:
187
+ specification_version: 4
188
+ summary: A tiny engine to allow throttling and blacklisting requests.
189
+ test_files: []