Using try_files while forcing a trailing-slash in the URL

Ben Johnson ben at indietorrent.org
Thu Jun 20 14:25:35 UTC 2013



On 6/18/2013 5:55 PM, Francis Daly wrote:
> On Tue, Jun 18, 2013 at 03:22:04PM -0400, Ben Johnson wrote:
> 
> Hi there,

Hi, Francis! I really appreciate your help and your time. Thanks for
replying in such detail.

>> 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.
> 
>> 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
>> directory).
>>
>> Am I missing something obvious?
> 
> try_files decides which file to serve, with a single fallback option. If
> that fallback option is something complicated, it is probably best to
> use a named location and put the complications in there.

This makes fine sense.

>> I was able to cook-up a "working solution", but it will probably bristle
>> a few peoples' hair:
> 
> If it works, it works. If you can measure the load on your test server,
> you may be interested in trying other things too and comparing.
> 
> For example:
> 
>   location / {
>     try_files $uri $uri/ @virtual;
>   }
>   location @virtual {
>     if ($uri !~ '/$') {
>       return 301 $uri/$is_args$args;
>     }
>     fastcgi_pass unix:php.sock;
>     fastcgi_param SCRIPT_FILENAME $document_root/index.php;
>     include fastcgi_params;
>   }
> 
> as well as a location for handling /index.php or any similar things
> directly.
> 
> (Depending on what exactly your php script does, you may also want to
> set QUERY_STRING explicitly.)

Your example is a true stroke of genius as compared to the garbage that
I put together. The end-result is the same and your example is far more
elegant.

> 
>> 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.
> 
> The above uses try_files, and uses "if" within "location" with only
> "return", which is a safe thing to do. http://wiki.nginx.org/IfIsEvil

Yes, I have read the IfIsEvil article a few times over. I would
certainly prefer to avoid using "if". =)

>> 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.
> 
> You asked for $uri, then &, then $args.
> 
> You should be surprised if you get anything other than $uri, then &,
> then $args.

Haha... fairly-stated. Ask and ye shall receive. And receive I did.

> I suspect it was done because the php script it feeds is known to ignore
> the unnecessary &.

Ah, I see; the implication is that Drupal 6 ignores the superfluous
ampersand, hence its inclusion in the example that I used.

I've made the adjustments necessary for my PHP script to ignore it, too.
I'm happy with the result, as-is, but I appreciate the below suggestions
nonetheless.

> nginx does provide the variable $is_args, but that is intended for other
> circumstances where it is more useful. You could do more "if" things on
> $is_args or on $args to decide whether to add the &, if you want to.
> 
> Good luck with it,
> 
> 	f
> 

Thanks again!

-Ben



More information about the nginx mailing list