I’m feeling very sickly at the moment, but I figure doing a post will help distract me.
Afew weeks back I began attempting to get Apache webserver to take a request, sans the extension, and give me back a php file with the same name (e.g. /admin displays /admin.php). I was puzzled to find that my rewrite wasn’t working as it should in some Apache configurations in my development environment.
Enter MultiViews!
“MultiViews” is an Apache option that was created mainly to deal with content negotiations where a server has several language specific versions of content available to web users (index.en.html, index.fr.html, etc). More info on MultiViews can be found at the Apache content negotiation pages. I use Apache 1.3, so please keep that in mind when reading this. I’ll explain why I use Apache 1.3 in a later post. You must specify the MultiViews directive in the Options line of your httpd.conf or .htaccess file for it to function.
But what is it?
The above documentation sucks, so I will sum up what it says. MultiViews was created so when it is on, Apache will serve content that is derived from the request, based on the information the browser passes, and if the specified files are present. So, MultiViews takes a logical request and returns the contents of a physical file that is closest to what is requested.
What does it do?
If you request index.html, but specify EN as your language, Apache will return index.en.html to your browser. And if you request /admin (and assuming the directory doesn’t exist), Apache will return admin.html if it exists. Why? Because admin.html is of the html/text type (.html) and starts with admin. Your browser by default expects html/text. It basically guesses which file you are requesting based on the browser request. Keep in mind that this is based on the extension of the file and it’s associated type. Apache uses the left most extension first to make a match (index.en.html). For my purposes, this isn’t important, since I only care about one extension.
Yay! Wait, no yay. That’s not what I wanted. I wanted it to return admin.php!! MultiViews returns admin.html!
Luckily, if admin.html doesn’t exist, and admin.php does, it will return the latter. This is where I noticed something wrong while writing my rewrite. I won’t get specific, but I wrote my rewrite in such a way that it would deliver PHP before HTML (admin.php over admin.html, if both exist), but it was returning the HTML first, because MultiViews was governing what was returned, not my rewrite. It took me days to figure out MultiViews was the culprit… Ok, now we celebrate.
Known Issue!
Wait! A major issue has been documented around the net about MultiViews. Allegedly, if you use MultiViews to display PHP without an extension, the server will incorrectly report the mime type as application/x-httpd-php. Normally, the php parser returns text/html, and Apache usually reports it as such. However, the server will not return content to a browser that does not support that type; it just throws a server error, the dreaded error 406 - Not accepted. Well, most browsers will accept the application/x-httpd-php type. The Googlebot browser however, will -not- accept the application/x-httpd-php type. I would venture to say that not being indexed by Google is unacceptable to most people.
Is It Fixed Though?
After experimenting (by passing a spoofed agent string to my Apache webserver) I have discovered that this issue seems to have been resolved in my version of Apache 1.3 and in our testing version of Apache 2.0. So when I request a PHP file without an extension, Apache returns the correct html/text type. I can’t find any documentation that specifically mentions it being fixed, so I will move forward very cautiously. Luckily, we have a Google Appliance at work, so we can point it at a test system and see what happens, just to be sure. I would hate to redo the entire UH website with this technique, and then lose our ability to index the site… *shiver*
This gave me such a headache, I hope collecting this information in one place will help others. I’ll try to find out officially if this issue has been resolved in the latest versions of Apache.
Bad Documentation, Hard to Implement
While I’m on this subject, MultiViews’ documentation is painfully incomplete, and the option is also unfriendly and not configurable. I can’t tell it to prioritize PHP content over HTML, or atleast it’s not documented.
I shouldn’t be complaining, lest I forget that this webserver is -free- and open sourced, so if I want to correct MultiViews’ shortfalls bad enough, I should shutup and checkout some code from the Apache repository.</rant>