rack-defense 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3ece635cf91bb8348db49468754161d10d7263d8
4
- data.tar.gz: 9e83f747514c973078fde57e36f370d1429e8188
3
+ metadata.gz: 9e47fe356fd72d70737af5ff0d64db8f823e1e93
4
+ data.tar.gz: 62972c5a9e0258ffccd3af644d9e191526686e2a
5
5
  SHA512:
6
- metadata.gz: c2c434565856a67d7dba649a8d17fc140242e086038c4f61fc6f08e05a6215779f8f76f0baf2fcc0a0fd5e9ff2fcacedb0ba9cc5e737ef21fbd417b29792e2fe
7
- data.tar.gz: 78d36f081d9084174c7922d48977f48cf2e38eabf800ddbcff5d17388eb312175d0c32e63765eef393b0054568a535bd716eee06fb955316d80615b53d511c70
6
+ metadata.gz: e09969ed7c4615439aa3f4dd105b992925cf48e7da9b0549f44c3f7757cbf8e4c46cdc5380edf0a66a5d3bb7c1bb8c2505062393a6600003dce6531f8b4f2840
7
+ data.tar.gz: c7258b578750efd00ce4046c8f3f6fa6daf97a0390a80b1a10df887bc22edf91894f7c6f49b00bfeda59724288c22dfc4e8fe776041ac457425c57a96d3b36e0
data/README.md CHANGED
@@ -3,8 +3,10 @@ Rack::Defense
3
3
 
4
4
  A Rack middleware for throttling and filtering requests.
5
5
 
