Você não precisa definir explicitamente uma variável de ambiente (por exemplo, LOOP
) para evitar o loop de redirecionamento. Você pode usar o próprio REDIRECT_STATUS
do Apache para esse propósito. REDIRECT_STATUS
não é definido quando a solicitação é processada pela primeira vez e definida como 200
(como em 200 OK) após a primeira reescrita bem-sucedida.
Eu também organizo suas diretivas para que os redirecionamentos externos sejam os primeiros, antes da reescrita interna, pois eles sempre precisarão ser executados primeiro.
Para que isso funcione em qualquer diretório, você pode definir um padrão regex para o nome do diretório (ou melhor, o caminho completo da URL se estiver lidando com qualquer nível de subdiretório) e incluir uma condição que verifique se a solicitação é mapeada para um diretório. Por exemplo, tente algo como o seguinte:
DirectorySlash Off
RewriteEngine on
# Strip trailing slash on directory
# (The root always has a slash, but the browser doesn't show it)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.+)/$ /$1 [R,L]
# Strip trailing "/index.html" (including root)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.*?)/?index\.html$ /$1 [R,L]
# Rewrite directory request to directory index
# (Any directory will already have had the trailing slash and "index.html" removed)
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.*) /$1/index.html [L]
(.*?)/?index\.html$
- Ao tornar o grupo capturado não-ganancioso (ou seja, (.*?)
), ele não capturará a barra opcional que segue. Se isso acontecesse, copiaria potencialmente a barra final para a substituição e resultaria em um redirecionamento adicional (já que a primeira regra a removeria mais tarde). E fazendo tudo antes do index.html
opcional, ele também funcionará para a raiz do documento.
Altere os redirecionamentos temporários (302) para permanente (301) somente quando tiver certeza de que está funcionando OK. Os 301s são armazenados em cache pelo navegador por padrão, o que pode tornar o teste problemático.