other rules: Never add trailing slash unless it is an index file of a directory. Order: .PHP,.HTML,.HTM. Use h5bp/server-configs-nginx as a base. PHP-FPM should be fully supported and not exploitable by the foo.com/random.gif.php bug. 403 and 404 send to /404.html.
I am sure I am forgetting something, but that is a start.
Your specs look a lot like ours (we have a CMS that adds a trailing /index to every page that is part of the core navigation, and we don't want that). Here's the three primary rewrite rules we use for the issue; they don't match your spec exactly, but they might help you get started:
# - Remove trailing slashes (except root /)
# e.g. /foo/bar/ -> /foo/bar
# ([^^] matches every character but the start of the string)
rewrite [^^](.*)/$ /$1 permanent;
# - Remove .html and .htm extensions
# e.g. /foo/bar.htm -> /foo/bar
rewrite ^(.*)\.html?$ $1 permanent;
# - Remove index file URLs
# e.g. /foo/bar/index -> /foo/bar/
# (the trailing slash is then removed by the first rewrite)
rewrite ^(.*/)index$ $1 permanent;
Edit: There's a couple extra directives that go along with the above to make it work that I neglected to include:
# Try the request URI, and a potential index file in the URI (in the case of a directory).
# This lets you hit the file WEBROOT/foo/bar/index with the URI /foo/bar,
# and hit the file WEBROOT/foo/bar.html with the URI /foo/bar
try_files $uri $uri/index $uri.html =404;
# You need this (or some other way to provide the type information)
# if you don't have extensions on your files.
default_type text/html;
Also, for error pages, you can probably just use the error_page directive:
error_page 404 403 /404; # The .html in your spec will be stripped off by the above rewrite rule
I have had problems using rewrite in this way. The URL that rewrite analyses may have already been changed by `index` or some other command, and this will lead to redirect loops. To avoid that problem, I have used:
if ($request_uri ~* "^(.*)\.html?$") {
return 301 $1;
}
The above is a safe use of "if", and can be helpful since it operates on the actual uri, not the internal uri.
That's a good suggestion. Yeah, index directives will cause a redirect loop in my above configuration. The try_files directive is effectively taking the place of an index.
foo.com/* -> www.foo.com/* seems "cleaner" to me than your opposite, due to the issues with cookie leaking, CDN hosting, "normal user" expectations, etc. Like, please appreciate that your usage of "cleaner" is at best subjective ;P. (And I don't quite understand how you are intending to do "foo.com/ -> foo.com"... all URLs must have a path: you can't just GET, you have to GET /.)
I understand the redirecting to non-www is subjective, however I find less characters in the URL is cleaner. Also for a majority of my projects cookies are not used, so it is not a big deal to use a non-www base url.(Static blogs and simple vanilla sites for various school projects, etc).
Also as far as foo.com/ -> foo.com, I was referring to the URL, not the acutal path.
No, that's just your browser (annoyingly) removing the trailing slash from URL shown in the address bar.
http://www.foo.com/ is the "correct" URL. Remember how HTTP works -- you connect to foo.com port 80, then "GET / HTTP/1.1". You can't just omit the "/" and expect it to work.
HTTP clients will just request "/" if no path is specified, so nginx will never even see a request that matches "^foo.com$". You'll cause an infinite redirect loop if you try to force the issue.
I am designing this Ngnix conf for use on small vanilla sites and static generated sites like Jekyll. Otherwise, yes I would rely on my CMS's index file.