Por que o redirecionamento em .htaccess não funciona?

Por que o redirecionamento em .htaccess não funciona?

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:

  1. Você é redirecionado para /somepage(pela primeira regra). A resposta de redirecionamento é enviada de volta ao cliente.
  2. Na segunda solicitação, /somepageé reescrito internamente /index.phppela última regra. O mecanismo de reescrita então reinicia (em umdiretóriocontexto)...
  3. /index.phpé redirecionado para /index(pela primeira regra). A resposta de redirecionamento é enviada de volta ao cliente.
  4. Na terceira solicitação /indexé reescrito internamente /index.phppela última reescrita. O mecanismo de reescrita então recomeça...
  5. 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 ENDsinalizador no Apache 2.4 ou ocorra um redirecionamento 3xx externo.)

Alterar para remove .htmlfunciona 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 ENDsinalizador (Apache 2.4+) na última reescrita, em vez de Levitar 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 .phpextensão na THE_REQUESTvariá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_STATUSvariá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 WordPressseção, pois o próprio WordPress tenta manter isso e pode sobrescrever esse código posteriormente. Esta regra precisa desapareceranteso # BEGIN WordPressmarcador de comentário. Você não precisa repetir a RewriteEngine Ondiretiva 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 .phparquivos sem a .phpextensão. Como o URL sem extensão precisará ser reescrito internamente no .phparquivo.

informação relacionada