homepage Welcome to WebmasterWorld Guest from
register, free tools, login, search, subscribe, help, library, announcements, recent posts, open posts,
Subscribe to WebmasterWorld
Home / Forums Index / Code, Content, and Presentation / Apache Web Server
Forum Library, Charter, Moderators: Ocean10000 & incrediBILL & phranque

Apache Web Server Forum

Redirect to mobile-cache version [help please]
I'm trying to use the same url for mobile devices

 8:57 pm on Jun 6, 2013 (gmt 0)

Hi, been trying hard before coming to ask here but I'm getting nowhere.
  • I have one site with real html files (static) organized into folders
  • I'm creating separated html files for mobile version, separate folder (no subfolders)
  • I want mobile users to be shown that content instead (same URL)

The files go like this:
  • www . domain . com /history-of-widgets_chapter(1).htm
  • www . domain . com /International-widgets/blue-widgets.htm

I'm trying to redirect that into:
  • www . domain . com /mobile/history-of-widgets_chapter(1).htm
  • www . domain . com /mobile/International-widgets-blue-widgets.htm

It's just one folder with no subfolders, so I'm capturing the url and replacing the"/" into "-" and redirecting users to that folder "mobile".

I'm using this on another site/thing:

Options +FollowSymLinks
RewriteEngine On
RewriteRule ^([a-zA-Z0-9\-\_\,\(\)]+).htm$ http://www.example.com/celd/mobile/$1.html [NC]
RewriteRule ^([a-zA-Z0-9\-\_\,\(\)]+)/([a-zA-Z0-9\-\_\,\(\)]+).htm$ http://www.example.com/celd/mobile/$1-$2.html [NC]

That's working so far but it changes the URL, I need to keep the old one and combine it with this:

RewriteCond %{HTTP_USER_AGENT} "android|blackberry|googlebot-mobile|iemobile|iphone|ipod|#opera mobile|palmos|webos" [NC]

? I jus't can't get this to work, any help will be appreciated.

[edited by: phranque at 1:46 pm (utc) on Jun 7, 2013]
[edit reason] exemplified hostname [/edit]



 9:55 pm on Jun 6, 2013 (gmt 0)

First reaction on seeing topic title plus subtitle: You cannot put "Redirect" and "same URL" into the same sentence. One or the other.

I just can't get this to work

What does your best effort look like? It seems as if you are at least 3/4 of the way there. Remember that each RewriteCond applies only to the immediately following rule. If you've got two rules with the same condition, you'll need to spell out the condition twice. Or see if you can compress it all into one rule.

It looks as if what you want to do is

RewriteCond {stuff about user-agent here}
RewriteCond %{REQUEST_URI} !^/mobile {this part is crucial because you can't put a negative into a rule that requires a capture, and you need to stop infinite redirects}
RewriteRule (blahblah) /mobile/$1 [L]

DO NOT use the [R] flag, because that will get you the redirect.

Now, personally I'd say you want a redirect, so it's clear that different URLs represent different content. But that's me. You will also need some way for users to override the default redirect if you've misidentified the user-agent; mod_rewrite can read cookies so this is not a problem. Just add another RewriteCond.


This can almost certainly be made less verbose. Since you're rewriting instead of redirecting, you do not want a [NC] flag. But it can be compressed in other ways. For starters, what are the parentheses doing in there? They've got no business in an URL; in fact I'm not even sure they are legal in the path.

In any case, nothing inside grouping brackets needs to be escaped except \ and ] and (in some positions) - hyphen. In some Apache mods, including mod_rewrite, you also have to escape literal spaces. But of course you wouldn't have those in an URL. (They are technically legal, but a bad idea because of the way they get mangled in transit. Same goes for parentheses, whether legal or not.)

Here the pattern boils down to
which in turn can almost certainly be reduced to
(note that the lowline is a "word character" while the hyphen isn't). Sometimes you'll meet a grumpy server, but \w is rock-bottom standard RegEx. And then, unless you have other strange characters that you particularly don't want to include in the redirect, this in turn reduces to


:: pause here to synchronize chronometers ::

meaning "directory name, slash, filename, extension".

Your bracketed group as originally written has nothing technically wrong with it and will cause the server no trouble; it's just a lot more bytes to read. (Every single thing the server does takes time. It may be measured in micro- and nanoseconds, but it's still time.)


 10:23 pm on Jun 6, 2013 (gmt 0)

Hi, thank you for taking your time I really appreciate it. Arrhh my head hurts.

What does your best effort look like? It seems as if you are at least 3/4 of the way there.

I tried several approaches but I messed up erasing and "fixing" wrong stuff that was not actually wrong (or seems that way). I was updating the .htaccess on the same folder until some simple rules stopped working so I figured some sort of cache (pretty sure browser cache) was getting in the way giving me the same old results of previous attempts.

Thanks for the [a-zA-Z0-9_,()-]+ light.
It seems that ^(.*).htm$ works too.

I went back to basics (my basics ha ha), so I took an old file that does it's job on another site:

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)
RewriteRule (.*) [%1...] [R=301,L]
RewriteRule blah blah (unrelated redirect from VARx.login$1 into login.pl?$1 [L,NC]
RewriteRule blah blah (unrelated redirect as above)
RewriteRule blah blah (unrelated redirect as above)
RewriteRule blah blah (unrelated redirect as above)
HERE: RewriteRule ^(.*).htm$ cgi-bin/core/script.pl?$1 [L,NC]

The last line on that htaccess file sends any url to the script.pl, this way my cms can tell what context to print. That same script prints cache versions (if needed when needed) only loading and printing. So that's my basic here. Besides that, above the htaccess turns any http:// www request into http:// domain . etc.

So I'm trying from scratch with something basic here:

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)
RewriteRule (.*) [%1...] [R=301,L]
RewriteRule ^(.*).htm$ folder/print.pl?$1 [L,NC]

