Hacker News new | ask | show | jobs
by richardjs 4433 days ago
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
1 comments

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.