Я наконец понял, почему это не сработало.
В исходной версии структура файла выглядела следующим образом:
- перенаправить на HTTPS и не WWW (и прекратить обработку последующих правил - флаг
[L]
) - перенаправить
/foo/bar.html/
на /foo/bar.html
(и остановить, как указано выше) - переписать
/foo/bar
на /foo/bar.html
(внутренне) - перенаправить
/foo/bar.html
на /foo/bar
(и остановиться, как в 1. и 2.)
Итак, когда запрашивалось /foo/bar.html
, оно соответствовало правилу 4. и перенаправлялось на /foo/bar
. Затем перезапись была начата снова, так как был сделан новый запрос к /foo/bar
, и он был переписан как /foo/bar.html
(3.). Затем он перешел к следующему правилу - 4. (снова) - и был перенаправлен обратно на /foo/bar
, поэтому был сделан еще один запрос, и перезапись началась снова, но затем он был заблокирован сервером из-за циклов.
Есть два способа это исправить. Первый способ - изменить порядок двух последних операций:
- перенаправление на HTTPS и не WWW (и прекратить обработку последующих правил - флаг
[L]
) - redirect
/foo/bar.html/
до /foo/bar.html
(и остановка) - перенаправление
/foo/bar.html
на /foo/bar
(и остановка) - перезапись
/foo/bar
на /foo/bar.html
(внутренне)
В этом случае запрос на /foo/bar.html
будет перенаправлен на /foo/bar
(3.), как и раньше, а в новом запросе он будет перезаписан как /foo/bar.html
внутри (4.), и все. Он не будет перенаправлен обратно на /foo/bar
, потому что после 4. нет перенаправлений или других правил.
Второй способ - добавить флаг [L]
к правилу, переписав /foo/bar
в /foo/bar.html
что даст тот же эффект, что и изменение порядка. Перезапись будет go как:
- перенаправление на HTTPS и не WWW (и остановка)
- перенаправление
/foo/bar.html/
на /foo/bar.html
(и остановка) - переписать
/foo/bar
в /foo/bar.html
(внутренне) (и остановить) - перенаправить
/foo/bar.html
в /foo/bar
(и остановить)
Я go с первым способом (переупорядочением), поскольку это позволит мне добавить другие правила после правила "/ foo / bar в /foo/bar.html".
Финал (как сейчас ... ) .htaccess
файл:
RewriteEngine On
# force HTTPS everywhere and strip WWW
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
# rewrite example.com/xxx/ to example.com/xxx
# if example.com/xxx/ is not directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ $1 [R=301,L]
# redirect from xxx.html to xxx
# if xxx.html is not directory AND xxx.html file exists
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.+)\.html$ $1 [R=301,L]
# rewrite example.com/xxx to example.com/xxx.html
# if example.com/xxx is not directory AND example.com/xxx.html file exists
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^ %{REQUEST_FILENAME}.html