.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 para 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 URL NUEVA:
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 se envía al usuario directamente a la URL de destino correcta mediante un solo redireccionamiento 301.
Observación interesante:
El redireccionamiento 301 adicional innecesario no ocurre cuando utilizo la URL ANTIGUA con HTTPS en lugar de HTTP.
Ejemplo:
https://www.example.com/courses/acme-course.php
_
El uso de la URL anterior hará 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
Primer redireccionamiento 301 (innecesario):
DESDE:
http://www.example.com/courses/acme-course.php
A:
https://www.example.com/index.php?url=courses/acme-course.php
Segundo redireccionamiento 301 (URL de destino final correcta):
DESDE:
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>
Respuestas
Tienes dos problemas principales ...
- Sus directivas están en el orden incorrecto en el
.htaccess
archivo. Su HTTP a HTTPS y laswww
redirecciones canónicas deben ir antes que su controlador frontal que enruta la URL a su CMS. De ahí el redireccionamiento externo incorrecto para/index.php?url=courses/acme-course.php
exponer la estructura interna de la URL de su CMS.
¿La eliminación de en
.php
realidad no está siendo realizada por sus.htaccess
directivas? Supongo que esto debe ser realizado por su aplicación / lógica CMS. En consecuencia, esto siempre resultará en una segunda redirección (ya que.htaccess
se redirige a HTTPS en la misma ruta de URL). Debe hacer algo como lo siguiente en la parte superior de su.htaccess
archivo para eliminar la.php
extensión.RewriteRule (.+)\.php$ https://www.example.com/$1 [R=301,L]
ACTUALIZACIÓN: Si vuelvo a ordenar las reglas / condiciones, ¿mi ubicación de Options + FollowSymlinks permanece igual?
Realmente no importa dóndeOptions
ocurra la directiva. Sin embargo, es lógico (desde el punto de vista de la legibilidad) tenerlo cerca de la parte superior. (Las directivas de Apache no se ejecutan necesariamente 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 manualmente su .htaccess
archivo, entonces se puede ordenar ...
No hay necesidad de
<IfModule mod_rewrite.c>
envoltorios (múltiples) . ¿Mod_rewrite es opcional? ¿Su sitio se trasladará a varios servidores donde mod_rewrite no está habilitado?No hay necesidad de varias
RewriteEngine
directivas. La última instancia gana y controla todo el archivo.Múltiples
<IfModule>
bloques yRewriteEngine
son típicos de sistemas que se editan automáticamente por código y / o están diseñados para funcionar sin editar en múltiples servidores.
Entonces, su .htaccess
archivo debe 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
PROTO
variable 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 HTTPS si se accede a HTTPS. Si está forzando HTTPS, entonces realmente no se aplica. (Aunque su aplicación aún puede usar esta var env).Rara vez debería usar la
NC
bandera en una condición negada. De ahí por qué lo eliminé de la condición!^www\.
. Desea que se redirija cuando el host no comience conwww.
: todo en minúsculas. Con laNC
bandera, no se redireccionaráWwW.
, aunque esto sería muy raro de todos modos.Eliminé la verificación innecesaria de HTTPS en el redireccionamiento canónico de www.
La
PT
bandera de la hormaRewriteRule
no es obligatoria en.htaccess
. En.htaccess
este es el comportamiento predeterminado (paso a través).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. Es una buena idea probar con redireccionamientos 302 (temporales) por este motivo.