Wednesday, February 01, 2006

Using mod_rewrite to avoid seeing script names

It seemed like a pretty innocuous job... getting rid of the script name in the request http://localhost/~scottw/puma3/puma3.lisp/extra/path. But you wouldn't believe the pain it caused me! I record here the eventual solution (the inspiration is from this post related to removing the index.php from wiki urls).

Suppose you have a script ~/web/script.cgi, which is ordinarily accessible from the web as ~user/script.cgi. You want to rewrite requests like ~user/path into requests like /~user/script.cgi/path. The important piece being that the script sits in the same directory as your "virtual" path filename. Because of this important fact, the following ~/web/.htaccess will not work:

RewriteEngine On
RewriteBase /~user/
RewriteRule ^(.*)$ script.cgi/$1 [L]
Even though you added [L] to your rule, requesting ~user/anything will result in a 500 error. Looking at the apache logs, you'll see mod_rewrite complaining of too many internal rewrites. This is because your request is being rewritten over and over again like this:
anything -> script.cgi/anything -> script.cgi/script.cgi/anything

This is where the magic happens. You only want the rewrite rule to run when the virtual path doesn't exist. Here's the correct and working solution:

RewriteEngine On
RewriteBase /~user/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ script.cgi/$1
Now after the first rewrite, the request filename begins with script.cgi, so the condition isn't true and the rewrite isn't triggered.


Blogger Geoff said...

Oh, yes... it's verr nice!

4:48 PM  

Post a Comment

<< Home