You can do this using mod_rewrite near the top of your .htaccess
file. In its simplest form this would be something like:
RewriteEngine On
# Remove "index.html"
RewriteRule (.*)index\.html$ /$1 [R=301,L]
The regex (.*)index\.html$
matches any URL-path that ends with index.html
and captures the part of the URL-path before index.html
.
The $1
backreference contains the captured URL-path before the index.html
. This would be empty in the case of example.com/index.html
or about/
in the case of example.com/about/index.html
.
HOWEVER, the above will fail if you are also serving files that end with index.html
, eg. /something/foo_index.html
, as it will redirect to /something/foo_
. If this is the case then you would need to change the regex in the above RewriteRule
to something like ^(|.+/)index\.html$
instead. For example:
# Remove "index.html" (whole path segment only)
RewriteRule ^(|.+/)index\.html$ /$1 [R=301,L]
This will then match /index.html
and /something/index.html
, but not /something/foo_index.html
.
^(|.+/)
matches either nothing (ie. the document root) or something followed by a slash (ie. a subdirectory).
You should test first with a 302 (temporary) redirect in order to avoid potential caching issues and only change to a 301 (permanent) redirect when you are sure everything is working OK.
Additional:
Avoid redirect loop if rewriting to index.html
(front-controller pattern)
The above is not sufficient if you are using a front-controller pattern to internally rewrite requests to index.html
(not the case here), since the above would also redirect the rewritten request to index.html
and trigger a redirect loop.
In this case you would need to add an additional condition (RewriteCond
directive) that ensures that only direct requests (by the user) are redirected and not rewritten requests by your script/directives.
You can do this by either checking against THE_REQUEST
(which contains the first line of the request headers and does not change when the request is rewritten) OR the REDIRECT_STATUS
environment variable (which is empty on the initial request and set to "200" - as in 200 OK HTTP response - after the first successful rewrite).
For example:
# Remove "index.html" on direct requests only
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+/)?index\.html$ /$1 [R=301,L]