Apache RewriteRules 101
Dec. 9th, 2008 05:14 pmIf you run your own machine, you probably don't want to use Apache as a webserver. Its configuring is complex, arcane, and it sucks up memory like a Microsoft toaster. There are lighter, faster alternatives out there, such as Nginx or thttpd. But, if you buy webserver from someplace, you'll probably be forced into using Apache, and will be for the foreseeable future. That being said...
What is a rewrite rule?
A rewrite rule is a way that Apache can rewrite an incoming request "on the fly". In essence, a user can ask a webserver for one file, and the webserver can serve up a completely different file to the user instead.
Isn't this like a redirect?
No, a redirect is when the webserver tells a user, "that's not the file you want, you need to go over here", at which point the browser loads the new URL. Redirects aren't always desirable, especially of the files/PHP scripts/whatever are currently living a temporary location.
Why would I want to use one?
Let's say you're installing an app that somebody else wrote, and the app lives under /very-long-application-name. You could use a rewrite rule so that users could go to /short-app-name, and Apache would rewrite that request behind the user's back to be /very-long-application-name. And the best part is that this is transparent to a properly built application.
Another example is maybe you're starting up a video "tube" site, and you want to have the smallest embed code possible for sharing videos. Problem is, the video player lives at http://mysite/app/version1.0/video/player.swf. You could use a rewrite rule so that http://mysite/player.swf is rewriting to the longer URL. And what's even better is that when you release version 2.0 of the video player, you can just update the rewrite rule, and everybody will start seeing version 2.0 of your player.
Is this really used in real life?
Yep. The best example I can think of is Drupal. When you load a URL from a Drupal-powered site, such as http://drupal.org/drupal-6.6, that is really rewritten by Apache to be http://drupal.org/?q=drupal-6.6. Regardless which URL you load, Drual sees that the variable $q is really set to "drupal-6.6". It doesn't care which URL was used.
Okay, so how do I do it?
Ah, here's the good part. The first thing you need to do is put the following in your .htaccess file:
Now, let's say you wanted to rewrite the path to your video player, as described in the example above:
Most Drupal configurations have something like this:
I hope that this post was helpful, and saves you from going through some of the pain that I went through when learning how rewrite rules work. :-) If this wasn't enough pain for you, full documentation on Apache rewrite rules can be found on their official site at:
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html
Enjoy!
What is a rewrite rule?
A rewrite rule is a way that Apache can rewrite an incoming request "on the fly". In essence, a user can ask a webserver for one file, and the webserver can serve up a completely different file to the user instead.
Isn't this like a redirect?
No, a redirect is when the webserver tells a user, "that's not the file you want, you need to go over here", at which point the browser loads the new URL. Redirects aren't always desirable, especially of the files/PHP scripts/whatever are currently living a temporary location.
Why would I want to use one?
Let's say you're installing an app that somebody else wrote, and the app lives under /very-long-application-name. You could use a rewrite rule so that users could go to /short-app-name, and Apache would rewrite that request behind the user's back to be /very-long-application-name. And the best part is that this is transparent to a properly built application.
Another example is maybe you're starting up a video "tube" site, and you want to have the smallest embed code possible for sharing videos. Problem is, the video player lives at http://mysite/app/version1.0/video/player.swf. You could use a rewrite rule so that http://mysite/player.swf is rewriting to the longer URL. And what's even better is that when you release version 2.0 of the video player, you can just update the rewrite rule, and everybody will start seeing version 2.0 of your player.
Is this really used in real life?
Yep. The best example I can think of is Drupal. When you load a URL from a Drupal-powered site, such as http://drupal.org/drupal-6.6, that is really rewritten by Apache to be http://drupal.org/?q=drupal-6.6. Regardless which URL you load, Drual sees that the variable $q is really set to "drupal-6.6". It doesn't care which URL was used.
Okay, so how do I do it?
Ah, here's the good part. The first thing you need to do is put the following in your .htaccess file:
RewriteEngine OnIf doing this gives you a "500 Server Error" when you try to load a webpage, go ask your web host to enable mod_rewrite. If they refuse, I would suggest moving to a webhost that doesn't suck.
Now, let's say you wanted to rewrite the path to your video player, as described in the example above:
RewriteRule ^player.swf$ /app/version/1.0/player.swfNote the "^" and "$" in the "left hand side" of that rewrite rule. That tells Apache to match ONLY the string "player.swf", and not "/path/to/player.swf". This will prevent an infinite loop wherein that string is matched over and over. (Infinite loops are bad, m'kay?)
Most Drupal configurations have something like this:
RewriteCond %{REQUEST_FILENAME} !-fThat's some pretty advanced stuff there, and it uses a new directive, "RewriteCond". RewriteCond allows you to do 1 or more levels of matching in addition to the matching in the RewriteRule line. In this case, if the URI that the user attempts to load is neither a valid file nor a valid directory, then it is rewritten as index.php with the original URL passed in as $q.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
I hope that this post was helpful, and saves you from going through some of the pain that I went through when learning how rewrite rules work. :-) If this wasn't enough pain for you, full documentation on Apache rewrite rules can be found on their official site at:
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html
Enjoy!
(no subject)
Date: 2008-12-09 10:55 pm (UTC)San FranciscoMontana called 540040.html? No, there's not, it's a unique identifier that points the LJ server software to some unique resource(s) in a database (we'll skip the filesystem-database debate for now). Look at the various URLs you see and you'll realize most of them are hiding some kind of complexity, especially the Web 2.0 stuff.Ultimately URLs are just, well, resource identifiers and it's up to the Web server how it replies. There's no written law anywhere that says that the URL has to be a real file. That's just an artifact of archaic design in some various server software packages (e.g. have you ever tried to set up an FTP server?).
(no subject)
Date: 2008-12-09 10:59 pm (UTC)I suspect that the rewriting in the example you described is done by application code. Not that there's anything wrong with that, of course.
But the whole reason I wrote up this little tutorial because it seems that people in the industry aren't familiar with rewriting done at the webserver level. And I wanted to give some real-life examples of where a little use of RewriteRule can have a whole lot of impact.
(no subject)
Date: 2008-12-09 11:01 pm (UTC)Probably there is some kind of driver script that gets the path part of the URL (/500040.html?replyto=4777342), sort of like main() in C, that parses the URL and decides what to do from there.
(no subject)
Date: 2008-12-09 11:05 pm (UTC)(no subject)
Date: 2008-12-09 11:56 pm (UTC)I've found RedirectMatch (using mod_alias (//httpd.apache.org/docs/1.3/mod/mod_alias.html)) will often do fine for simple redirection if for some reason you don't have or don't want to use mod_redirect, e.g.:
RedirectMatch 301 (.*) http://yerf.artspots.com$1(no subject)
Date: 2008-12-10 12:16 am (UTC)Alias /player.swf /path/to/player.swf
Simpler and less chance of an accidental infinite loop. It's important to note, though, that Redirect works on URL's, but the target of an Alias is a filesystem path. And while there is an AliasMatch, since it doesn't work on URL's, it can't do what the Drupal example does. mod_alias covers this in more depth.
(no subject)
Date: 2008-12-10 12:17 am (UTC)And that's usually the only config file you can modify when using somebody else's webhosting service.
(no subject)
Date: 2008-12-10 12:24 am (UTC)Now, if only I could get mod_speling to work with that...
I mean, internally I am redirecting requests to something like
script.php?directory=$1
So when I fopen the files or whatever, the filename is case and mispelling sensitive.... I've thought about writing my own logic to at least fix spelling errors, but with it already being out there, I don't really want to...
(no subject)
Date: 2008-12-10 12:31 am (UTC)(no subject)
Date: 2008-12-10 01:07 am (UTC)If I ever need to rewrite requests under Apache, though, I know a little about that now. :o)
(no subject)
Date: 2008-12-10 01:51 am (UTC)Very, very, very useful, though.
(no subject)
Date: 2008-12-10 03:54 am (UTC)With the regex ability to snag info out of the URI it can sometimes be the glue to bridge legacy code into a new system.
On one system we moved the users from being "/~user" to "user.domain.com." The cool thing is that by have the rewrite rule to grab and change the URI, any existing pages that referenced "/~user" in their HTML code still functioned without excessive 302 calls.
A very handy thing.