Apache-style multiviews with Nginx
I'm interested in switching from Apache/mod_php to Nginx for some non-CMS sites I'm running. The sites in question are either completely static HTML files or simple PHP, but the one thing they have in common is that I'm currently using Apache's mod_negotiation to serve them up without file extensions. I'm not concerned with actual content negotiation; I'm using this just so I don't have to use file extensions in my URLs.
For example, the file at /info/contact.php
is accessed via a URL of just /info/contact
The actual file is a .php
file in that location, but I don't use the extension in the URLs. This gives me slightly shorter, cleaner URLs and also doesn't expose what's essentially a meaningless implementation detail to the user. In Apache, all this takes is enabling mod_negotiation and adding +MultiViews to the Options for the site. In Nginx I gather I'll be rewriting somehow but being new to Nginx, I'm not exactly sure how to do it.
These sites are currently working fine proxied from Nginx to Apache, but I'd like to try running them solely with Nginx/fastcgi. They work fine this way as long as I'm using the extensions, so the fastcgi aspect is working great. My concern now is just with removing those extensions.
It's important to keep in mind that the filename is not always in the URL, in the case of subdirectories. That is,
/foo/bar
should look for /foo/bar.php
or /foo/bar/index.php
/foo/
should look for /foo/index.php
Is there a simple way to achieve this with Nginx or should I stick with proxying to Apache?
You don't need any tedious rewrites, try_files works perfectly for this. It's essentially only one line.
server {
server_name foo.com;
root /your/root/path;
index index.php;
location /
try_files $uri.php $uri/ /notfound.html;
}
# Your standard PHP location and everything else is still required here.
}
Alternatively you can use:
try_files $uri $uri/ index.php;
without the /
in front of index.php it would look for /foo/bar/index.php
if it couldn't find /foo/bar/somethingelse.php
. (most people have /index.php
as the fall back, as that is normally what would work with wordpress and similar CMSes).