.HTACCESS está criando uma cadeia de redirecionamento 301 desnecessária - como remover?

.HTACCESS está criando uma cadeia de redirecionamento 301 desnecessária - como remover?

Minha pilha:

  • LÂMPADA
  • Apache/2.4.41

Informações básicas:

Recentemente lancei um novo site para um cliente. Durante o processo de redesenho, decidimos:

  • Mudar para HTTPS em todo o site
  • Remova a extensão .php dos URLs
  • Mudar para um CMS

Exemplo de URL ANTIGO:
http://www.example.com/courses/acme-course.php

Exemplo de NOVO URL:
https://www.example.com/courses/acme-course

Meu problema:

Um redirecionamento 301 adicional desnecessário está ocorrendo quando um usuário navega para um dos URLs ANTIGOS.

Não entendo por que o redirecionamento 301 adicional está sendo criado e não envia o usuário diretamente para o URL de destino correto usando um único redirecionamento 301.

Observação interessante:

O redirecionamento 301 adicional desnecessário não ocorre quando uso o URL ANTIGO com HTTPS em vez de HTTP.

Exemplo:
https://www.example.com/courses/acme-course.php _

Usar o URL acima fará corretamente um único redirecionamento 301 para o URL de destino correto de:https://www.example.com/courses/acme-course

Aqui está um exemplo de cadeia de redirecionamento 301:

URL de solicitação original:

http://www.example.com/courses/acme-course.php

1º Redirecionamento 301 (desnecessário):

DE:

http://www.example.com/courses/acme-course.php

PARA:

https://www.example.com/index.php?url=courses/acme-course.php

2º Redirecionamento 301 (URL de destino final correto):

DE:

https://www.example.com/index.php?url=courses/acme-course.php

PARA:

https://www.example.com/courses/acme-course

Meu código .htaccess:

# (1) General Settings
<IfModule mod_rewrite.c>
    Options +FollowSymLinks
    RewriteEngine On
</IfModule>

# (2) Force WWW
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=off
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteCond %{SERVER_ADDR} !=127.0.0.1
    RewriteCond %{SERVER_ADDR} !=::1
    RewriteRule ^ %{ENV:PROTO}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

# (3) Force HTTPS
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=on
    RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>

# (4) URL Routing for CMS
<IfModule mod_rewrite.c>

    RewriteCond %{HTTPS} =on
    RewriteRule ^ - [env=proto:https]
    RewriteCond %{HTTPS} !=on
    RewriteRule ^ - [env=proto:http]

    ## Check if file/directory exists
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    ## Route all other URLs to index.php/URL
    RewriteRule ^(.*)$ index.php?url=$1 [PT,L,QSA]
</IfModule>

Responder1

Você tem dois problemas principais....

  1. Suas diretivas estão na ordem errada no .htaccessarquivo. Seu HTTP para HTTPS e wwwredirecionamentos canônicos precisam serantesseu front-controller que encaminha o URL para o seu CMS. Daí o redirecionamento externo incorreto para /index.php?url=courses/acme-course.php- expondo sua estrutura interna de URL do CMS.
  1. A remoção de .phpnão está realmente sendo realizada pelas suas .htaccessdiretivas?! Presumo que isso deva estar sendo feito pela lógica do seu aplicativo/CMS. Consequentemente, isto irásempreresultará em um segundo redirecionamento (já que .htaccessestá redirecionando para HTTPS no mesmo caminho de URL). Você precisa fazer algo como o seguinte na parte superior do .htaccessarquivo para remover a .phpextensão.

    RewriteRule (.+)\.php$ https://www.example.com/$1 [R=301,L]
    

ATUALIZAR:Se eu reordenar as regras/condições, meu posicionamento de Options +FollowSymlinks permanecerá o mesmo?

Isso realmente não importaondea Optionsdiretiva ocorre. No entanto, é lógico (do ponto de vista da legibilidade) colocá-lo próximo ao topo. (As diretivas do Apache não são necessariamente executadas na ordem em que aparecem no arquivo de configuração, pois cada módulo funciona de forma independente.)

Supondo que você esteja codificando seu .htaccessarquivo manualmente, ele pode ser arrumado ...

  1. Não há necessidade de (vários) <IfModule mod_rewrite.c>wrappers. O mod_rewrite é opcional? O seu site foi portado para vários servidores onde o mod_rewrite não está habilitado?

  2. Não há necessidade de múltiplas RewriteEnginediretivas. Odurarinstância na verdadevencee controla o arquivo inteiro.

    <IfModule>Blocos múltiplos e RewriteEnginesão típicos de sistemas que são editados automaticamente por código e/ou projetados para funcionar sem edição em vários servidores.

Portanto, seu .htaccessarquivo deve ser reescrito assim, nesta ordem:

Options +FollowSymlinks

# Enable the rewrite engine...   
RewriteEngine On

# ----------------------------------------------------------------------
# | Forcing `https://`                                                       |
# ----------------------------------------------------------------------

# Redirect to HTTPS on the "same host" (requirement for HSTS)
RewriteCond %{HTTPS} !=on
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]


# ----------------------------------------------------------------------
# | Forcing `www`                                                          |
# ----------------------------------------------------------------------

RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{SERVER_ADDR} !=127.0.0.1
RewriteCond %{SERVER_ADDR} !=::1
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# ----------------------------------------------------------------------
# | URL Routing for CMS                                              |
# ----------------------------------------------------------------------

# (3)
RewriteCond %{HTTPS} =on
RewriteRule ^ - [env=proto:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^ - [env=proto:http]
   
# (4) - Check if physical file exists
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d  

# (5) - Rewrite all other URLs to index.php/URL
RewriteRule (.*) index.php?url=$1 [L,QSA]

Notas Adicionais:

  • A PROTOvariável de ambiente contém qualquer protocolo que esteja sendo solicitado. Com a ordem dos redirecionamentos agora será sempre HTTPS. A razão para essa variável é que o CMS pode redirecionar para HTTP se HTTP for acessado ou HTTPS se HTTPS for acessado. Se você está forçando HTTPS, isso realmente não se aplica. (Embora este env var ainda possa ser usado pelo seu aplicativo.)

  • Raramente você deve usar o NCsinalizador em uma condição negada. Daí porque eu o removi da condição !^www\.. Você deseja que ele redirecione quando o host não iniciar com www.- tudo em letras minúsculas. Com o NCsinalizador, não será possível redirecionarWwW. - embora isso seja muito raro de qualquer maneira.

  • Removi a verificação desnecessária de HTTPS no redirecionamento canônico www.

  • O PTsinalizador no último RewriteRulenão é obrigatório no .htaccess. Em.htaccess é o comportamento padrão (passagem).

  • Você precisará limpar o cache do navegador antes de testar, pois os redirecionamentos 301 errados provavelmente terão sido armazenados em cache pelo navegador. É uma boa ideia testar redirecionamentos 302 (temporários) por esse motivo.

informação relacionada