FallbackResource

There’s a new directive in mod_dir, and I’m very pleased about it, because it’s something that we’ve wanted for a long time, and which a LOT of people will benefit from. The directive is called FallbackResource, and is documented here.

Many web applications use the concept of a “front controller”, which means that every incoming request is mapped to a single script/handler/program that determines what needs to be done based on the URI. There’s some kind of an internal URL parsing mechanism that takes the action and arguments from the URI and sends it to the correct function or controller to produce output.

In order to produce this effect, there needs to be some kind of rewrite that sends all requests to that front controller. Something like this:

RewriteEngine On
RewriteRule (.*) index.php

Then, when the URI /foo/bar is requested, that gets sent to index.php, which, in turn, looks at the variable REQUEST_URI (‘/foo/bar’) and figures out what to do.

The trouble with this approach is that actual file resources, like ‘my_logo.jpg’ and ‘style.css’ also get sent to index.php, so we have to take steps to avoid that happening:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php

-f and -d are rewrite-speak for “is a file” and “is a directory”, respectively. So this says “if it’s not a file, and not a directory, do the rewrite.”

A lot of web app projects use a rewrite ruleset exactly like this one. WordPress does. CakePHP does. Drupal and Habari and Django, and lots of other things do. Unfortunately, many of them get it horribly wrong, or, sometimes, just sufficiently wrong to make it hard to troubleshoot. And WordPress famously had a 72-line version of this at one point. Fortunately, they fixed that several years ago.

But even that isn’t enough, because sometimes you have Aliases that need to be explicitly avoided, and you’ll need to list those, too:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(pony|server-status|server-info|icons)
RewriteRule (.*) index.php

And, of course, you may have other rewrite rules for other things on your site. And with added complexity comes added fragility, so there’s greater chance of breaking something, or just getting confused.

All of the above is now replaced by one directive:

FallbackResource index.php

That’s all. It says “if a request doesn’t map to something, send it to index.php.”

This directive is in trunk, and so will be in the 2.3/2.4 release. I don’t know if it will get backported to 2.2.