How to hide the .html extension with Apache mod_re

2019-01-01 11:22发布

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 mydomain.com/foo rather than mydomain.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 :-)

7条回答
骚的不知所云
2楼-- · 2019-01-01 11:34

The previous answers don't check if the requested path is a directory.

Here is the full rewrite condition which doesn't rewrite, if requested path is a directory (as stated by the original question):

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d          # is not directory
RewriteCond %{REQUEST_FILENAME}\.html -f     # is an existing html file
RewriteRule ^(.*)$ $1.html                   # rewrite index to index.html

To be SEO friendly and avoid double content, redirect the .html urls:

# Redirects domain.com/file.html to domain.com/file
RewriteCond %{REQUEST_FILENAME} !-d          # is not directory
RewriteCond %{REQUEST_FILENAME}\.html -f     # is an existing html file
RewriteCond %{REQUEST_URI} ^(.+)\.html$      # request URI ends with .html
RewriteRule (.*)\.html$ /$1 [R=301,L]        # redirect from index.html to index

If you need the same for scripts take a look here: How can I use .htaccess to hide .php URL extensions?

查看更多
柔情千种
3楼-- · 2019-01-01 11:36

To remove .html extension from .*.html requests, you can use the following script in root/.htaccess :

RewriteEngine On
RewriteBase /
#1) externally redirect "/file.html" to "/file"
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.html [NC]
RewriteRule ^ %1 [R=301,L]
#2) rewrite  "/file" back to "/file.html"
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.*?)/?$ $1.html [NC,L]
查看更多
呛了眼睛熬了心
4楼-- · 2019-01-01 11:38

The accepted solution do not works when the website is configured with a virtual host / document root.

There is the solution I used:

RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.html -f
RewriteRule !.*\.html$ %{REQUEST_FILENAME}.html [L]
查看更多
何处买醉
5楼-- · 2019-01-01 11:42

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',
查看更多
梦醉为红颜
6楼-- · 2019-01-01 11:48

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.

查看更多
零度萤火
7楼-- · 2019-01-01 11:50

Wow, I have seldom seen such an issue for which there exists so many "solutions" on the web, where people just throw up what "works for them" but for which few take time to read the documentation to figure out what it does. Many of the solutions given here don't work for virtual hosts, for example.

After much cross-referencing and reading, I want to contribute my own solution that "works for me". Hopefully it works for you, too. I didn't create it from scratch; I was inspired by all the other contributions (even though most of them did not "work for me" without modification).

RewriteEngine on

#if foo requested, return foo.html contents
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}\.html -f
RewriteRule ^(.*)$ $1.html [L]

#redirect foo.html to foo
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteRule ^(.+)\.html$ $1 [R,L]

The [R] flag by default does a temporary (302) redirect; if you want a permanent redirect, use R=301 in place of R.

查看更多
登录 后发表回答