This is working so far. It's sending any url to the script, this script then prints the requested url. This way:

http:// www domain . com/contact.htm turns into the script printing --> contact
http:// www domain . com/CATEGORIES/widgets.htm prints--> CATEGORIES/widgets

And it's keeping the original URL. I could make it work this way implementing a script that just prints the loaded file (from the requested url) but as you say, all of that takes time and resources, so I would like to point it to the actual html files (very little). This site has more enough traffic to make me want to avoid unneeded processes.

I'll post my next attempt, I will test it before to avoid posting something that doesn't work.

Thanks for your help!


 10:34 pm on Jun 6, 2013 (gmt 0)

Update (baby steps here)

This is working so far:

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)
RewriteCond %{HTTP_USER_AGENT} "android|blackberry|googlebot-mobile|iemobile|iphone|ipod|#opera mobile|palmos|webos" [NC]
RewriteRule ^(.*).htm$ print.pl?$1 [L,NC]

Now I'm going to work on turning the / into -

PD. Gotta go, will post my attempts later


 3:19 am on Jun 7, 2013 (gmt 0)

It seems that ^(.*).htm$ works too.

Sure, but much less efficiently. It will capture all pages, regardless of directory depth-- and it will capture the entire request before backtracking to look for the .htm extension. The server basically operates in one dimension. It can't see that there's a "something-htm" coming up ahead. The earlier form was good because the server didn't have to waste any time on non-page requests: the moment it meets a literal period not followed by htm, it's outta there.

And speaking of literal periods, those always have to be escaped in Regular Expressions outside of grouping brackets.

btw, what happens to requests for the front page? In htaccess, that will come through as a null request, so no form of the present rule will match. And any other directory-index page-- if you've got them-- will come through without its trailing "stuff.html" component. Probably. There may be exceptions.

RewriteCond %{HTTP_HOST} ^www\.(.*)

What's this for? Do you have subdomains that you need to omit from the rewrite? If so, what about requests without the leading "www."?

Redirects need to come before rewrites, as a separate step. First get everyone on the same page (literally, in this case) and then serve them the content you want.

When you have a long pipe-separated list, it's a good idea for insurance to enclose the whole thing in parentheses. You can make them (?: non-capturing) if you like.

googlebot-mobile|iemobile|iphone|ipod|#opera mobile

Do any non-mobile UAs contain the string "mobile"? If not, seems like you can do a lot of compressing here.

And watch out! There's a literal space in the middle of that list. The quotation marks may be enough to protect it, but it's safer to escape all spaces (\ ). That's assuming you even need the space; you probably don't.

Never use [NC] when you're rewriting. At best it leads to a nonexistent page; at worst it exposes you to vast Duplicate Content as all kinds of MiXeD-cAse URLs lead to the same content. (Obvious exception: when the rewrite is just a transfer point leading to a php-type thing that will do more stuff before issuing a redirect. Not the case here.)


 7:32 am on Jun 7, 2013 (gmt 0)

^(.*).htm$ works too. ... Sure, but much less efficiently.

For the benefit of the OP, it's worth mentioning that the "much less efficiently" claim is demonstrably untrue. Remember I ran a benchmark for you, Lucy? We should change our opinions to fit the facts; not cherry pick facts to fit our opinions.

@explorador Most of what Lucy told you is good and useful advice, but on this one point, you should know that the pattern (.*) is both standard practice and frequently used even in the official Apache documentation. If it's logically the correct pattern for your requirements, then you should use it.


 7:43 am on Jun 7, 2013 (gmt 0)

Pattern as originally posted and to which I suggested an improvement:


But hey, who needs facts when you've got an opportunity to disagree?


 5:28 pm on Jun 7, 2013 (gmt 0)

Hi there, thanks for the time and guidance.

As for the ^(.*).htm$ vs the other option, well I've seen both around and I can't comment about it, really outside my experience and knowledge to argue in favor or against. Clueless on that here.

RewriteCond %{HTTP_HOST} ^www\.(.*)

I removed it, didn't see any difference so it's gone. It was part of the .htaccess I studied to remove the www from the url, I'm using that code for another site that use purely dynamic pages.

Do any non-mobile UAs contain the string "mobile"? If not, seems like you can do a lot of compressing here.

Done. I understand that "wathever-mobile|new-mobile|andoid-mobile|wap" works the same as just using "mobile|wap". The space has been removed.

NC removed. If "whatever" exist then it will be found while "waThever" and "Wathever" don't exist, then must return not found.

Thanks both for the help, specially Lucy you gave me a lot of light here. It was difficult for me to grasp the concepts I must confess.

I now have a beta .htaccess for this case now.
  • It works as long as the user agent identifies itself as mobile
  • When on mobile, a desktop version can be requested using the query ?desktop
  • It works on .HTM pages and instead (using the SAME url) will show the equivalent mobile version from another folder, these files have .html extension
  • Won't use any script to create the pages or to display them, it would be about pure existent plain html files

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{QUERY_STRING} !desktop
RewriteCond %{HTTP_USER_AGENT} "android|blackberry|mobile|iphone|ipod|palmos|webos|wap|midp" [NC]
RewriteRule ^(.*)/(.*).htm$ mobile/$1-$2.html [L]

Any comments will be welcome

Global Options:
 top home search open messages active posts  

Home / Forums Index / Code, Content, and Presentation / Apache Web Server
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved