Agrupando RewriteRule por RewriteCond con .htaccess

Apr 16 2020

Tengo una plantilla de página web que utilizo para ejecutar varias páginas de destino y htaccess se usa para dirigir la URL amigable al pageid dentro del código PHP. Todo funciona, pero en este momento tengo que agregar la línea de condición de reescritura antes de que cada regla o las redirecciones entren en conflicto. Puede ver esto en el pseudo código a continuación:

RewriteEngine On

RewriteCond for domain1
RewriteRule for page 1 on domain 1
RewriteCond for domain1
RewriteRule for page 2 on domain 1

RewriteCond for domain2
RewriteRule for page 1 on domain 2
RewriteCond for domain2
RewriteRule for page 2 on domain 2

Esto no se escala bien y si estuviera haciendo esto en otros idiomas, estaría agrupando las reglas de esta manera:

RewriteCond for domain1
{
    RewriteRule for page 1 on domain 1  
    RewriteRule for page 2 on domain 1
}

RewriteCond for domain2
{
    RewriteRule for page 1 on domain 2  
    RewriteRule for page 2 on domain 2
}

Si pudiera agrupar, haría que el archivo htaccess fuera mucho más manejable. ¿Hay alguna forma de agrupar las reglas? He intentado buscar una solución, pero cada ejemplo que encuentro analiza 1 redireccionamiento para 1 dominio. Mi otra idea es hacer un script htaccess en PHP / MySQL en el que ingreso mis datos, presiono un botón y escribe el archivo htaccess, sería complejo de leer pero estaría bien. Seguro que hay una solución sencilla. ¿Alguien puede ayudar por favor?

Respuestas

1 PlatformDating Apr 17 2020 at 09:54

Aquí está mi solución final que está funcionando en produciton:

RewriteEngine On

<If "%{HTTP_HOST} == 'domain1.com'">        

        #main pages
        RewriteRule /members/$ /index.php?pageid=2 [NC,L] RewriteRule /contact/$    /index.php?pageid=3 [NC,L]
        RewriteRule /affiliates/$ /index.php?pageid=4 [NC,L] #blog articles RewriteRule /welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]
</If>


<If "%{HTTP_HOST} == 'domain2.com'">        

        #main pages
        RewriteRule /about/$ /index.php?pageid=2 [NC,L] RewriteRule /press-kit/$    /index.php?pageid=3 [NC,L]
        RewriteRule /contact/$ /index.php?pageid=4 [NC,L] RewriteRule /affiliates/$   /index.php?pageid=5 [NC,L]

        #blog articles
        RewriteRule /welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]
</If>
MrWhite Sep 22 2020 at 16:28

Algunas alternativas al uso de <If>secciones, ya que no está exenta de advertencias .

  1. Omitir directivas cuando la condición coincide (o no)
  2. Prefije la URL (para que coincida) con el nombre de host
  3. .htaccessArchivo de configuración separado para cada host

( Aparte: ¿Realmente quieres una NCcoincidencia que no distinga entre mayúsculas y minúsculas ?)

1. Omitir directivas cuando la condición coincide (o no)

Puede omitir ( Smarcar) cualquier número de directivas cuando la regla (o condición) no coincida. es decir. Si omite las reglas siguientes cuando HTTP_HOSTno es domain1.com, las siguientes reglas solo se procesan cuando HTTP_HOSTes domain1.com.

Por ejemplo:

# Skip the following 4 rules when the host is not "domain1.com"
RewriteCond %{HTTP_HOST} !=domain1.com
RewriteRule ^ - [S=4]

# Only processed when the HTTP_HOST is equal to "domain1.com"

#main pages
RewriteRule ^members/$ /index.php?pageid=2 [NC,L] RewriteRule ^contact/$     /index.php?pageid=3 [NC,L]
RewriteRule ^affiliates/$ /index.php?pageid=4 [NC,L] #blog articles RewriteRule ^welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]

# --------------------------------------------------------------------

