[Sorry for the english speakers, today I’m not in the mood for translating this]
Uno de mis clientes me ha pedido redireccionar su blog (un wordpress situado en /blog) a su nueva web en Joomla, que incluye el blog en el propio CMS. Hasta ahora copiaban las noticias en ambos sitios: tanto en el blog wordpress (en /blog) como en el blog de joomla (en /). Cansado de copiar las noticias en ambos sitios, el cliente me solicita que redirecciones el blog a la web.
Primera aproximación
La primera idea es simplemente añadir una nueva regla al fichero .htaccess para que cualquier dirección que apunte a /blog pase directamente al dominio raiz. Esto se haría asi:
1
2
3
| # estas dos quitan /blog y redireccionan a hyips directamente
RewriteRule ^blog$ blog/ [R,NC,L]
RewriteRule ^blog/$ http://www.hyips.es/ [R,NC,L] |
# estas dos quitan /blog y redireccionan a hyips directamente
RewriteRule ^blog$ blog/ [R,NC,L]
RewriteRule ^blog/$ http://www.hyips.es/ [R,NC,L]
La primera línea redirecciona de blog a blog/. El símbolo ^ indica “cualquier cosa que empiece por… y esté en la carpeta actual”
La segunda línea redirecciona de blog/ al dominio principal.
A continuación aparece la lista de modificadores, entre corchetes:
* R : indica redirect, o lo que es lo mismo, fuerza una redirección. Si no se le pasa ningún código se devuelve una respuesta HTTP 302 (MOVED TEMPORARILY). También se puede especificar otro código de respuesta en el rango 300-400. Cuando uses este flag asegúrate de que el campo de sustitución es una URL válida. Si no lo es estarás redirigiendo a una localización inexistente!
* NC: indica no case, o lo que es lo mismo, hace el patrón insensible a las mayúsculas/minúsculas. Esto es, no hay diferencia entre ‘A-Z’ y ‘a-z’.
* L: indica al proceso de reescritura que pare en este punto y no aplique ninguna regla más de reescritura. Utiliza este flag para prevenir que la URL recién reescrita sea reescrita por reglas que se encuentren más adelante en el fichero .htaccess.
(Consulta el resto de flags en la guia oficial de Apache mod_rewrite)
Esto funcionaría para un blog de reciente creación, pero no es buena idea en el caso que nos ocupa, pues google tiene muchos de sus posts indexados.
Segunda aproximación a la solución
Para hacerlo bien, había que ver qué tenía Google indexado de su blog para hacer las redirecciones correspondientes a los artículos en la web.
Haciendo una simple búsqueda en google encontramos que tiene indexados algunos artículos. Por ejemplo:
http://www.hyips.es/blog/?p=560
Entonces buscamos el equivalente en Joomla! de ese artículo en el blog, y lo encontramos en:
http://www.hyips.es/gni-bestinv-otras-noticias
La redirección está clara: tenemos que redireccionar del primer link al segundo. Sería muy fácil construir una regla con RewriteRule, pero nos encontramos con el problema de escapar el signo de interrogación.
De hecho os animo a que probéis lo siguiente, para que veáis como NO funciona (pese a que hemos escapado correctamente el interrogante y el signo igual):
RewriteRule ^blog\/\?p\=560$ gni-bestinv-otras-noticias |
RewriteRule ^blog\/\?p\=560$ gni-bestinv-otras-noticias
Entendiendo RewriteCond
Si sabéis cómo funciona RewriteCond+RewriteRule lo siguiente no tiene ninguna gracia. Asumiré que no lo sabéis, por lo que os cuento alguna cosilla antes de dar la solución:
Cuando hacemos una petición HTTP a un servidor, Apache guarda ciertas variables. Vamos a suponer que hacemos una petición GET a un recurso del tipo:
http://www.midominio.com/carpeta1/index.php?variable1=valor1&var2=valor2
1. HTTP_HOST almacenará http://www.midominio.com
2. REQUEST_URI almacenará: /carpeta1/index.php
3. QUERY_STRING almacenará la parte de petición GET, osea: variable1=valor1&var2=valor2
También es necesario conocer cómo funciona RewriteCond:
La sintaxis de RewriteCond es como sigue:
RewriteCond STRING CONDITION |
RewriteCond STRING CONDITION
STRING debe ser una variable del servidor o una referencia anterior a alguna RewriteCond.
CONDITION puede ser una expresión regular, similar a una RewriteRule. Además puede tener variantes especiales sobre las expresiones regulares estándar.
Cómo encaja todo esto en nuestas RewriteRule? Si colocas un RewriteCond antes de RewriteRule, la RewriteRule sólo se procesará cuando la RewriteCond sea evaluada como true (esto es, si se cumple la CONDITION).
Y ya vale de teoría. Hagamos algo práctico para evitar que ciertas direcciones IP accedan a nuestro servidor.
1
2
| RewriteCond %{REMOTE_ADDR} 123.45.67.89
RewriteRule .* you-are-banned.html [R] |
RewriteCond %{REMOTE_ADDR} 123.45.67.89
RewriteRule .* you-are-banned.html [R]
Es un ejemplo bastante simple. Si la IP del visitante es 123.45.67.89, a éste se le muestra una página de baneo.
La solución final
Ahora ya sabemos lo necesario para seguir. La regla que consigue la redirección que deseamos es (sólo os pongo el ejemplo que traduce http://www.hyips.es/blog/?p=560 a http://www.hyips.es/gni-otras-noticias
1
2
3
4
5
6
7
8
9
10
11
12
| # Lo siguiente redirecciona cualquier cosa que tenga:
# - el REQUEST_URI=/blog/
# - en el QUERY_STRING p=560
# a /gni-otras-noticias
# Por ejemplo NO redireccionará http://www.hyips.es/articulos?p=560 a /gni-otras-noticias
# SÍ redireccionará http://www.hyips.es/blog/?p=560 a /gni-otras-noticias
RewriteCond %{REQUEST_URI} ^/blog/$
RewriteCond %{QUERY_STRING} ^p=560$
RewriteRule .* gni-bestinv-otras-noticias? [R,L]
# La última regla para que ya no se acceda jamás al blog...
RewriteRule ^blog$ http://www.hyips.es [R,L] |
# Lo siguiente redirecciona cualquier cosa que tenga:
# - el REQUEST_URI=/blog/
# - en el QUERY_STRING p=560
# a /gni-otras-noticias
# Por ejemplo NO redireccionará http://www.hyips.es/articulos?p=560 a /gni-otras-noticias
# SÍ redireccionará http://www.hyips.es/blog/?p=560 a /gni-otras-noticias
RewriteCond %{REQUEST_URI} ^/blog/$
RewriteCond %{QUERY_STRING} ^p=560$
RewriteRule .* gni-bestinv-otras-noticias? [R,L]
# La última regla para que ya no se acceda jamás al blog...
RewriteRule ^blog$ http://www.hyips.es [R,L]
RewriteCond, RewriteRule, QUERY_STRING y variables
Una vez entendido el ejemplo os propongo otro, todavía más útil. La página de mi cliente tenía indexadas en google muchísimas páginas asociadas a un tag, es decir, en el formato http://www.tusitio.com/blog/?tag=XXX Yo quería que esas tags se redireccionaran al buscador de la web en Joomla! (URLdel tipo: http://www.tusitio.com/Buscada?ordering=&searchphrase=all&searchword=XXX). Para ello construí la siguiente regla:
1
2
3
4
5
6
7
| # Regla para pasar de:
# www.tusitio.com/blog/?tag=perfectmoney
# a
# http://www.tusitio.com/Buscada?ordering=&searchphrase=all&searchword=perfectmoney
RewriteCond %{REQUEST_URI} ^/blog/$
RewriteCond %{QUERY_STRING} ^tag=(.*)$
RewriteRule ^blog/(.*)$ Buscada?ordering=&searchphrase=all&searchword=%1 [R,L] |
# Regla para pasar de:
# www.tusitio.com/blog/?tag=perfectmoney
# a
# http://www.tusitio.com/Buscada?ordering=&searchphrase=all&searchword=perfectmoney
RewriteCond %{REQUEST_URI} ^/blog/$
RewriteCond %{QUERY_STRING} ^tag=(.*)$
RewriteRule ^blog/(.*)$ Buscada?ordering=&searchphrase=all&searchword=%1 [R,L]
La línea 5 es vieja conocida, no la comento.
En la línea 6 encontramos un elemento nuevo con respecto a las anteriores reglas que expliqué; los paréntesis. Gracias a ellos se almacena en una variable el valor que sigue a la parte de la URL ?tag=, osea XXX (según el ejemplo que he puesto unas líneas más arriba).
Después sólo nos queda indicar en la RewriteRule que la búsqueda se haga a esa variable (accesible con %1). Es importante fijarse en cómo se accede de distinta forma a las variables generadas por la propiar RewriteRule ($1) de las generadas por las RewriteCond (%1).
En nuestro caso podríamos acceder al valor completo que sigue a /blog/ (sería algo del tipo ?tag=XXX) con $1 o sólo al valor del tag con %1.
¿Queda claro? Espero que la explicación os haya servido para algo…