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!