# Skip the following 5 rules when the host is not "domain2.com"
RewriteCond %{HTTP_HOST} !=domain2.com
RewriteRule ^ - [S=5]

# Only processed when the HTTP_HOST is equal to "domain2.com"

#main pages
RewriteRule ^about/$ /index.php?pageid=2 [NC,L] RewriteRule ^press-kit/$   /index.php?pageid=3 [NC,L]
RewriteRule ^contact/$ /index.php?pageid=4 [NC,L] RewriteRule ^affiliates/$  /index.php?pageid=5 [NC,L]

#blog articles
RewriteRule ^welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]

Aunque una advertencia obvia con este enfoque es que debe tener cuidado de actualizar la S=<number>marca al agregar o eliminar reglas.

Obviamente, puede revertir la lógica para tener lo que parece una tabla de contenido en la parte superior. Por ejemplo:

RewriteCond %{HTTP_HOST} =domain1.com
RewriteRule ^ - [S=2]
RewriteCond %{HTTP_HOST} =domain2.com
RewriteRule ^ - [S=5]
RewriteCond %{HTTP_HOST} =domain3.com
RewriteRule ^ - [S=9]

# --------------------------------------------------------------------
# domain1.com

#main pages
RewriteRule ^members/$     /index.php?pageid=2 [NC,L]
RewriteRule ^contact/$ /index.php?pageid=3 [NC,L] RewriteRule ^affiliates/$  /index.php?pageid=4 [NC,L]

#blog articles
RewriteRule ^welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L] # -------------------------------------------------------------------- # domain2.com #main pages RewriteRule ^about/$       /index.php?pageid=2 [NC,L]
RewriteRule ^press-kit/$ /index.php?pageid=3 [NC,L] RewriteRule ^contact/$     /index.php?pageid=4 [NC,L]
RewriteRule ^affiliates/$ /index.php?pageid=5 [NC,L] #blog articles RewriteRule ^welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]

Aunque las reglas de "omisión" son potencialmente más propensas a errores, ya que es posible que deba actualizar varias al agregar o eliminar reglas, dependiendo de dónde se encuentren estas reglas.

2. Prefije la URL (para que coincida) con el nombre de host

Alternativamente, podría (temporalmente) prefijar la ruta de URL con el nombre de host y hacer coincidir esto en las reglas que siguen. Esto evita la RewriteConddirectiva adicional en todas las reglas posteriores.

Por ejemplo:

# Prefix URL-path with HTTP_HOST if not already prefixed / No "L" flag
RewriteCond %{HTTP_HOST}@$1 !^([a-z.-]+)@\1 RewriteCond %{REQUEST_FILENAME} !-f RewriteRule (.*) %{HTTP_HOST}/$1

# --------------------------------------------------------------------
# domain1.com

#main pages
RewriteRule ^domain1\.com/members/$ /index.php?pageid=2 [NC,L] RewriteRule ^domain1\.com/contact/$     /index.php?pageid=3 [NC,L]
RewriteRule ^domain1\.com/affiliates/$ /index.php?pageid=4 [NC,L] #blog articles RewriteRule ^domain1\.com/welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]

# --------------------------------------------------------------------
# domain2.com

#main pages
RewriteRule ^domain2\.com/about/$ /index.php?pageid=2 [NC,L] RewriteRule ^domain2\.com/press-kit/$   /index.php?pageid=3 [NC,L]
RewriteRule ^domain2\.com/contact/$ /index.php?pageid=4 [NC,L] RewriteRule ^domain2\.com/affiliates/$  /index.php?pageid=5 [NC,L]

#blog articles
RewriteRule ^domain2\.com/welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]

Esto evita la RewriteConddirectiva adicional , sin embargo, requiere que usted prefija la ruta URL coincidente con el dominio en cada caso. Menos posibilidades de error que con el uso de la Sbandera como en el primer ejemplo anterior.

En el ejemplo anterior, el nombre de host permanece prefijado a la ruta URL al final de la solicitud para cualquier URL que no se asigne directamente a un archivo o no se reescriba /index.php?pageid=<number>. Esto resultaría en un 404.

