
Eu tenho um site Wordpress. Quero redirecionar URLs .php para aqueles sem o sufixo .php. O .htaccess é o seguinte:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)\.php$ "$1" [R=301,L,NC]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Mas quando eu visitohttps://www.example.com/somepage.php, a página não poderá ser exibida. O seguinte erro é mostrado no navegador:
The page isn’t redirecting properly
An error occurred during a connection to www.example.com.
This problem can sometimes be caused by disabling or refusing to accept cookies.
E o URL na barra de endereço se torna https://www.example.com/index.
Se eu alterar a regra de reescrita como:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)\.html$ "$1" [R=301,L,NC]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
E visitehttps://www.example.com/somepage.html, ele é redirecionado com sucesso parahttps://www.example.com/somepagee a página da web é exibida normalmente. Por que?
Responder1
Porque, como o redirecionamento éincondicional, você acaba redirecionando novamentedepoisa URL foi reescrita para index.php
(o front-controller do WordPress).
Quando você solicita /somepage.php
:
- Você é redirecionado para
/somepage
(pela primeira regra). A resposta de redirecionamento é enviada de volta ao cliente. - Na segunda solicitação,
/somepage
é reescrito internamente/index.php
pela última regra. O mecanismo de reescrita então reinicia (em umdiretóriocontexto)... /index.php
é redirecionado para/index
(pela primeira regra). A resposta de redirecionamento é enviada de volta ao cliente.- Na terceira solicitação
/index
é reescrito internamente/index.php
pela última reescrita. O mecanismo de reescrita então recomeça... - Vá para 3 (preso em um loop de redirecionamento sem fim).
Em umdiretóriocontext (como .htaccess
) o mecanismo de reescrita não faz simplesmente uma única passagem pelo script. Ele faz um loop até que o URL passe inalterado. (A menos que você use o END
sinalizador no Apache 2.4 ou ocorra um redirecionamento 3xx externo.)
Alterar para remove .html
funciona bem porque você está reescrevendo para /index.php
, que não termina em .html
, portanto a diretiva de redirecionamento (que remove .html
) não corresponde.
Para resolver isso, você precisa evitar o redirecionamento da solicitação reescrita. Você pode fazer isso:
usando o
END
sinalizador (Apache 2.4+) na última reescrita, em vez deL
evitar quaisquer loops adicionais do mecanismo de reescrita. Embora você deva evitar alterar as diretivas padrão do WordPress (veja abaixo), esta pode não ser a opção preferida. Isso também não funciona no Apache 2.2.Ou verifique a
.php
extensão naTHE_REQUEST
variável do servidor (que contém a linha inicial dos cabeçalhos da solicitação HTTP e não muda quando a solicitação é reescrita). Por exemplo:# Remove ".php" extension on "direct" (not rewritten) requests only RewriteCond %{THE_REQUEST} [A-Z]{3,7}\s/[^?]+\.php(?:\?|\s|$) [NC] RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
Ou verifique a
REDIRECT_STATUS
variável de ambiente, que está vazia na solicitação inicial e definida como 200 (como no status HTTP 200 OK) na primeira reescrita bem-sucedida (isso é mais simples do que o regex bastante mais complexo acima). Por exemplo:# Remove ".php" extension on "direct" (not rewritten) requests only RewriteCond %{ENV:REDIRECT_STATUS} ^$ RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
Porém, você não deve editar o código dentro da # BEGIN WordPress
seção, pois o próprio WordPress tenta manter isso e pode sobrescrever esse código posteriormente. Esta regra precisa desapareceranteso # BEGIN WordPress
marcador de comentário. Você não precisa repetir a RewriteEngine On
diretiva que aparece posteriormente no arquivo (na seção WordPress).
Você precisará limpar o cache do navegador antes de testar, pois o redirecionamento incorreto (permanente) provavelmente terá sido armazenado em cache pelo navegador. Teste primeiro com redirecionamentos 301 (temporários) para evitar problemas de cache.
No entanto, isso por si só não permite acessar .php
arquivos sem a .php
extensão. Como o URL sem extensão precisará ser reescrito internamente no .php
arquivo.