Как скрыть расширение .html с помощью Apache mod_rewrite

У меня есть небольшое количество статических сайтов, где я просто хочу скрыть расширение .html:

  • url /foo извлекает статический файл /foo.html
  • браузер по-прежнему отображает URL /foo

Затем клиент может отправить закладки в стиле mydomain.com/foo, а не mydomain.com/foo.html.

Звучит очень просто, и я использовал mod_rewrite счастливо раньше (скажем, с WordPress или для перенаправления), но это гораздо труднее взломать, что я думал. Возможно, мне не хватает чего-то действительно очевидного, но я не могу найти решение нигде, и я был на нем весь день!

Мы запускаем собственный сервер, так что это может происходить там, где это лучшее место.

Добавление

Решение, указанное ниже, отлично работает. Затем после запуска сайта я заметил две проблемы:

  • все страницы стали казаться неустановленными. Я перезагрузил, очистил кеш и т.д., Но все еще не-стиль. Раньше у меня была эта проблема, и я не могу найти источник.

  • Здесь есть каталог AND html файл с именем 'gallery', поэтому ссылка /gallery показывает список каталогов вместо html файла. Я должен уметь сортировать это, но дальнейшие советы приветствуются: -)

Ответ 1

Попробуйте следующее правило:

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

Это приведет к перезаписи всех запросов, которые могут быть сопоставлены с существующим файлом при добавлении .html.

Ответ 2

Предыдущие ответы не проверяют, является ли запрошенный путь каталогом.

Вот полное условие перезаписи, которое не переписывается, если запрошенный путь является каталогом (как указано в исходном вопросе):

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

Чтобы быть дружественным к SEO и избегать двойного контента, перенаправьте URL-адрес .html:

# 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

Если вам нужно то же самое для скриптов, посмотрите здесь: Как я могу использовать .htaccess, чтобы скрыть расширения URL-адресов? php?

Ответ 3

Принятое решение не работает, если веб-сайт настроен с помощью виртуального хоста/документа root.

Есть решение, которое я использовал:

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

Ответ 4

Посмотрите на этот пост http://alexcican.com/post/how-to-remove-php-html-htm-extensions-with-htaccess/ Я еще не пробовал, но демонстрация кажется довольно убедительной.

Options -MultiViews 
RewriteEngine On 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule ^([^\.]+)$ $1.php [NC,L]

Ответ 5

Чтобы удалить расширение .html из .*.html запросов, вы можете использовать следующий script в 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]

Ответ 6

Вот пример, который позволяет нам хранить файл на диске как:

foo.html.php

Но в браузере обратитесь к нему как

foo.html

Чтобы сделать это для вас, я думаю, вам просто нужно немного изменить его, чтобы соответствовать вашим существующим запросам, и проверить фактический файл на месте с расширением .html.

 # 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',

Ответ 7

Ничего себе, я редко видел такую ​​проблему, для которой существует так много "решений" в Интернете, где люди просто бросают то, что "работает на них", но для чего мало времени, чтобы прочитать документацию, чтобы выяснить, что оно делает. Многие из приведенных здесь решений не работают, например, для виртуальных хостов.

После много перекрестных ссылок и чтения я хочу внести свое собственное решение, которое "работает для меня". Надеюсь, это сработает и для вас. Я не создал его с нуля; Я был вдохновлен всеми другими вкладами (хотя большинство из них "не работало для меня" без изменений).

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]

По умолчанию флаг [R] выполняет временную (302) переадресацию; если вы хотите постоянную переадресацию, используйте R=301 вместо R.