browsernizer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/README.md +53 -0
- data/Rakefile +8 -0
- data/browsernizer.gemspec +25 -0
- data/lib/browsernizer.rb +13 -0
- data/lib/browsernizer/browser.rb +6 -0
- data/lib/browsernizer/browser_version.rb +24 -0
- data/lib/browsernizer/config.rb +26 -0
- data/lib/browsernizer/router.rb +46 -0
- data/lib/browsernizer/version.rb +3 -0
- data/lib/generators/browsernizer/install_generator.rb +12 -0
- data/lib/generators/templates/browsernizer.rb +7 -0
- data/spec/browsernizer/browser_version_spec.rb +31 -0
- data/spec/browsernizer/config_spec.rb +29 -0
- data/spec/browsernizer/router_spec.rb +78 -0
- data/spec/spec_helper.rb +2 -0
- metadata +100 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# Browsernizer
|
2
|
+
|
3
|
+
Want friendly "please upgrade your browser" page? This gem is for you.
|
4
|
+
|
5
|
+
You can redirect your visitors to any page you like (static or dynamic).
|
6
|
+
Just specify `config.location` option in initializer file.
|
7
|
+
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add following line to your `Gemfile`:
|
12
|
+
|
13
|
+
gem 'browsernizer'
|
14
|
+
|
15
|
+
Hook it up:
|
16
|
+
|
17
|
+
rails generate browsernizer:install
|
18
|
+
|
19
|
+
Configure browser support in `config/initializers/browsernizer.rb` file.
|
20
|
+
|
21
|
+
All browsers that are not listed in initializer file will be considered to be **supported**.
|
22
|
+
|
23
|
+
|
24
|
+
## Browsers
|
25
|
+
|
26
|
+
You should specify browser name as a string. Here are the available options:
|
27
|
+
|
28
|
+
* Chrome
|
29
|
+
* Firefox
|
30
|
+
* Safari
|
31
|
+
* Opera
|
32
|
+
* Internet Explorer
|
33
|
+
|
34
|
+
And some less popular:
|
35
|
+
|
36
|
+
* Android
|
37
|
+
* webOS
|
38
|
+
* BlackBerry
|
39
|
+
* Symbian
|
40
|
+
* Camino
|
41
|
+
* Iceweasel
|
42
|
+
* Seamonkey
|
43
|
+
|
44
|
+
Browser detection is done using [useragent gem](https://github.com/josh/useragent).
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
## Credits and License
|
49
|
+
|
50
|
+
Developed by Milovan Zogovic.
|
51
|
+
|
52
|
+
I don't believe in licenses and other woody crap.
|
53
|
+
Do whatever you want with this :)
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "browsernizer/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "browsernizer"
|
7
|
+
s.version = Browsernizer::VERSION
|
8
|
+
s.authors = ["Milovan Zogovic"]
|
9
|
+
s.email = ["milovan.zogovic@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Want friendly "please upgrade your browser" page? This gem is for you.}
|
12
|
+
s.description = %q{Rack middleware for redirecting unsupported user agents to "please upgrade" page}
|
13
|
+
|
14
|
+
s.rubyforge_project = "browsernizer"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rake"
|
22
|
+
s.add_development_dependency "rspec"
|
23
|
+
|
24
|
+
s.add_runtime_dependency 'useragent', "~> 0.4.6"
|
25
|
+
end
|
data/lib/browsernizer.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#TODO: remove when useragent gem is fixed
|
2
|
+
require 'rubygems'
|
3
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
4
|
+
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
|
5
|
+
|
6
|
+
|
7
|
+
require "browsernizer/browser"
|
8
|
+
require "browsernizer/browser_version"
|
9
|
+
require "browsernizer/config"
|
10
|
+
require "browsernizer/router"
|
11
|
+
require "browsernizer/version"
|
12
|
+
|
13
|
+
require 'useragent'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Browsernizer
|
2
|
+
class BrowserVersion
|
3
|
+
include ::Comparable
|
4
|
+
|
5
|
+
attr_accessor :to_a
|
6
|
+
|
7
|
+
def initialize(version)
|
8
|
+
@version = version
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_a
|
12
|
+
@version.split(".").map{ |s| s.to_i }
|
13
|
+
end
|
14
|
+
|
15
|
+
def <=>(other)
|
16
|
+
([0]*6).zip(to_a, other.to_a).each do |dump, a, b|
|
17
|
+
r = (a||0) <=> (b||0)
|
18
|
+
return r unless r.zero?
|
19
|
+
end
|
20
|
+
0
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Browsernizer
|
2
|
+
class Config
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@supported = []
|
6
|
+
@location = "/unsupported-browser.html"
|
7
|
+
end
|
8
|
+
|
9
|
+
def supported(browser, version)
|
10
|
+
@supported << Browser.new(browser.to_s, version.to_s)
|
11
|
+
end
|
12
|
+
|
13
|
+
def location(path)
|
14
|
+
@location = path
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_supported
|
18
|
+
@supported
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_location
|
22
|
+
@location
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Browsernizer
|
2
|
+
|
3
|
+
class Router
|
4
|
+
def initialize(app, &block)
|
5
|
+
@app = app
|
6
|
+
@config = Config.new
|
7
|
+
yield(@config)
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
@env = env
|
12
|
+
|
13
|
+
if html_request? && !on_redirection_path? && unsupported?
|
14
|
+
[307, {"Content-Type" => "text/plain", "Location" => @config.get_location}, []]
|
15
|
+
elsif html_request? && on_redirection_path? && !unsupported?
|
16
|
+
[303, {"Content-Type" => "text/plain", "Location" => "/"}, []]
|
17
|
+
else
|
18
|
+
@app.call(env)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def html_request?
|
24
|
+
@env["HTTP_ACCEPT"] && @env["HTTP_ACCEPT"].include?("text/html")
|
25
|
+
end
|
26
|
+
|
27
|
+
def on_redirection_path?
|
28
|
+
@env["PATH_INFO"] && @env["PATH_INFO"] == @config.get_location
|
29
|
+
end
|
30
|
+
|
31
|
+
# supported by default
|
32
|
+
def unsupported?
|
33
|
+
agent = ::UserAgent.parse @env["HTTP_USER_AGENT"]
|
34
|
+
@config.get_supported.detect do |supported_browser|
|
35
|
+
if agent.browser.to_s.downcase == supported_browser.browser.to_s.downcase
|
36
|
+
a = BrowserVersion.new agent.version.to_s
|
37
|
+
b = BrowserVersion.new supported_browser.version.to_s
|
38
|
+
a < b
|
39
|
+
end
|
40
|
+
# TODO: when useragent is fixed you can use just this line instead the above
|
41
|
+
# agent < supported_browser
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Browsernizer
|
2
|
+
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path("../../templates", __FILE__)
|
5
|
+
|
6
|
+
desc "Copies initializer script"
|
7
|
+
def copy_initializer
|
8
|
+
copy_file "browsernizer.rb", "config/initializers/browsernizer.rb"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Browsernizer::BrowserVersion do
|
4
|
+
|
5
|
+
describe "Comparable" do
|
6
|
+
|
7
|
+
it "is greater" do
|
8
|
+
version("2").should > version("1")
|
9
|
+
version("1.1").should > version("1")
|
10
|
+
version("1.1").should > version("1.0")
|
11
|
+
version("2").should > version("1.9")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "is equal" do
|
15
|
+
version("1").should == version("1")
|
16
|
+
version("1").should == version("1.0")
|
17
|
+
version("1.0").should == version("1")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "handles strings" do
|
21
|
+
version("1.0").should == version("1.0.alpha")
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def version(str)
|
28
|
+
Browsernizer::BrowserVersion.new(str)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Browsernizer::Config do
|
4
|
+
|
5
|
+
subject { config = Browsernizer::Config.new }
|
6
|
+
|
7
|
+
describe "new" do
|
8
|
+
it "sets the defaults" do
|
9
|
+
subject.get_supported.should == []
|
10
|
+
subject.get_location.should == "/unsupported-browser.html"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "supported(name, version)" do
|
15
|
+
it "defines new supported browser" do
|
16
|
+
subject.supported "Chrome", "16.0"
|
17
|
+
subject.supported "Firefox", "10.0"
|
18
|
+
subject.get_supported.should have(2).items
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "location(path)" do
|
23
|
+
it "sets the redirection path for unsupported browsers" do
|
24
|
+
subject.location "foo.html"
|
25
|
+
subject.get_location.should == "foo.html"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Browsernizer::Router do
|
4
|
+
|
5
|
+
let(:app) { mock() }
|
6
|
+
|
7
|
+
subject do
|
8
|
+
Browsernizer::Router.new(app) do |config|
|
9
|
+
config.supported "Firefox", "4"
|
10
|
+
config.supported "Chrome", "7.1"
|
11
|
+
config.location "/browser.html"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:default_env) do
|
16
|
+
{
|
17
|
+
"HTTP_USER_AGENT" => chrome_agent("7.1.1"),
|
18
|
+
"HTTP_ACCEPT" => "text/html",
|
19
|
+
"PATH_INFO" => "/index"
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
context "All Good" do
|
24
|
+
it "propagates request" do
|
25
|
+
app.should_receive(:call).with(default_env)
|
26
|
+
subject.call(default_env)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "Unsupported Browser" do
|
31
|
+
before do
|
32
|
+
@env = default_env.merge({
|
33
|
+
"HTTP_USER_AGENT" => chrome_agent("7")
|
34
|
+
})
|
35
|
+
end
|
36
|
+
|
37
|
+
it "prevents propagation" do
|
38
|
+
app.should_not_receive(:call)
|
39
|
+
subject.call(@env)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "redirects to proper location" do
|
43
|
+
response = subject.call(@env)
|
44
|
+
response[0].should == 307
|
45
|
+
response[1]["Location"].should == "/browser.html"
|
46
|
+
end
|
47
|
+
|
48
|
+
context "Non-html request" do
|
49
|
+
before do
|
50
|
+
@env = @env.merge({
|
51
|
+
"HTTP_ACCEPT" => "text/css"
|
52
|
+
})
|
53
|
+
end
|
54
|
+
it "propagates request" do
|
55
|
+
app.should_receive(:call).with(@env)
|
56
|
+
subject.call(@env)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "Already on /browser.html page" do
|
61
|
+
before do
|
62
|
+
@env = @env.merge({
|
63
|
+
"PATH_INFO" => "/browser.html"
|
64
|
+
})
|
65
|
+
end
|
66
|
+
it "propagates request" do
|
67
|
+
app.should_receive(:call).with(@env)
|
68
|
+
subject.call(@env)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def chrome_agent(version)
|
75
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/#{version} Safari/535.7"
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: browsernizer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Milovan Zogovic
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-06 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &70114897960180 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70114897960180
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &70114897959760 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70114897959760
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: useragent
|
38
|
+
requirement: &70114897959260 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.4.6
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70114897959260
|
47
|
+
description: Rack middleware for redirecting unsupported user agents to "please upgrade"
|
48
|
+
page
|
49
|
+
email:
|
50
|
+
- milovan.zogovic@gmail.com
|
51
|
+
executables: []
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- .gitignore
|
56
|
+
- Gemfile
|
57
|
+
- README.md
|
58
|
+
- Rakefile
|
59
|
+
- browsernizer.gemspec
|
60
|
+
- lib/browsernizer.rb
|
61
|
+
- lib/browsernizer/browser.rb
|
62
|
+
- lib/browsernizer/browser_version.rb
|
63
|
+
- lib/browsernizer/config.rb
|
64
|
+
- lib/browsernizer/router.rb
|
65
|
+
- lib/browsernizer/version.rb
|
66
|
+
- lib/generators/browsernizer/install_generator.rb
|
67
|
+
- lib/generators/templates/browsernizer.rb
|
68
|
+
- spec/browsernizer/browser_version_spec.rb
|
69
|
+
- spec/browsernizer/config_spec.rb
|
70
|
+
- spec/browsernizer/router_spec.rb
|
71
|
+
- spec/spec_helper.rb
|
72
|
+
homepage: ''
|
73
|
+
licenses: []
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project: browsernizer
|
92
|
+
rubygems_version: 1.8.15
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: Want friendly "please upgrade your browser" page? This gem is for you.
|
96
|
+
test_files:
|
97
|
+
- spec/browsernizer/browser_version_spec.rb
|
98
|
+
- spec/browsernizer/config_spec.rb
|
99
|
+
- spec/browsernizer/router_spec.rb
|
100
|
+
- spec/spec_helper.rb
|