improved-rack-throttle 0.5.0 → 0.6.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.
- data/README.md +29 -5
- data/improved-rack-throttle.gemspec +8 -4
- data/lib/rack/throttle.rb +1 -0
- data/lib/rack/throttle/matchers/url_matcher.rb +1 -1
- data/lib/rack/throttle/matchers/{ip_matcher.rb → user_agent_matcher.rb} +3 -3
- data/lib/rack/throttle/version.rb +1 -1
- data/spec/url_matcher_spec.rb +1 -1
- data/spec/user_agent_matcher_spec.rb +28 -0
- metadata +18 -17
data/README.md
CHANGED
|
@@ -15,10 +15,13 @@ Features
|
|
|
15
15
|
subsequent HTTP requests from a particular client, as well as by defining
|
|
16
16
|
a maximum number of allowed HTTP requests per a given time period (hourly
|
|
17
17
|
or daily).
|
|
18
|
+
* Scopes throttling rules by request path, http method, or user_agent
|
|
19
|
+
for applications that need a variety of rules
|
|
18
20
|
* Compatible with any Rack application and any Rack-based framework.
|
|
19
21
|
* Stores rate-limiting counters in any key/value store implementation that
|
|
20
22
|
responds to `#[]`/`#[]=` (like Ruby's hashes) or to `#get`/`#set` (like
|
|
21
|
-
memcached or Redis).
|
|
23
|
+
memcached or Redis). This makes it easy to use global counters across
|
|
24
|
+
multiple web servers.
|
|
22
25
|
* Compatible with the [gdbm][] binding included in Ruby's standard library.
|
|
23
26
|
* Compatible with the [memcached][], [memcache-client][], [memcache][] and
|
|
24
27
|
[redis][] gems.
|
|
@@ -92,6 +95,10 @@ Examples
|
|
|
92
95
|
|
|
93
96
|
use Rack::Throttle::Interval, :cache => Redis.new, :key_prefix => :throttle
|
|
94
97
|
|
|
98
|
+
### Scoping the rate-limit to a specific path and method
|
|
99
|
+
|
|
100
|
+
use Rack::Throttle::Interval, :rules => {:url => /api/, :method => :post}
|
|
101
|
+
|
|
95
102
|
Throttling Strategies
|
|
96
103
|
---------------------
|
|
97
104
|
|
|
@@ -115,6 +122,17 @@ significantly more complex than what we've provided for, you can also define
|
|
|
115
122
|
entirely new kinds of throttling strategies by subclassing the
|
|
116
123
|
`Rack::Throttle::Limiter` base class directly.
|
|
117
124
|
|
|
125
|
+
Scoping Rules
|
|
126
|
+
-------------
|
|
127
|
+
Rack::Throttle ships with a Rack::Throttle::Matcher base class, and three
|
|
128
|
+
implementations of it. Rack::Throttle::UrlMatcher and
|
|
129
|
+
Rack::Throttle::UserAgentMatcher allow you to pass in regular expressions
|
|
130
|
+
for request path and user agent, while Rack::Throttle::MethodMatcher
|
|
131
|
+
will filter by request method when passed a Symbol :get, :post, :put, or
|
|
132
|
+
:delete. These rules are additive, so you can throttle just POST
|
|
133
|
+
requests to your '/login' page, for example.
|
|
134
|
+
|
|
135
|
+
|
|
118
136
|
HTTP Client Identification
|
|
119
137
|
--------------------------
|
|
120
138
|
|
|
@@ -158,6 +176,7 @@ status code by passing in a `:code => 503` option when constructing a
|
|
|
158
176
|
|
|
159
177
|
Documentation
|
|
160
178
|
-------------
|
|
179
|
+
OUT OF DATE
|
|
161
180
|
|
|
162
181
|
<http://datagraph.rubyforge.org/rack-throttle/>
|
|
163
182
|
|
|
@@ -177,23 +196,23 @@ Installation
|
|
|
177
196
|
The recommended installation method is via [RubyGems](http://rubygems.org/).
|
|
178
197
|
To install the latest official release of the gem, do:
|
|
179
198
|
|
|
180
|
-
% [sudo] gem install rack-throttle
|
|
199
|
+
% [sudo] gem install improved-rack-throttle
|
|
181
200
|
|
|
182
201
|
Download
|
|
183
202
|
--------
|
|
184
203
|
|
|
185
204
|
To get a local working copy of the development repository, do:
|
|
186
205
|
|
|
187
|
-
% git clone git://github.com/
|
|
206
|
+
% git clone git://github.com/bensomers/improved-rack-throttle.git
|
|
188
207
|
|
|
189
208
|
Alternatively, you can download the latest development version as a tarball
|
|
190
209
|
as follows:
|
|
191
210
|
|
|
192
|
-
% wget http://github.com/
|
|
211
|
+
% wget http://github.com/bensomers/improved-rack-throttle/tarball/master
|
|
193
212
|
|
|
194
213
|
Authors
|
|
195
214
|
-------
|
|
196
|
-
|
|
215
|
+
* [Ben Somers](mailto:somers.ben@gmail.com) - <http://www.somanyrobots.com>
|
|
197
216
|
* [Arto Bendiken](mailto:arto.bendiken@gmail.com) - <http://ar.to/>
|
|
198
217
|
* [Brendon Murphy](mailto:disposable.20.xternal@spamourmet.com>) - <http://www.techfreak.net/>
|
|
199
218
|
|
|
@@ -211,3 +230,8 @@ information, see <http://unlicense.org/> or the accompanying UNLICENSE file.
|
|
|
211
230
|
[redis]: http://rubygems.org/gems/redis
|
|
212
231
|
[Heroku]: http://heroku.com/
|
|
213
232
|
[Heroku memcache]: http://docs.heroku.com/memcache
|
|
233
|
+
|
|
234
|
+
Support
|
|
235
|
+
-------
|
|
236
|
+
|
|
237
|
+
Recent work on improved-rack-throttle has been funded by Rafter, Inc.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = "improved-rack-throttle"
|
|
8
|
-
s.version = "0.
|
|
8
|
+
s.version = "0.6.0"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Ben Somers", "Arto Bendiken", "Brendon Murphy"]
|
|
@@ -13,10 +13,12 @@ Gem::Specification.new do |s|
|
|
|
13
13
|
s.description = "Rack middleware for rate-limiting incoming HTTP requests."
|
|
14
14
|
s.email = "somers.ben@gmail.com"
|
|
15
15
|
s.extra_rdoc_files = [
|
|
16
|
-
"UNLICENSE",
|
|
17
16
|
"README.md"
|
|
18
17
|
]
|
|
19
18
|
s.files = [
|
|
19
|
+
".document",
|
|
20
|
+
"Gemfile",
|
|
21
|
+
"Gemfile.lock",
|
|
20
22
|
"README.md",
|
|
21
23
|
"Rakefile",
|
|
22
24
|
"UNLICENSE",
|
|
@@ -27,15 +29,16 @@ Gem::Specification.new do |s|
|
|
|
27
29
|
"etc/memcache.ru",
|
|
28
30
|
"etc/memcached.ru",
|
|
29
31
|
"etc/redis.ru",
|
|
32
|
+
"improved-rack-throttle.gemspec",
|
|
30
33
|
"lib/rack/throttle.rb",
|
|
31
34
|
"lib/rack/throttle/daily.rb",
|
|
32
35
|
"lib/rack/throttle/hourly.rb",
|
|
33
36
|
"lib/rack/throttle/interval.rb",
|
|
34
37
|
"lib/rack/throttle/limiter.rb",
|
|
35
38
|
"lib/rack/throttle/matcher.rb",
|
|
36
|
-
"lib/rack/throttle/matchers/ip_matcher.rb",
|
|
37
39
|
"lib/rack/throttle/matchers/method_matcher.rb",
|
|
38
40
|
"lib/rack/throttle/matchers/url_matcher.rb",
|
|
41
|
+
"lib/rack/throttle/matchers/user_agent_matcher.rb",
|
|
39
42
|
"lib/rack/throttle/time_window.rb",
|
|
40
43
|
"lib/rack/throttle/version.rb",
|
|
41
44
|
"spec/daily_spec.rb",
|
|
@@ -44,7 +47,8 @@ Gem::Specification.new do |s|
|
|
|
44
47
|
"spec/limiter_spec.rb",
|
|
45
48
|
"spec/method_matcher_spec.rb",
|
|
46
49
|
"spec/spec_helper.rb",
|
|
47
|
-
"spec/url_matcher_spec.rb"
|
|
50
|
+
"spec/url_matcher_spec.rb",
|
|
51
|
+
"spec/user_agent_matcher_spec.rb"
|
|
48
52
|
]
|
|
49
53
|
s.homepage = "http://github.com/bensomers/improved-rack-throttle"
|
|
50
54
|
s.licenses = ["Public Domain"]
|
data/lib/rack/throttle.rb
CHANGED
|
@@ -11,5 +11,6 @@ module Rack
|
|
|
11
11
|
autoload :Matcher, 'rack/throttle/matcher'
|
|
12
12
|
autoload :UrlMatcher, 'rack/throttle/matchers/url_matcher'
|
|
13
13
|
autoload :MethodMatcher, 'rack/throttle/matchers/method_matcher'
|
|
14
|
+
autoload :UserAgentMatcher, 'rack/throttle/matchers/user_agent_matcher'
|
|
14
15
|
end
|
|
15
16
|
end
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
module Rack; module Throttle
|
|
2
2
|
###
|
|
3
3
|
# IpMatchers take RegExp objects and compare the request ip against them
|
|
4
|
-
class
|
|
4
|
+
class UserAgentMatcher < Matcher
|
|
5
5
|
def match?(request)
|
|
6
|
-
!!(@rule =~ request.
|
|
6
|
+
!!(@rule =~ request.user_agent)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def identifier
|
|
10
|
-
"
|
|
10
|
+
"ua-" + @rule.inspect
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
|
data/spec/url_matcher_spec.rb
CHANGED
|
@@ -22,7 +22,7 @@ describe Rack::Throttle::UrlMatcher do
|
|
|
22
22
|
|
|
23
23
|
it "should append the rule to the cache key" do
|
|
24
24
|
get "/foo"
|
|
25
|
-
app.send(:cache_key, last_request).should == "127.0.0.1:url
|
|
25
|
+
app.send(:cache_key, last_request).should == "127.0.0.1:url-/foo/"
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Rack::Throttle::UserAgentMatcher do
|
|
4
|
+
include Rack::Test::Methods
|
|
5
|
+
|
|
6
|
+
def app
|
|
7
|
+
@target_app ||= example_target_app
|
|
8
|
+
@app ||= Rack::Throttle::Limiter.new(@target_app, :rules => {:user_agent => /google/i})
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should not bother checking if the path doesn't match the rule" do
|
|
12
|
+
app.should_not_receive(:allowed?)
|
|
13
|
+
get "/foo"
|
|
14
|
+
last_response.body.should show_allowed_response
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should check if the path matches the rule" do
|
|
18
|
+
app.should_receive(:allowed?).and_return(false)
|
|
19
|
+
header 'User-Agent', 'blahdeblah GoogleBot owns your soul'
|
|
20
|
+
get "/foo"
|
|
21
|
+
last_response.body.should show_throttled_response
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should append the rule to the cache key" do
|
|
25
|
+
get "/foo"
|
|
26
|
+
app.send(:cache_key, last_request).should == "127.0.0.1:ua-/google/i"
|
|
27
|
+
end
|
|
28
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: improved-rack-throttle
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -15,7 +15,7 @@ date: 2012-10-03 00:00:00.000000000 Z
|
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: rack
|
|
18
|
-
requirement: &
|
|
18
|
+
requirement: &70147455830820 !ruby/object:Gem::Requirement
|
|
19
19
|
none: false
|
|
20
20
|
requirements:
|
|
21
21
|
- - ~>
|
|
@@ -23,10 +23,10 @@ dependencies:
|
|
|
23
23
|
version: 1.0.0
|
|
24
24
|
type: :runtime
|
|
25
25
|
prerelease: false
|
|
26
|
-
version_requirements: *
|
|
26
|
+
version_requirements: *70147455830820
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: timecop
|
|
29
|
-
requirement: &
|
|
29
|
+
requirement: &70147455830340 !ruby/object:Gem::Requirement
|
|
30
30
|
none: false
|
|
31
31
|
requirements:
|
|
32
32
|
- - ~>
|
|
@@ -34,10 +34,10 @@ dependencies:
|
|
|
34
34
|
version: 0.5.2
|
|
35
35
|
type: :development
|
|
36
36
|
prerelease: false
|
|
37
|
-
version_requirements: *
|
|
37
|
+
version_requirements: *70147455830340
|
|
38
38
|
- !ruby/object:Gem::Dependency
|
|
39
39
|
name: rack-test
|
|
40
|
-
requirement: &
|
|
40
|
+
requirement: &70147455829840 !ruby/object:Gem::Requirement
|
|
41
41
|
none: false
|
|
42
42
|
requirements:
|
|
43
43
|
- - ~>
|
|
@@ -45,10 +45,10 @@ dependencies:
|
|
|
45
45
|
version: 0.6.2
|
|
46
46
|
type: :development
|
|
47
47
|
prerelease: false
|
|
48
|
-
version_requirements: *
|
|
48
|
+
version_requirements: *70147455829840
|
|
49
49
|
- !ruby/object:Gem::Dependency
|
|
50
50
|
name: rspec
|
|
51
|
-
requirement: &
|
|
51
|
+
requirement: &70147455829140 !ruby/object:Gem::Requirement
|
|
52
52
|
none: false
|
|
53
53
|
requirements:
|
|
54
54
|
- - ~>
|
|
@@ -56,10 +56,10 @@ dependencies:
|
|
|
56
56
|
version: 2.11.0
|
|
57
57
|
type: :development
|
|
58
58
|
prerelease: false
|
|
59
|
-
version_requirements: *
|
|
59
|
+
version_requirements: *70147455829140
|
|
60
60
|
- !ruby/object:Gem::Dependency
|
|
61
61
|
name: yard
|
|
62
|
-
requirement: &
|
|
62
|
+
requirement: &70147455828360 !ruby/object:Gem::Requirement
|
|
63
63
|
none: false
|
|
64
64
|
requirements:
|
|
65
65
|
- - ! '>='
|
|
@@ -67,10 +67,10 @@ dependencies:
|
|
|
67
67
|
version: 0.5.5
|
|
68
68
|
type: :development
|
|
69
69
|
prerelease: false
|
|
70
|
-
version_requirements: *
|
|
70
|
+
version_requirements: *70147455828360
|
|
71
71
|
- !ruby/object:Gem::Dependency
|
|
72
72
|
name: rake
|
|
73
|
-
requirement: &
|
|
73
|
+
requirement: &70147455844160 !ruby/object:Gem::Requirement
|
|
74
74
|
none: false
|
|
75
75
|
requirements:
|
|
76
76
|
- - ! '>='
|
|
@@ -78,10 +78,10 @@ dependencies:
|
|
|
78
78
|
version: '0'
|
|
79
79
|
type: :development
|
|
80
80
|
prerelease: false
|
|
81
|
-
version_requirements: *
|
|
81
|
+
version_requirements: *70147455844160
|
|
82
82
|
- !ruby/object:Gem::Dependency
|
|
83
83
|
name: jeweler
|
|
84
|
-
requirement: &
|
|
84
|
+
requirement: &70147455843680 !ruby/object:Gem::Requirement
|
|
85
85
|
none: false
|
|
86
86
|
requirements:
|
|
87
87
|
- - ! '>='
|
|
@@ -89,7 +89,7 @@ dependencies:
|
|
|
89
89
|
version: '0'
|
|
90
90
|
type: :development
|
|
91
91
|
prerelease: false
|
|
92
|
-
version_requirements: *
|
|
92
|
+
version_requirements: *70147455843680
|
|
93
93
|
description: Rack middleware for rate-limiting incoming HTTP requests.
|
|
94
94
|
email: somers.ben@gmail.com
|
|
95
95
|
executables: []
|
|
@@ -117,9 +117,9 @@ files:
|
|
|
117
117
|
- lib/rack/throttle/interval.rb
|
|
118
118
|
- lib/rack/throttle/limiter.rb
|
|
119
119
|
- lib/rack/throttle/matcher.rb
|
|
120
|
-
- lib/rack/throttle/matchers/ip_matcher.rb
|
|
121
120
|
- lib/rack/throttle/matchers/method_matcher.rb
|
|
122
121
|
- lib/rack/throttle/matchers/url_matcher.rb
|
|
122
|
+
- lib/rack/throttle/matchers/user_agent_matcher.rb
|
|
123
123
|
- lib/rack/throttle/time_window.rb
|
|
124
124
|
- lib/rack/throttle/version.rb
|
|
125
125
|
- spec/daily_spec.rb
|
|
@@ -129,6 +129,7 @@ files:
|
|
|
129
129
|
- spec/method_matcher_spec.rb
|
|
130
130
|
- spec/spec_helper.rb
|
|
131
131
|
- spec/url_matcher_spec.rb
|
|
132
|
+
- spec/user_agent_matcher_spec.rb
|
|
132
133
|
homepage: http://github.com/bensomers/improved-rack-throttle
|
|
133
134
|
licenses:
|
|
134
135
|
- Public Domain
|
|
@@ -144,7 +145,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
144
145
|
version: '0'
|
|
145
146
|
segments:
|
|
146
147
|
- 0
|
|
147
|
-
hash: -
|
|
148
|
+
hash: -1924272463384256508
|
|
148
149
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
150
|
none: false
|
|
150
151
|
requirements:
|