Forum Moderators: phranque

Message Too Old, No Replies

Mod Rewrite based on mobile device detection/cookie override

         

ocon

1:28 pm on May 15, 2012 (gmt 0)

10+ Year Member Top Contributors Of The Month



I'd like two versions of my homepage served based on mobile device detection or cookie/session overrides. Regardless of which version is served I would always like it accessed at my domain's root: www.example.com

On the index.html version you can set a cookie/session override of mobile=yes, and on the mobile.html version you can set a cookie/session override of mobile=no.

Mod Rewrite has always seemed like a black art to me, so I'm not sure of what I have pieced together and would very much appreciate some feedback on my code:

To keep it simple for right now I'm fine with just detecting a few of the more popular devices as mobile, but I would also appreciate feedback on if I should add/remove some more prominent devices.

RewriteEngine On
RewriteBase /

RewriteCond %{HTTP_USER_AGENT} android|blackberry|iphone|ipod|iemobile|palmos [OR]
RewriteCond %{HTTP_COOKIE} mobile=yes
RewriteCond %{HTTP_COOKIE} !mobile=no
RewriteRule / /mobile.html [L]

lucy24

8:33 pm on May 15, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Mod Rewrite has always seemed like a black art to me

mod_rewrite is a black art. You can seriously injure yourself with a carelessly composed Rewrite. But that doesn't detract from its usefulness.

RewriteCond %{HTTP_COOKIE} mobile=yes
RewriteCond %{HTTP_COOKIE} !mobile=no

This seems redundant, though it may actually be right. You do need to check whether the cookie is present at all. Would the cookie ever have a "yes" value if the UA is other than the listed UAs? For example, something on the home page that says "mobile version"?

In the first line-- the one checking UA-- you'll need an [NC] flag. Or, better, use the normative casing, like "iPhone". That is, why bother to give the option to spoofers who can't be bothered to spell things right? I also recommend wrapping the whole line in parentheses. It isn't technically necessary, since you're not capturing and there are no anchors, but pipes-plus-parentheses tends to be a safer combination.

Conversely, "RewriteBase /" won't do any harm. But it isn't necessary, since it's already the default.

ocon

9:28 pm on May 15, 2012 (gmt 0)

10+ Year Member Top Contributors Of The Month



Thanks for the reply.

On the basic level I want to serve default desktop version to all users except when serving the mobile version to users matching the user agent. No cookies involved.

If a person wants the desktop version, but matches the user agent, they can set the cookie of mobile=no. In this situation, they will not be served the mobile version even though they match the user agent.

If a person wants the mobile version, but do not match the user agent, they can set the cookie of mobile=yes. In this situation, they will be served the mobile version even though they do not match the user agent.

So my code now looks like this:

RewriteEngine On
RewriteBase /

RewriteCond %{HTTP_USER_AGENT} (android|blackberry|iphone|ipod|iemobile|palmos) [NC,OR]
RewriteCond %{HTTP_COOKIE} mobile=yes
RewriteCond %{HTTP_COOKIE} !mobile=no
RewriteRule / /mobile.html [L]

I'm not comfortable with the ReWriteRule / /mobile.html [L] part. What happens if the user goes to example.com, example.com/, example.com/index.html. Is there a better way to match this?

lucy24

12:37 am on May 16, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



What happens if the user goes to example.com, example.com/, example.com/index.html

Useful question. "example.com" without slash is not a problem, because the browser itself appends the slash.

"index.html" is two different issues, because it can come from two different places.

One: mod_dir will silently rewrite any directory in / to add the appropriate index file. This is its job. Usually this happens after mod_rewrite, but if you want to be safe, you can add a line saying {THE_REQUEST} index\.html to keep from going around in circles.

Two: users who really request "index.html". It goes without saying, ahem, that none of your own internal links use this form. The name of a directory ends in /. So that leaves the type-ins. They need to be forcibly redirected to directory-name alone.

Now, I have belatedly noticed two problems with the "pattern" side of your rule says. First, it says "/" rather than nothing. Does the slash work? On shared hosting it isn't supposed to. Second and more urgently, there are no anchors. That means the Rule will apply to anything in any directory-- including non-page files.

You need an extra step that says, generically,

RewriteCond %{THE_REQUEST} index\.html$
RewriteRule (([^./]+/)*)index\.html http://www.example.com/$1 [R=301,L]

Since Redirects go before Rewrites within your mod_rewrite directives, that automatically takes care of the intentional index.html...

...leaving only the ickier, messier question of people who enter the site somewhere other than the front page.