mobile

Selective Autoredirection

Tuesday, 13th July 2010, sheilaellen (http://blogs.bluegumtree.co.uk/vista/)

Imagine you have two versions of the same site and one of them is optimised for mobile devices.  Aside from the root folder, the URL pattern is identical for both versions so to map between the versions you simply add or remove “/mobile”:

  • http://www.mysite.com
  • http://www.mysite.com/mobile

Most pages on each version have a matching partner on the other but, importantly, this isn’t the case for all pages.

Although you have a version optimised for mobile devices, you can’t be sure that they’ll always land on it when they visit your site so you want to:

  • detect mobile devices when they land on your site
  • automatically redirect them to the mobile version if they’ve landed on the default version but only if a mobile version of that page actually exists.

Ideally, in order to avoid swapping a perfectly good page for a 404 error you want to make the check before initiating the redirection.  You don’t have access to the Apache config files but you can use .htaccess files.

I’ve been puzzling over this conundrum for a while, trying to find a solution that has as little impact on the rest of the system, aside from doing what it’s very specifically required to do, and doesn’t open up a cross-site scripting vulnerability.  Last night, I think I cracked it and as I found very little on this myself when scouring the web, I’ll share it here.  Hopefully if you spot any problems with it or – even better – ways to improve upon it, you’ll let me know.

This code goes in an .htaccess file in the root of http://www.mysite.com/. Further up the file, a check has already been made to determine whether or not the user agent is a mobile device and if it is, the value of an environment variable called $IS_MOBILE has been set to “true”. The ErrorDocument for 404 errors has also been set.


# Activate the RewriteEngine
RewriteEngine on

# Set the base to root
RewriteBase /

# Check whether it's a mobile device
RewriteCond %{ENV:IS_MOBILE} ^true$ [NC]

# Check that the URL isn't already going to the mobile version
RewriteCond %{REQUEST_URI} !^/mobile/ [NC]

# Capture the part of the URL that follows after the base, prepend it with "/mobile/" and
# assign the new string to an environment variable called $MOBILE_TARGET_URL;
# Also assign the un-prepended captured value to an environment variable called
# $MOBILE_ORIGINAL_URL; Chain this rule to the next one.
RewriteRule ^(.*)$ - [E=MOBILE_TARGET_URL:/mobile/$1,E=MOBILE_ORIGINAL_URL:$1,C]

# Concatenate the $DOCUMENT_ROOT and $MOBILE_TARGET_URL together
# and check whether that maps to either a directory or a file
RewriteCond %{DOCUMENT_ROOT}%{ENV:MOBILE_TARGET_URL} -d [OR]
RewriteCond %{DOCUMENT_ROOT}%{ENV:MOBILE_TARGET_URL} -f

# If it does, redirect to the user to the mobile version
RewriteRule ^.*$ %{ENV:MOBILE_TARGET_URL} [R,L]