How to hide the .html extension with Apache mod_rewrite

Viewed 78737

I have a small number of static sites where I simply want to hide the .html extension:

  • the URL /foo fetches the static file /foo.html
  • the browser still displays the URL /foo

The client can then send out bookmarks in the style example.com/foo rather than example.com/foo.html.

It sounds very simple, and I've used mod_rewrite happily before (say with WordPress or for redirects), but this is proving much harder to crack that I thought. Perhaps I'm missing something really obvious, but I can't find a solution anywhere and I've been at it all day!

We run our own server, so this can go wherever is the best place.

Addendum

The solution checked below worked fine. Then after running the site awhile I noticed two problems:

  1. all pages began to appear unstyled. I reloaded, cleared the cache, etc., but still no-style. I've had this trouble before, and can't locate the source.

  2. There's a directory AND an HTML file named 'gallery', so the /gallery link shows a directory listing instead of the HTML file. I should be able to sort that one, but further tips welcome :-)

8 Answers

Try this rule:

RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule !.*\.html$ %{REQUEST_FILENAME}.html [L]

This will rewrite all requests that can be mapped to an existing file when appending a .html.

  • the url /foo fetches the static file /foo.html
  • the browser still displays the url /foo

Apache can do this without mod_rewrite, see documentation:

Multiviews

The effect of MultiViews is as follows: if the server receives a request for /some/dir/foo, if /some/dir has MultiViews enabled, and /some/dir/foo does not exist, then the server reads the directory looking for files named foo.*, and effectively fakes up a type map which names all those files, assigning them the same media types and content-encodings it would have if the client had asked for one of them by name. It then chooses the best match to the client's requirements.

Source: http://httpd.apache.org/docs/current/content-negotiation.html

Here is an example which allows us to store the file on disk as:

foo.html.php

But in the browser, refer to it as

foo.html

To make this work for you, I think you would just need to modify it a bit to match your existing requests, and check for an actual file in place with the .html extension.

 # These are so we do not need the .php extension
 RewriteCond %{REQUEST_FILENAME} (\.xul|\.html|\.xhtml|\.xml)$',
 RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.php -f',
 RewriteRule ^(.*)$ $1.php',
Related