.HTACCESS está creando una cadena de redireccionamiento 301 innecesaria: ¿cómo eliminarla?

.HTACCESS está creando una cadena de redireccionamiento 301 innecesaria: ¿cómo eliminarla?

Mi pila:

  • LÁMPARA
  • Apache/2.4.41

Información de contexto:

Recientemente lancé un nuevo sitio web para un cliente. Durante el proceso de rediseño decidimos:

  • Cambiar a HTTPS en todo el sitio
  • Eliminar la extensión .php de las URL
  • Cambiar a un CMS

Ejemplo de URL ANTIGUA:
http://www.example.com/courses/acme-course.php

Ejemplo de NUEVA URL:
https://www.example.com/courses/acme-course

Mi problema:

Se produce un redireccionamiento 301 adicional innecesario cuando un usuario navega a una de las URL ANTIGUAS.

No entiendo por qué se crea el redireccionamiento 301 adicional y no envía al usuario directamente a la URL de destino correcta mediante un único redireccionamiento 301.

Observación interesante:

El redireccionamiento 301 adicional innecesario no ocurre cuando uso la URL ANTIGUA con HTTPS en lugar de HTTP.

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

El uso de la URL anterior realizará correctamente un único redireccionamiento 301 a la URL de destino correcta de:https://www.example.com/courses/acme-course

Aquí hay un ejemplo de una cadena de redireccionamiento 301:

URL de solicitud original:

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

1er redireccionamiento 301 (innecesario):

DE:

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

A:

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

2.º redireccionamiento 301 (URL de destino final correcta):

DE:

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

A:

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

Mi 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>

Respuesta1

Tienes dos problemas principales....

  1. Sus directivas están en el orden incorrecto en el .htaccessarchivo. Su HTTP a HTTPS y wwwsus redirecciones canónicas deben desaparecerantessu controlador frontal que enruta la URL a su CMS. De ahí la redirección externa incorrecta a /index.php?url=courses/acme-course.php: exponer la estructura interna de URL de su CMS.
  1. ¿ La eliminación de .phpen realidad no se realiza según sus .htaccessdirectivas? Supongo que esto lo debe hacer la lógica de su aplicación/CMS. En consecuencia, esto serásiempreresultará en una segunda redirección (ya que .htaccessse redirige a HTTPS en la misma ruta URL). Debe hacer algo como lo siguiente en la parte superior de su .htaccessarchivo para eliminar la .phpextensión.

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

ACTUALIZAR:Si reordeno las reglas/condiciones, ¿mi ubicación de Opciones +Seguir enlaces simbólicos permanece igual?

Realmente no importadóndese produce la Optionsdirectiva. Sin embargo, es lógico (desde el punto de vista de la legibilidad) tenerlo cerca de la parte superior. (Las directivas de Apache no necesariamente se ejecutan en el orden en que aparecen en el archivo de configuración, ya que cada módulo funciona de forma independiente).

Suponiendo que esté codificando su .htaccessarchivo a mano, entonces podrá ordenarlo...

  1. No hay necesidad de (múltiples) <IfModule mod_rewrite.c>envoltorios. ¿Es mod_rewrite opcional? ¿Su sitio se trasladará a varios servidores donde mod_rewrite no está habilitado?

  2. No hay necesidad de múltiples RewriteEnginedirectivas. Elúltimoejemplo en realidadganay controla todo el archivo.

    Múltiples <IfModule>bloques y RewriteEngineson típicos de sistemas que se editan automáticamente mediante código y/o están diseñados para funcionar sin editar en múltiples servidores.

Entonces, su .htaccessarchivo debería reescribirse así en este orden:

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 adicionales:

  • La PROTOvariable de entorno contiene cualquier protocolo que se solicite. Con el orden de las redirecciones, ahora siempre será HTTPS. El motivo de esta variable es que el CMS puede redirigir a HTTP si se accede a HTTP, o a HTTPS si se accede a HTTPS. Si está forzando HTTPS, entonces realmente no se aplica. (Aunque su aplicación aún puede utilizar esta var de entorno).

  • Rara vez deberías usar la NCbandera en una condición negada. Por eso lo eliminé de la condición !^www\.. Desea que se redirija cuando el host no comienza con www.todo en minúsculas. Con la NCbandera no se podrá redirigir WwW., aunque esto sería muy raro de todos modos.

  • Eliminé la verificación innecesaria de HTTPS en la redirección canónica www.

  • La PTbandera en la horma RewriteRuleno es obligatoria en .htaccess. Este .htaccesses el comportamiento predeterminado (pasar).

  • Deberá borrar el caché de su navegador antes de realizar la prueba, ya que es probable que el navegador haya almacenado en caché los redireccionamientos 301 erróneos. Por este motivo, es una buena idea realizar pruebas con redireccionamientos 302 (temporales).

información relacionada