6
- [![Code Climate](https://codeclimate.com/github/Sinbadsoft/rack-defense/badges/gpa.svg)](https://codeclimate.com/github/Sinbadsoft/rack-defense) [![Build Status](https://travis-ci.org/Sinbadsoft/rack-defense.svg)](https://travis-ci.org/Sinbadsoft/rack-defense)
6
+ [![Build Status](https://travis-ci.org/Sinbadsoft/rack-defense.svg)](https://travis-ci.org/Sinbadsoft/rack-defense)
7
+ [![Code Climate](https://codeclimate.com/github/Sinbadsoft/rack-defense/badges/gpa.svg)](https://codeclimate.com/github/Sinbadsoft/rack-defense)
7
8
  [![Dependency Status](https://gemnasium.com/Sinbadsoft/rack-defense.svg)](https://gemnasium.com/Sinbadsoft/rack-defense)
9
+ [![Gem Version](https://badge.fury.io/rb/rack-defense.svg)](http://badge.fury.io/rb/rack-defense)
8
10
 
9
11
  Rack::Defense is a Rack middleware that allows you to easily add request rate limiting and request filtering to your Rack based application (Ruby On Rails, Sinatra etc.).
10
12
 
@@ -14,6 +16,8 @@ Rack::Defense is a Rack middleware that allows you to easily add request rate li
14
16
 
15
17
  Rack::Defense has a small footprint and only two dependencies: [rack](https://github.com/rack/rack) and [redis](https://github.com/redis/redis-rb).
16
18
 
19
+ Rack::Defense is inspired from the [Rack::Attack](https://github.com/kickstarter/rack-attack) project. The main difference is the throttling algorithm: Rack::Attack uses a counter reset at the end of each period, therefore allowing up to 2 times more requests than the maximum rate specified. We use a sliding window algorithm allowing a precise request rate limiting.
20
+
17
21
  ## Getting started
18
22
 
19
23
  Install the rack-defense gem; or add it to you Gemfile with bundler:
@@ -43,7 +47,7 @@ end
43
47
  ```
44
48
 
45
49
  ## Throttling
46
- The Rack::Defense middleware evaluates the throttling criterias (lambadas) against the incoming request. If the return value is falsy, the request is not throttled. Otherwise, the returned value is used as a key to throttle the request. The returned key could be the request IP, user name, API token or any discriminator to throttle the requests against.
50
+ The Rack::Defense middleware evaluates the throttling criterias (lambdas) against the incoming request. If the return value is falsy, the request is not throttled. Otherwise, the returned value is used as a key to throttle the request. The returned key could be the request IP, user name, API token or any discriminator to throttle the requests against.
47
51
 
48
52
  ### Examples
49
53
 
@@ -71,13 +75,13 @@ Rack::Defense uses Redis to track request rates. By default, the `REDIS_URL` env
71
75
  The redis store can be setup with either a connection url:
72
76
  ```ruby
73
77
  Rack::Defense.setup do |config|
74
- store = "redis://:p4ssw0rd@10.0.1.1:6380/15"
78
+ config.store = "redis://:p4ssw0rd@10.0.1.1:6380/15"
75
79
  end
76
80
  ```
77
81
  or directly with a connection object:
78
82
  ```ruby
79
83
  Rack::Defense.setup do |config|
80
- store = Redis.new(host: "10.0.1.1", port: 6380, db: 15)
84
+ config.store = Redis.new(host: "10.0.1.1", port: 6380, db: 15)
81
85
  end
82
86
  ```
83
87
 
@@ -98,7 +102,7 @@ end
98
102
  Allow only requests with a known API authorization token:
99
103
  ```ruby
100
104
  Rack::Defense.setup do |config|
101
- config.ban('allow_only_ip_list') do |req|
105
+ config.ban('validate_api_token') do |req|
102
106
  %r{^/api/} =~ req.path && Redis.current.sismember('apitokens', req.env['HTTP_AUTHORIZATION'])
103
107
  end
104
108
  end
@@ -111,19 +115,19 @@ By default, Rack::Defense returns `429 Too Many Requests` and `403 Forbidden` re
111
115
  ```ruby
112
116
  Rack::Defense.setup do |config|
113
117
  config.banned_response =
114
- ->(env) { [404, {'Content-Type' => 'text/plain'}, ["Not Found"]] }
118
+ ->(env) { [404, {'Content-Type' => 'text/plain'}, ["Not Found\n"]] }
115
119
 
116
120
  config.throttled_response =
117
- ->(env) { [503, {'Content-Type' => 'text/plain'}, ["Service Unavailable"]] }
121
+ ->(env) { [503, {'Content-Type' => 'text/plain'}, ["Service Unavailable\n"]] }
118
122
  end
119
123
  end
120
124
  ```
121
125
 
122
126
  ## License
123
127
 
124
- Copyright [Sinbadsoft](http://www.sinbadsoft.com).
125
-
126
128
  Licensed under the [MIT License](http://opensource.org/licenses/MIT).
127
129
 
130
+ Copyright Sinbadsoft.
131
+
128
132
 
129
133
 
data/lib/rack/defense.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'rack'
2
2
  require 'redis'
3
+ require 'delegate'
3
4
 
4
5
  class Rack::Defense
5
6
  autoload :ThrottleCounter, 'rack/defense/throttle_counter'
@@ -29,13 +30,15 @@ class Rack::Defense
29
30
  end
30
31
 
31
32
  def store=(value)
32
- @store = value.is_a?(String) ? Redis.new(url: value) : value
33
+ value = Redis.new(url: value) if value.is_a?(String)
34
+ @store = SimpleDelegator::new(value) unless @store
35
+ @store.__setobj__(value)
33
36
  end
34
37
 
35
38
  def store
36
39
  # Redis.new uses REDIS_URL environment variable by default as URL.
37
40
  # See https://github.com/redis/redis-rb
38
- @store ||= Redis.new
41
+ @store ||= SimpleDelegator.new(Redis.new)
39
42
  end
40
43
  end
41
44
 
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class Defense
3
- VERSION = '0.1.0'
3
+ VERSION = '0.1.1'
4
4
  end
5
5
  end
@@ -0,0 +1,32 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe Rack::Defense::Config do
4
+ before do
5
+ @config = Rack::Defense::Config.new
6
+ end
7
+
8
+ describe 'store' do
9
+ it 'creates store instance from connection string' do
10
+ url = 'redis://localhost:4444'
11
+ @config.store = url
12
+ assert url, conn_url(@config.store)
13
+ end
14
+
15
+ it 'update proxied store instance when store config changes' do
16
+ obj1, obj2 = Redis.new(url: 'redis://localhost:3333'), Redis.new(url: 'redis://localhost:4444')
17
+
18
+ @config.store = obj1
19
+ assert conn_url(obj1), conn_url(@config.store)
20
+
21
+ cached_store = @config.store
22
+
23
+ @config.store = obj2
24
+ assert conn_url(obj2), conn_url(@config.store)
25
+ assert conn_url(obj2), conn_url(cached_store)
26
+ end
27
+
28
+ def conn_url(conn)
29
+ conn.client.options[:url]
30
+ end
31
+ end
32
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-defense
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chaker Nakhli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-09 00:00:00.000000000 Z
11
+ date: 2014-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -16,40 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.5'
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: 1.5.2
19
+ version: '1.3'
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
24
  - - "~>"
28
25
  - !ruby/object:Gem::Version
29
- version: '1.5'
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: 1.5.2
26
+ version: '1.3'
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: redis
35
29
  requirement: !ruby/object:Gem::Requirement
36
30
  requirements:
37
31
  - - "~>"
38
32
  - !ruby/object:Gem::Version
39
- version: '3.1'
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- version: 3.1.0
33
+ version: '3'
43
34
  type: :runtime
44
35
  prerelease: false
45
36
  version_requirements: !ruby/object:Gem::Requirement
46
37
  requirements:
47
38
  - - "~>"
48
39
  - !ruby/object:Gem::Version
49
- version: '3.1'
50
- - - ">="
51
- - !ruby/object:Gem::Version
52
- version: 3.1.0
40
+ version: '3'
53
41
  - !ruby/object:Gem::Dependency
54
42
  name: rake
55
43
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +107,7 @@ files:
119
107
  - lib/rack/defense/throttle_counter.rb
120
108
  - lib/rack/defense/version.rb
121
109
  - spec/defense_ban_spec.rb
110
+ - spec/defense_config_spec.rb
122
111
  - spec/defense_throttle_spec.rb
123
112
  - spec/spec_helper.rb
124
113
  - spec/throttle_counter_spec.rb
@@ -150,5 +139,6 @@ summary: Throttle and filter requests
150
139
  test_files:
151
140
  - spec/spec_helper.rb
152
141
  - spec/throttle_counter_spec.rb
142
+ - spec/defense_config_spec.rb
153
143
  - spec/defense_ban_spec.rb
154
144
  - spec/defense_throttle_spec.rb