Monthly Archives: May 2010

For YAFGC – htaccess Files

Yet Another Fantasy Gamer Comic

This one goes out to Rich and Hilary of Yet Another Fantasy Gamer Comic who are making some changes to their site. In so doing some of their URLs are gonna change, and like good, responsible web citizens they are setting up some redirects from the old URLs to the new ones.

To understand why this makes them awesome, you should read Hypertext Style: Cool URIs don’t change. by Tim ‘I invented the World Wide Web’ Berners-Lee

An htaccess file is a granular Apache configuration file for just one (or a few) directories and files. They are often a pain in the ass to work with and understand… but they’re worth it, as they provide a mechanism by which to implement what most people call "clean urls" using mod_rewrite. I strongly encourage anyone reading this to look into clean urls; they’re good for SEO and make it easier for someone to navigate back to your page when they don’t have bookmarks available (and can’t find it on Google ’cause your messy URLs result in poor SEO :P ) and as such it’s no coincidence that most web frameworks offer them as a feature.

This article/post is for Rich and Hilary though, so I’ll cut to the point:

Apologies, Rich and Hilary, but I work as an educator and as such am irrationally compelled to explain this slowly and as such will – even why trying to get to the point – ramble on at lengths about the "why" every step of the way.

They want to use mod_rewrite to match part of the requested URL (in the query string) and then redirect to another page (with a different query string… on an entirely different domain!).

I am trying to remap this url:
yafgc.shipsinker.com/index.php?strip_id=abcd
to this url:
yafgc.net/?id=abcd
where abcd = a variable numeric parameter, from 1 – 4 digits.

Most people would try the following:

The following is a fail:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteRule \?strip_id\=(\d{1,4}) http://yafgc.net/?id=$1 [L,R]
</IfModule>

In baby steps, this rewrite rule says that, should the requested URL contain…

\?			# a question mark "\?" (escaped with a '\' as '?' is a RegEx quantifier)
strip_id		# followed by "strip_id"
\=			# an equals character "="
(
 \d{1,4}		# between 1 and 4 digits \d
)			# store the digits – hence why they are in brackets

… then we rewrite the URL to http://yafgc.net/?id=$1, where $1 is a backreference to the digits which were in brackets. The "L" and "R" flags tell us this should be the Last rule checked and that the browser should be Redirected.

This won’t work because mod_rewrite doesn’t allow you to match the contents of the query string (the stuff after the question mark ‘?’) in a RewriteRule so the match perpetually fails. Instead, we have to match the query string in a RewriteCond.

The Solution

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{QUERY_STRING}  ^strip_id=(\d{1,4})$
    RewriteRule .* http://yafgc.net/?id=%1 [L,R]
</IfModule>

Here we match the QUERY_STRING and then use a different kind of backreference; unlike other RegEx implementations mod_rewrite provides two dimensions of backreferences; references to the RewriteRule and references to the RewriteCond. References to the rule are prefixed with a dollar sign ‘$’ like $1 in the earlier example, and references to the conditions are prefixed with a percentage sign ‘%’ like %1 in this example.

There is a demo available at http://richard.jp.leguen.ca/yafgc/index.php?strip_id=100