nginx try_files to rewrite .html into "clean" url

Here's the directory containing static html files

public
|-- index.html
|-- media
|   `-- blurred_image-8.jpg
|-- post
|   `-- 13considerations
|       `-- index.html

I am attempting to configure nginx to convert all the urls ending with .html to strip out the suffix.

Like this:-

server {
    listen       80;
    server_name  mysite.com;

    location / {
        root   /var/www/mysite/public;
        try_files  $uri  $uri/ $uri/index.html;
    }

    location /media/ {
        alias /var/www/mysite/public/media/;
        error_page 404 = /404;
        expires 30d;
    }

    location /static/ {
        alias /var/www/mysite/public/static/;
        error_page 404 = /404;
        expires 30d;
    }
}

This works properly for the homepage "http://mysite.com/" but if I attempt to access "http://mysite.com/post/13considerations/", I get a 500 internal server error.

What gives?


The example you're using works for returning the contents of a directory's index.html file, but will not work for files (e.g., http://server/somedir/file will not return the contents of /somedir/file.html).

A simplified configuration, which will return any HTML file without its extension and will use index.html for directories is as follows:

server {
    listen       80;
    server_name  mysite.com;

    index index.html;
    root /var/www/mysite/public;

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

    location ~ \.html$ {
        try_files $uri =404;
    }   

    location @htmlext {
        rewrite ^(.*)$ $1.html last;
    }   
}

How it works:

  • Specifying index index.html will default to using this file when directory URIs are accessed.
  • Putting root outside the location block will apply server-wide.
  • try_files $uri $uri/ @htmlext will look for an exact match for a file or directory first before finally trying to append .html.
  • try_files $uri =404 is to prevent Nginx getting stuck in a rewrite loop if a file can't be found.
  • rewrite ^(.*)$ $1.html last appends .html and restarts the URI matching process.