Si desea eliminar específicamente el prefijo del nombre de host (tal vez esté utilizando la $_SERVER['REDIRECT_URL']variable en sus documentos de error, en lugar de $_SERVER['REQUEST_URI']), entonces podría hacerlo introduciendo una variable de entorno adicional (llamémosla FINISHED) y eliminar este prefijo al final.

Por ejemplo, modifique la primera regla para verificar la FINISHEDvar env (no existe inicialmente) e introduzca una nueva regla al final que elimine el prefijo y establezca la var env. Sin la FINISHEDvar env nos atascaremos en un bucle de reescritura de "URL desconocidas", ya que repetidamente prefijará y eliminará el nombre de host en la ruta de URL.

# Prefix URL-path with HTTP_HOST if not already prefixed and not FINISHED / No "L" flag
RewriteCond %{ENV:FINISHED} ^$
RewriteCond %{HTTP_HOST}@$1 !^([a-z.-]+)@\1 RewriteCond %{REQUEST_FILENAME} !-f RewriteRule (.*) %{HTTP_HOST}/$1

# :
# : Directives for each domain go here (as above)
# :

# Tidy up - remove the HTTP_HOST prefix and set FINISHED env var
RewriteCond %{HTTP_HOST}@$1 ^([a-z.-]+)@\1/(.*)
RewriteRule (.*) %2 [E=FINISHED:1,L]

3. .htaccessArchivo de configuración independiente para cada host

Otra alternativa que quizás sea más adecuada para esta situación particular de dominios separados y sitios web esencialmente separados (aunque quizás un motor "común" ) es tener .htaccessarchivos adicionales (separados) para cada sitio.

La forma exacta de configurar esto podría depender exactamente de cómo haya configurado su estructura de archivos, sin embargo, esto permite una mayor separación entre sus sitios e incluso compartir configuraciones entre dos o más sitios si lo desea. Puede tener recursos que se relacionen solo con el sitio al que se accede, pero es posible que ya tenga algo como esto.

Por ejemplo...

  • Aún tendría el .htaccessarchivo "maestro" en la raíz del documento (asumiendo que comparte un directorio raíz común para todos los dominios).
  • Cree un subdirectorio para cada host. p.ej. /domain1.comy dentro de cada subdirectorio, solo tiene un .htaccessarchivo para ese dominio.

Estructura de archivo:

/
    domain1.com/
        .htaccess
    domain2.com/
        .htaccess
    .htaccess
    index.php

/.htaccess

El .htaccessarchivo raíz luego enrutaría la solicitud al subdirectorio apropiado para el host solicitado.

RewriteEngine On

# If the request is already for index.php in the document root then DONE
RewriteRule ^index\.php$ - [L]

# Rewrite all requests that don't map to files to the appropriate domain subdirectory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) %{HTTP_HOST}/$1 [L]

/domain1.com/.htaccess

Luego, el .htaccessarchivo de cada dominio contiene solo las directivas para ese dominio y reescribe la solicitud al /index.phparchivo "común" en la raíz del documento para procesar la solicitud.

Las directivas de reescritura toman el mismo formato "normal" que se usó anteriormente.

# domain1.com

RewriteEngine On

# Optional - If this subdirectory is accessed directly then redirect back to the root
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.*) /$1 [R=301,L] #main pages RewriteRule ^members/$     /index.php?pageid=2 [NC,L]
RewriteRule ^contact/$ /index.php?pageid=3 [NC,L] RewriteRule ^affiliates/$  /index.php?pageid=4 [NC,L]

#blog articles
RewriteRule ^welcome-to-our-blog/$ /index.php?pageid=b0001 [NC,L]

De todos modos, alimento para el pensamiento. Algo de esto se reduce a cómo estructura su aplicación en lugar de estrictamente "Agrupar RewriteRule por RewriteCond". Si desea una explicación más detallada de cualquier "bit", dígalo.