rack-bouncer 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|