rack-bouncer 1.2.1 → 1.3.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/.gitignore +1 -0
- data/README.md +9 -4
- data/lib/rack-bouncer.rb +2 -0
- data/lib/rack/bouncer.rb +56 -28
- data/rack-bouncer.gemspec +1 -1
- data/test/lib/rack/bouncer_test.rb +90 -2
- metadata +6 -5
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -4,13 +4,14 @@ A Rack middleware that expels undesirable browsers out of your website. This pro
|
|
4
4
|
|
5
5
|
| _Browser_ | _Undesirable Versions_ |
|
6
6
|
|-------------------|------------------------|
|
7
|
-
| Internet Explorer | < 8
|
7
|
+
| Internet Explorer | < 8.0 |
|
8
|
+
| Firefox | < 4.0 |
|
8
9
|
| AOL | All |
|
9
10
|
|
10
11
|
## usage
|
11
12
|
|
12
13
|
gem install rack-bouncer
|
13
|
-
require "rack
|
14
|
+
require "rack-bouncer"
|
14
15
|
|
15
16
|
The default redirects users to [Browse Happy](http://browsehappy.com/):
|
16
17
|
|
@@ -24,11 +25,15 @@ You can redirect users to a URL as well:
|
|
24
25
|
|
25
26
|
use Rack::Bouncer, :redirect => "http://slashdot.org"
|
26
27
|
|
27
|
-
You can
|
28
|
+
You can specify a minimum version of IE like so:
|
28
29
|
|
29
30
|
use Rack::Bouncer, :redirect => "http://slashdot.org", :minimum_ie => 6.0
|
30
31
|
|
31
|
-
You can
|
32
|
+
You can specify a minimum version of Firefox like so:
|
33
|
+
|
34
|
+
use Rack::Bouncer, :redirect => "http://slashdot.org", :minimum_firefox => 3.6
|
35
|
+
|
36
|
+
You can specify a set of safe paths:
|
32
37
|
|
33
38
|
use Rack::Bouncer, :safe_paths => ["/asset", "/images", "/stylesheets", "/javascripts", "/feedback"]
|
34
39
|
|
data/lib/rack-bouncer.rb
ADDED
data/lib/rack/bouncer.rb
CHANGED
@@ -2,12 +2,13 @@
|
|
2
2
|
|
3
3
|
module Rack
|
4
4
|
class Bouncer
|
5
|
-
VERSION = "1.
|
5
|
+
VERSION = "1.3.0"
|
6
6
|
|
7
7
|
DEFAULT_OPTIONS = {
|
8
|
-
:safe_paths
|
9
|
-
:redirect
|
10
|
-
:minimum_ie
|
8
|
+
:safe_paths => ["/asset", "/images", "/stylesheets", "/javascripts", "/feedback"],
|
9
|
+
:redirect => "http://browsehappy.com/",
|
10
|
+
:minimum_ie => 8.0,
|
11
|
+
:minimum_firefox => 4.0
|
11
12
|
}
|
12
13
|
|
13
14
|
def initialize(app, options = {})
|
@@ -16,49 +17,76 @@ module Rack
|
|
16
17
|
end
|
17
18
|
|
18
19
|
def call(env)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
return @app.call(env) if safe_path?(env)
|
21
|
+
return @app.call(env) if user_agent_blank?(env)
|
22
|
+
|
23
|
+
user_agent = env["HTTP_USER_AGENT"]
|
24
|
+
|
25
|
+
if undesirable_ie_present?(user_agent) ||
|
26
|
+
undesirable_aol_present?(user_agent) ||
|
27
|
+
undesirable_firefox_present?(user_agent)
|
28
|
+
return kick_it
|
23
29
|
end
|
30
|
+
|
31
|
+
@app.call(env)
|
24
32
|
end
|
25
33
|
|
26
34
|
private
|
27
35
|
|
28
|
-
def safe_path(env)
|
29
|
-
|
30
|
-
|
36
|
+
def safe_path?(env)
|
37
|
+
return true if @options[:redirect] == env["PATH_INFO"]
|
38
|
+
return env["PATH_INFO"] =~ Regexp.new("^(#{@options[:safe_paths].join("|")})")
|
39
|
+
end
|
31
40
|
|
32
|
-
|
41
|
+
def user_agent_blank?(env)
|
42
|
+
env["HTTP_USER_AGENT"].nil? || env["HTTP_USER_AGENT"].empty?
|
33
43
|
end
|
34
44
|
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
|
45
|
+
def kick_it
|
46
|
+
[302, {"Location" => @options[:redirect], "Content-Type" => "text/html"}, "Browser not supported"]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Internet Explorer
|
50
|
+
###############################################################################################
|
51
|
+
|
52
|
+
def undesirable_ie_present?(user_agent)
|
53
|
+
is_ie?(user_agent) && ie_version(user_agent) < @options[:minimum_ie]
|
39
54
|
end
|
40
55
|
|
41
|
-
def is_ie?(
|
56
|
+
def is_ie?(user_agent)
|
42
57
|
# We need at least one digit to be able to get the version, hence the \d
|
43
|
-
|
58
|
+
user_agent.match(/MSIE \d/) ? true : false
|
44
59
|
end
|
45
60
|
|
46
|
-
def
|
47
|
-
|
48
|
-
is_aol?(env["HTTP_USER_AGENT"])
|
49
|
-
end
|
61
|
+
def ie_version(user_agent)
|
62
|
+
user_agent.match(/MSIE (\S+)/)[1].to_f
|
50
63
|
end
|
51
64
|
|
52
|
-
|
53
|
-
|
65
|
+
# AOL
|
66
|
+
###############################################################################################
|
67
|
+
|
68
|
+
def undesirable_aol_present?(user_agent)
|
69
|
+
is_aol?(user_agent)
|
54
70
|
end
|
55
71
|
|
56
|
-
def
|
57
|
-
|
72
|
+
def is_aol?(user_agent)
|
73
|
+
user_agent.match(/AOL \d/) ? true : false
|
58
74
|
end
|
59
75
|
|
60
|
-
|
61
|
-
|
76
|
+
# Firefox
|
77
|
+
###############################################################################################
|
78
|
+
|
79
|
+
def undesirable_firefox_present?(user_agent)
|
80
|
+
is_firefox?(user_agent) && firefox_version(user_agent) < @options[:minimum_firefox]
|
81
|
+
end
|
82
|
+
|
83
|
+
def is_firefox?(user_agent)
|
84
|
+
# We need at least one digit to be able to get the version, hence the \d
|
85
|
+
user_agent.match(/Firefox\/\d/) ? true : false
|
86
|
+
end
|
87
|
+
|
88
|
+
def firefox_version(user_agent)
|
89
|
+
user_agent.match(/Firefox\/(\S+)/)[1].to_f
|
62
90
|
end
|
63
91
|
end
|
64
92
|
end
|
data/rack-bouncer.gemspec
CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |s|
|
|
5
5
|
s.name = "rack-bouncer"
|
6
6
|
s.version = Rack::Bouncer::VERSION
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
|
-
s.authors = ["
|
8
|
+
s.authors = ["Julio Cesar Ody", "Jerod Santo", "Will Jessop", "Ryan Sobol"]
|
9
9
|
s.email = "contact@ryansobol.com"
|
10
10
|
s.homepage = "https://github.com/ryansobol/rack-bouncer"
|
11
11
|
s.summary = "A Rack middleware that expels undesirable browsers out of your website."
|
@@ -3,7 +3,7 @@ require "rubygems"
|
|
3
3
|
require "minitest/autorun"
|
4
4
|
require "rack/mock"
|
5
5
|
|
6
|
-
require "rack
|
6
|
+
require "rack-bouncer"
|
7
7
|
|
8
8
|
class TestApp
|
9
9
|
def call(env)
|
@@ -18,7 +18,7 @@ end
|
|
18
18
|
class Rack::Bouncer::Test < MiniTest::Unit::TestCase
|
19
19
|
|
20
20
|
def test_version
|
21
|
-
assert_equal "1.
|
21
|
+
assert_equal "1.3.0", Rack::Bouncer::VERSION
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_default_safe_paths
|
@@ -34,6 +34,10 @@ class Rack::Bouncer::Test < MiniTest::Unit::TestCase
|
|
34
34
|
assert_equal 8.0, Rack::Bouncer::DEFAULT_OPTIONS[:minimum_ie]
|
35
35
|
end
|
36
36
|
|
37
|
+
def test_default_minimum_firefox
|
38
|
+
assert_equal 4.0, Rack::Bouncer::DEFAULT_OPTIONS[:minimum_firefox]
|
39
|
+
end
|
40
|
+
|
37
41
|
def test_allows_if_no_user_agent_specified
|
38
42
|
request = create_request
|
39
43
|
response = request.get("/")
|
@@ -175,6 +179,48 @@ class Rack::Bouncer::Test < MiniTest::Unit::TestCase
|
|
175
179
|
# Firefox
|
176
180
|
#################################################################################################
|
177
181
|
|
182
|
+
def test_expels_firefox_3_6
|
183
|
+
request = create_request
|
184
|
+
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0(Windows; U; Windows NT 5.2; rv:1.9.2) Gecko/20100101 Firefox/3.6" })
|
185
|
+
assert_equal 302, response.status
|
186
|
+
assert_equal response.location, "http://browsehappy.com/"
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_allows_firefox_3_6_when_minimum
|
190
|
+
request = create_request(:minimum_firefox => 3.6)
|
191
|
+
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0(Windows; U; Windows NT 5.2; rv:1.9.2) Gecko/20100101 Firefox/3.6" })
|
192
|
+
assert_equal 200, response.status
|
193
|
+
assert_equal "Hi Internets!", response.body
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_expels_firefox_3_6_2
|
197
|
+
request = create_request
|
198
|
+
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2" })
|
199
|
+
assert_equal 302, response.status
|
200
|
+
assert_equal response.location, "http://browsehappy.com/"
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_expels_firefox_3_6_b5
|
204
|
+
request = create_request
|
205
|
+
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2b5) Gecko/20091204 Firefox/3.6b5" })
|
206
|
+
assert_equal 302, response.status
|
207
|
+
assert_equal response.location, "http://browsehappy.com/"
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_expels_firefox_3_6_22
|
211
|
+
request = create_request
|
212
|
+
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.4; en-US; rv:1.9.2.22) Gecko/20110902 Firefox/3.6.22" })
|
213
|
+
assert_equal 302, response.status
|
214
|
+
assert_equal response.location, "http://browsehappy.com/"
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_expels_firefox_3_8
|
218
|
+
request = create_request
|
219
|
+
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.2) Gecko/20121223 Ubuntu/9.25 (jaunty) Firefox/3.8" })
|
220
|
+
assert_equal 302, response.status
|
221
|
+
assert_equal response.location, "http://browsehappy.com/"
|
222
|
+
end
|
223
|
+
|
178
224
|
def test_allows_firefox_4
|
179
225
|
request = create_request
|
180
226
|
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0" })
|
@@ -182,6 +228,48 @@ class Rack::Bouncer::Test < MiniTest::Unit::TestCase
|
|
182
228
|
assert_equal "Hi Internets!", response.body
|
183
229
|
end
|
184
230
|
|
231
|
+
def test_allows_firefox_4_0_1
|
232
|
+
request = create_request
|
233
|
+
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20110518 Firefox/4.0.1" })
|
234
|
+
assert_equal 200, response.status
|
235
|
+
assert_equal "Hi Internets!", response.body
|
236
|
+
end
|
237
|
+
|
238
|
+
def test_allows_firefox_5
|
239
|
+
request = create_request
|
240
|
+
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 5.1; U; rv:5.0) Gecko/20100101 Firefox/5.0" })
|
241
|
+
assert_equal 200, response.status
|
242
|
+
assert_equal "Hi Internets!", response.body
|
243
|
+
end
|
244
|
+
|
245
|
+
def test_allows_firefox_6
|
246
|
+
request = create_request
|
247
|
+
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 6.1; rv:6.0) Gecko/20110814 Firefox/6.0" })
|
248
|
+
assert_equal 200, response.status
|
249
|
+
assert_equal "Hi Internets!", response.body
|
250
|
+
end
|
251
|
+
|
252
|
+
def test_allows_firefox_9
|
253
|
+
request = create_request
|
254
|
+
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0" })
|
255
|
+
assert_equal 200, response.status
|
256
|
+
assert_equal "Hi Internets!", response.body
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_allows_firefox_9_0_a2
|
260
|
+
request = create_request
|
261
|
+
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0a2) Gecko/20111101 Firefox/9.0a2" })
|
262
|
+
assert_equal 200, response.status
|
263
|
+
assert_equal "Hi Internets!", response.body
|
264
|
+
end
|
265
|
+
|
266
|
+
def test_allows_firefox_10_0_a4
|
267
|
+
request = create_request
|
268
|
+
response = request.get("/", {"HTTP_USER_AGENT" => "Mozilla/6.0 (Macintosh; I; Intel Mac OS X 11_7_9; de-LI; rv:1.9b4) Gecko/2012010317 Firefox/10.0a4" })
|
269
|
+
assert_equal 200, response.status
|
270
|
+
assert_equal "Hi Internets!", response.body
|
271
|
+
end
|
272
|
+
|
185
273
|
# Safari
|
186
274
|
#################################################################################################
|
187
275
|
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-bouncer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 1.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 1.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
|
-
- Jerod Santo
|
14
13
|
- Julio Cesar Ody
|
14
|
+
- Jerod Santo
|
15
15
|
- Will Jessop
|
16
16
|
- Ryan Sobol
|
17
17
|
autorequire:
|
@@ -68,6 +68,7 @@ files:
|
|
68
68
|
- Gemfile.lock
|
69
69
|
- README.md
|
70
70
|
- Rakefile
|
71
|
+
- lib/rack-bouncer.rb
|
71
72
|
- lib/rack/bouncer.rb
|
72
73
|
- rack-bouncer.gemspec
|
73
74
|
- test/lib/rack/bouncer_test.rb
|