Miles
Miles

Reputation: 69

Nginx try_files not working with domain that appends trailing slash

I have a dockerised Django app where nginx uses proxy_pass to send requests to the Django backend. I am looking to pre-publish certain pages that dont change often so Django doesnt have to deal with them.

I am trying to use try_files to check if that page exists locally and pass to Django if not.

Our URL structure requires that all URLs end with a forward slash and we dont use file type suffixes e.g. a page might be www.example.com/hello/. This means the $uri param in nginx in this instance is /hello/ and when try_files looks at that it is expecting a directory due to the trailing slash. If I have a directory with a list of files how do I get try_files to look at them without re-writing the URL to remove the slash as Django requires it?

My nginx conf is below.

server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    server_name example.com;

    root /home/testuser/example;

    location / {
        try_files $uri uri/ @site_root;
    }

    location @site_root {
       proxy_pass         http://127.0.0.1:12345;
    }
}

If I have a file "hello" at /home/testuser/example/hello and call https://www.example.com/hello/ how can I get it to load the file correctly?

P.S. the permissions on the static content folder and its contents are all 777 (for now to rule out permissions issues)

Cheers in advance!

Upvotes: 2

Views: 1797

Answers (2)

RilDev
RilDev

Reputation: 301

In my case using NextJS, leaving the final slash causes errors.

So here is the solution I found to make it work nicely:

root /path/to/static/files/directory; # no trailing slash
rewrite ^/(.*)/$ /$1 permanent; # automatically remove the trailing slash

location / {
  try_files $uri $uri.html $uri/index.html /404.html;
  # try the provided uri
  # then try adding .html
  # then try uri/index.html (ex: homepage)
  # finally serve the 404 page
}

Upvotes: 0

Richard Smith
Richard Smith

Reputation: 49792

You can point the URI /hello/ to a local file called hello or hello.html using try_files, but you must first extract the filename using a regular expression location. See this document for details.

The advantage of using .html is that you will not need to provide the Content-Type of the response.

For example, using hello.html:

root /path/to/root;

location / {
    try_files $uri uri/ @site_root;
}
location ~ ^(?<filename>/.+)/$ {
    try_files $filename.html @site_root;
}
location @site_root {
   proxy_pass  ...;
}

If you prefer to store the local files without an extension, and they are all text/html, you will need to provide the Content-Type. See this document for details.

For example, using hello:

root /path/to/root;

location / {
    try_files $uri uri/ @site_root;
}
location ~ ^(?<filename>/.+)/$ {
    default_type text/html;
    try_files $filename @site_root;
}
location @site_root {
   proxy_pass  ...;
}

Upvotes: 3

Related Questions