How to rewrite and forward .*/index.html to .*/ with nginx and Apache

Recently, I decided to clean up my index urls. I had .*/index.html files, directory listings at .*/, indirect serving of index.html to .*/, many times with the index being reachable via two urls without forwards. It’s good practice to have only one URL for a specific page (and it also makes the GoogleBot happy), so I looked into forwards and redirects with Apache and nginx.

First, you need to decide whether you prefer .*/ or .*/index.html. I’m in for the former, because I wanted to have a coherent scheme with directory listings, too, and it doesn’t make sense to have a webserver-generated directory listing at the location of a file. Also, it seems to me like it’s the more semantically correct url. My requirement was to have the forward for all directories and index.html files, not only for the top level /index.html. The usual examples don’t cover that and / or use two regexes, but I found an easy way to do it with a single one.

nginx

For nginx, you need the rewrite directive and a small workaround:

# forward all index.html files to their parent directories for having unique urls
rewrite ^(.*/)index.html$ $1 permanent;

# The default index directive, "index index.html;", reacts on .*/
# with an internal redirect to .*/index.html, which is then affected
# by the rewrite, resulting in an infinite redirect loop.
# This location directive breaks the loop by bypassing the index directive
# and directly trying to serve index.html.
location ~ ^(.*)/$ {
    try_files $1/index.html =404;
}

The index index.html directive works with an internal redirect, which seems to get caught in the rewrite rule again, endlessly. try_files also does an internal redirect like the index directive, but as it’s enclosed in a location block, it doesn’t reach the rewrite above anymore (At least I think that’s the reason… drop me an email if you know more about or a better way to do this).

Apache

For Apache, you need the RewriteRule directive:

RewriteEngine on
# forward all index.html files to their parent directories for having unique urls
RewriteRule ^(.*/)index\.html$ $1 [redirect=301,last]

No workaround needed for apache, the rule just works as expected. But don’t forget a

sudo a2enmod rewrite

if you don’t have mod_rewrite already enabled.

Have fun!

Remarks? Additions? Corrections? For anything you want to tell me about this blog post, feel free to send me an email[*].
Despite having no comments section (isn't that easy with a static site generator and without relying on a proprietary 3rd party service), I greatly appreciate direct feedback. 😉 In case of additions, I'll mention the name from the mail if you don't object.

[*]: Mails from small independent mailservers are my mailserver's favourite! ❤
If you don't want to keep one on your own, you can pay various admins about 1€ per month to do so for you, e.g. at posteo, mailbox.org, jit-creatives, or at most webhosting providers like netcup or 1&1 in case you want to have your own domain name on top.