Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Pulled in joren's redirect_to option. Added support for redirect maps.

  • Loading branch information...
commit 2124c97b83faf888e49e411e99049ff55ad3001b 1 parent f598230
@talison authored
View
27 README.md
@@ -77,9 +77,30 @@ Configuration/CLDC-1.1 VendorID/102' connects, the value of
This allows you to limit the catchall expression to only the device
list you choose.
- use Rack::MobileDetect, :redirect_to => '/mobile'
-
-This allows you to choose a custom redirect path
+Redirects
+=========
+
+ use Rack::MobileDetect, :redirect_to => '/mobile'
+
+This allows you to choose a custom redirect path any time a mobile
+device is detected.
+
+ use Rack::MobileDetect, :targeted => /BlackBerry|iPhone/,
+ :redirect_map => { 'BlackBerry' => '/m/blackberry', 'iPhone' => '/m/iphone' }
+
+This allows you to map specific redirect URLs to targeted devices. The
+key in the redirect_map should be the value of the matched pattern.
+
+ use Rack::MobileDetect, :targeted => /BlackBerry|iPhone/,
+ :redirect_map => { 'BlackBerry' => '/m/blackberry', 'iPhone' => '/m/iphone' },
+ :redirect_to => '/mobile'
+
+This allows you to map targeted devices to specific URLs. Non-targeted
+mobile devices will redirect to the url specified by redirect_to.
+
+In the example above, BlackBerry's and iPhone's get redirected to
+device-specific URLs. All other mobile devices get redirected to
+'/mobile'.
Utils
View
5 Rakefile
@@ -8,11 +8,12 @@ begin
gem.summary = %Q{Rack middleware for ruby webapps to detect mobile devices.}
gem.description = %Q{Rack::MobileDetect detects mobile devices and adds an
X_MOBILE_DEVICE header to the request if a mobile device is detected. Specific
- devices can be targeted with custom Regexps.}
+ devices can be targeted with custom Regexps and redirect support is available.}
gem.email = "accounts@majortom.fastmail.us"
gem.homepage = "http://github.com/talison/rack-mobile-detect"
- gem.authors = ["Tom Alison", "Michael Wood"]
+ gem.authors = ["Tom Alison"]
gem.add_development_dependency "shoulda", ">= 0"
+ gem.add_development_dependency "rack", ">=0"
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
end
Jeweler::GemcutterTasks.new
View
2  TODO
@@ -1 +1,3 @@
* Allow options to disable UAProf detection, Accept detection
+
+
View
31 lib/rack/mobile_detect.rb
@@ -20,6 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
+require 'rack'
+
module Rack
#
# Full project at http://github.com/talison/rack-mobile-detect
@@ -121,8 +123,11 @@ def initialize(app, options = {})
'240x320|320x320|mobileexplorer|j2me|sgh|portable|sprint|vodafone|' +
'docomo|kddi|softbank|pdxgw|j-phone|astel|minimo|plucker|netfront|' +
'xiino|mot-v|mot-e|portalmmm|sagem|sie-s|sie-m|android|ipod', true)
-
+
+ # A URL that specifies a single redirect-url for any device
@redirect_to = options[:redirect_to]
+ # A mapping of devices to redirect URLs, for targeted devices
+ @redirect_map = options[:redirect_map]
end
# Because the web app may be multithreaded, this method must
@@ -143,15 +148,29 @@ def call(env)
# Fall back on catch-all User-Agent regex
device ||= Regexp.new(@regex_ua_catchall).match(user_agent) != nil
-
- path = Rack::Utils.unescape(env['PATH_INFO'])
-
+
if device
- env[X_HEADER] = device.to_s
- return [301, {'Location' => @redirect_to}, []] if @redirect_to && path !~ /^#{@redirect_to}/
+ device = device.to_s
+
+ env[X_HEADER] = device
+ redirect = check_for_redirect(device)
+
+ if redirect
+ path = Rack::Utils.unescape(env['PATH_INFO'])
+ return [301, {'Location' => redirect}, []] if redirect && path !~ /^#{redirect}/
+ end
end
@app.call(env)
end
+
+ # Checks to see if any redirect options were passed in
+ # and returns the appropriate redirect or nil (if no redirect requested)
+ def check_for_redirect(device)
+ # Find the device-specific redirect in the map, if exists
+ return @redirect_map[device] if @redirect_map && @redirect_map.has_key?(device)
+ # Return global redirect, or nil
+ return @redirect_to
+ end
end
end
View
2  test/helper.rb
@@ -4,7 +4,7 @@
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.dirname(__FILE__))
-require 'rack-mobile-detect'
+require 'rack/mobile-detect'
class Test::Unit::TestCase
end
View
77 test/test_rack-mobile-detect.rb
@@ -121,24 +121,93 @@ class TestRackMobileDetect < Test::Unit::TestCase
assert !env.key?(x_mobile)
end
end
-
- context "An app with a custom redirect" do
+
+ context "An app with a custom redirect" do
setup do
@app = test_app
# Custom redirect
@rack = Rack::MobileDetect.new(@app, :redirect_to => '/mobile')
end
-
+
should "redirect to mobile website" do
env = test_env({ 'HTTP_USER_AGENT' => iphone })
status, headers, body = @rack.call(env)
assert_equal 'iPhone', env[x_mobile]
-
+
assert_equal(301, status)
assert_equal({'Location' => "/mobile"}, headers)
end
end
+ context "An app with a custom redirect map" do
+ setup do
+ @app = test_app
+ redirects = { "myphone" => "/m/myphone", "yourphone" => "/m/yourphone" }
+ # Target fake devices
+ @rack = Rack::MobileDetect.new(@app,
+ :targeted => /myphone|yourphone/,
+ :redirect_map => redirects)
+ end
+
+ should "redirect to the custom url of the targeted devices" do
+ env = test_env({ 'HTTP_USER_AGENT' => 'myphone rocks' })
+ status, headers, body = @rack.call(env)
+ assert_equal 'myphone', env[x_mobile]
+
+ assert_equal(301, status)
+ assert_equal({'Location' => "/m/myphone"}, headers)
+
+
+ env = test_env({ 'HTTP_USER_AGENT' => 'yourphone sucks' })
+ status, headers, body = @rack.call(env)
+ assert_equal 'yourphone', env[x_mobile]
+
+ assert_equal(301, status)
+ assert_equal({'Location' => "/m/yourphone"}, headers)
+
+ end
+
+ should "not redirect a non-targeted device" do
+ env = test_env({ 'HTTP_USER_AGENT' => 'some wap phone' })
+ status, headers, body = @rack.call(env)
+ assert_equal 'true', env[x_mobile]
+
+ assert_not_equal(301, status)
+ end
+ end
+
+ context "An app with a custom redirect map and redirect_to option" do
+ setup do
+ @app = test_app
+ redirects = { "myphone" => "/m/myphone", "yourphone" => "/m/yourphone" }
+ # Target fake devices
+ @rack = Rack::MobileDetect.new(@app,
+ :targeted => /myphone|yourphone/,
+ :redirect_map => redirects,
+ :redirect_to => '/m/genericdevice')
+ end
+
+ should "use the redirect value in the redirect map when targeted" do
+ env = test_env({ 'HTTP_USER_AGENT' => 'myphone rocks' })
+ status, headers, body = @rack.call(env)
+ assert_equal 'myphone', env[x_mobile]
+
+ assert_equal(301, status)
+ assert_equal({'Location' => "/m/myphone"}, headers)
+
+ end
+
+ should "use redirect_to to redirect a device not in the map" do
+ env = test_env({ 'HTTP_USER_AGENT' => 'some wap phone' })
+ status, headers, body = @rack.call(env)
+ assert_equal 'true', env[x_mobile]
+
+ assert_equal(301, status)
+ assert_equal({'Location' => "/m/genericdevice"}, headers)
+ end
+ end
+
+
# Expected x_header
def x_mobile
Rack::MobileDetect::X_HEADER
View
2  util/echo_env.rb 100755 → 100644
@@ -3,7 +3,7 @@
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
-require 'rack-mobile-detect'
+require 'rack/mobile-detect'
use Rack::MobileDetect
Please sign in to comment.
Something went wrong with that request. Please try again.