Using try_files while forcing a trailing-slash in the URL

Ben Johnson ben at
Tue Jun 18 19:22:04 UTC 2013


Brand new to nginx and loving it so far. Thanks to all who contribute to
the project.

The try_files directive is brilliant. The only problem I'm having is
that I would like to be able to force a trailing-slash, a la "rewrite",
on the fallback URL.

The try_files documentation at states that
something like this is usually sufficient (and it is):

# for Drupal 6 or 7:
try_files $uri $uri/ /index.php?q=$uri&$args;

This works well, but I have a need to eliminate duplicate URLs (for SEO
["duplicate-content penalty"] reasons) by forcing a trailing slash on
all virtual URLs (that is, URLs that do not point to a real file or

Am I missing something obvious?

I was able to cook-up a "working solution", but it will probably bristle
a few peoples' hair:

location / {
    # Because nginx doesn't support compound logical
    # expressions in this context, e.g., "if $a = 1 && $b = 2".

    set $test "";

    if (!-d $request_filename) {
        set $test "${test}nd";

    if (!-f $request_filename) {
        set $test "${test}nf";

    # The request is NOT for an existing file or directory;
    # It must be for a) a file that doesn't exist, b) a legitimate
    # clean-URL PHP resource.

    # Even if the request is for a legitimate clean-URL PHP resource, we
    # always force a trailing slash.

    if ($request_filename !~ "/$") {
        set $test "${test}nts";

    # Not a directory, not a file, and doesn't contain a trailing
    # slash; we need to redirect and append the slash.

    if ($test = 'ndnfnts') {
        rewrite ^(.*[^/])$ $1/ permanent;

    # Not a directory and not a file, but contains a trailing slash;
    # we're done, and we can rewrite the URL per our
    # Controller Pattern logic.

    if ($test = 'ndnf') {
        rewrite  ^(.*)$  /index.php?q=$1  last;

Ultimately, I'm wondering if there's a means by which to achieve the
above with try_files, and if not, if there's a better means than what
I've employed on my own.

A related "problem" (more an inconvenience, really) is that using
try_files in the manner described in the cited documentation causes the
trailing ampersand ("&") to be appended to "q" even when there are no
$args. Is this behavior intentional? Maybe there's an RFC of which I"m
unaware that lead to this decision.

Thanks for any help!


More information about the nginx mailing list