Crear redirecciones con Nginx

Las redirecciones de servidor son importantes para redirigir el tráfico entre http y https o para redirigir el dominio a su prefijo con www. Los administradores de los sitios web las usan para actualizar las URL de sus artículos sin perder el linkbuilding y el posicionamiento.

Nginx es muy flexible y tiene varias directivas parar crear redirecciones. return es eficiente y fácil de usar. Con rewrite es posible crear redirecciones usando expresiones regulares y para mantener un largo listado de redirecciones usamos map.

En este artículo te explico como funcionan y las diferencias entre return, rewrite y map.

1. Redirección simple

La directiva return es la forma más sencilla de hacer una redirección 301 o 302 con Nginx.

Este es su modo de empleo:

return (301 | 302 | 303 | 307) URL;

Tiene dos parámetros:

  • Código de respuesta 301, 302, 303 ó 307 - Es la cabecera HTTP que se envía como respuesta desde el servidor.
    La redirección 301 indica al navegador que es una redirección permanente. De este modo, el navegador recordará la configuración para las sucesivas visitas y realizará la redirección internamente reduciendo el número de peticiones al servidor.
    Utilizamos el código 302 para crear redirecciones temporales.
  • URL - Indica la nueva dirección web.

Hay que tener en cuenta que solo es posible usar la directiva return dentro de un bloque server o un bloque location. Como en este ejemplo, donde todo el tráfico http del dominio example.com es redirigido hacia example.org con protocolo seguro (https).

# Redirigir example.com y www.example.com a example.org con un 301
server {
    listen 80;
    listen [::]:80;
    hostname example.com www.example.com;
    # ...
    return 301 https://example.org$request_uri;
}

La directiva return es apropiada para redirigir el tráfico de http a https o al revés y para redirigir entre el dominio con www y sin www. A continuación encontrarás ejemplos de configuración para cada caso:

Ejemplo 1. Forzar el uso de SSL/TLS

Esta configuración sirve para redirigir todo el tráfico http del servidor hacia https:

# Redirigir todo el tráfico http a https
server {
	listen 80 default_server;
	listen [::]:80 default_server;
	server_name _;
	return 301 https://$host$request_uri;
}

Y esta es la configuración para redirigir de http a https pero solo para uno de los dominios que tiene configurado el servidor:

# Redirigir http a https para example.org y www.example.org
server {
	listen 80 default_server;
	listen [::]:80 default_server;
	server_name example.org www.example.org;
	return 301 https://$server_name$request_uri;
}

Ejemplo 2. Redirección canónica

Cuando un servidor tiene un único sitio con varios alias es importante hacer una redirección desde los alias al dominio principal para evitar sitios con contenido duplicado.

Si el hostname del servidor coincide con el nombre del dominio principal es posible crear la redirección del siguiente modo:

# Redirigir alias al hostname canónico
server_name example.org www.example.org example.com www.example.com _;
if ( $host != $server_name ) {
    return 301 $scheme://$server_name$request_uri;
}

Ejemplo 3. Redirección entre el dominio con y sin www

Esta configuración sirve para redirigir todas las peticiones de cualquier dominio hacia sí mismo pero con www.

# Redirigir a www
if ( $host !~ ^www\. ) {
    return 301 $scheme://www.$host$request_uri;
}

Y la configuración contraria que redirige cualquier petición que llegue a un dominio con www al mismo dominio sin el prefijo:

# ...
# Redirigir a sin www
if ( $host ~ ^www\.(?<domain>.+)$ ) {
    return 301 $scheme://$domain$request_uri;
}

2. Redirección con patrones

Con Nginx es posible hacer redirecciones basadas en variables y expresiones regulares utilizando la directiva rewrite.

Con una expresión regular capturamos una parte de la URL original para luego usarla en la URL de destino. De este modo, es posible hacer migraciones SEO sin perder el posicionamiento ni los enlaces de otros sitios (linkbuilding).

Al igual que la directiva return, rewrite estará siempre dentro de un bloque server o uno location. Este es su modo de empleo:

rewrite regex URL [flag];
  • regex - Es el expresión regular.
  • URL - Indica la nueva dirección web y podemos usar variables de captura.
  • flag - Es opcional y puede tomar uno de estos valores: permanent, redirect, last o break.
    permanent y redirect añaden un código de respuesta 301 y 302 respectivamente.
    Las etiquetas last y break finalizan la ejecución de las instrucciones del bloque donde se encuentran. La diferencia entre ambas es que break retorna inmediatamente una respuesta de servidor, mientras que last buscará coincidencias con el resto de bloques location para aplicar nuevas instrucciones.

Aquí puedes ver un ejemplo:

rewrite ^/foo/(bar)/(.*)$ https://$server_name/$1/$2 permanent;

Diferencias entre return y rewrite

A diferencia de la directiva return, rewrite no finaliza el procesamiento de la petición. De este modo, Nginx continúa procesando el resto de instrucciones del bloque a menos que exista una directiva return.

Otra diferencia es que rewrite solo devuelve un código de respuesta 301 (etiqueta permanent) o 302 (etiqueta redirect). Para devolver otros códigos hay que añadir una directiva return en el mismo bloque.

A la hora de elegir entre ambas, siempre que sea posible, usa return ya que la directiva rewrite consume más tiempo en interpretar la expresión regular.

3. Mapa de redirecciones

Cuando hay que hacer muchas redirecciones es poco práctico escribir cada instrucción return o rewrite dentro del bloque server o location. Como en este ejemplo:

location / {
	rewrite url-anterior1 url-nueva1 permanent;
	rewrite url-anterior2 url-nueva2 permanent;
	rewrite url-anterior4 url-nueva3 permanent;
	# ...
	rewrite url-anterior1000 url-nueva1000 permanent;
}

Con Nginx es posible organizar las redirecciones en un archivo de configuración independiente usando la directiva map. Para entender como funciona esta técnica es necesario conocer como funciona map:

map cadena $variable { 
	clave-1 valor-1;
	clave-2 valor-2;
	# ...
 }

map crea una nueva variable llamada $variable cuyo valor es el resultado de buscar el parámetro cadena en un conjunto de datos clave-valor dados como último parámetro.

Así, con map creamos un conjunto de datos formado por URLs a las que corresponde una redirección. Vamos a ver paso a paso un ejemplo de configuración completo:

Paso 1. Crear el mapa de redirecciones

Dentro del directorio de configuración de Nginx, crearemos un nuevo fichero llamado mapa-de-redirecciones.conf:

map $request_uri $nueva_uri {
    /acerca-de.html      /acerca-de;
    /clientes.html       /clientes;
    
    # Cualquier url que termine en producto.html
    ~producto\.html?$    /productos;
    
    # Igual que el anterior sin distinguir mayúsculas y minúsculas
    ~*producto\.html?$   /productos;

    # expresión regular con captura de elementos
    # convierte producto-1234.html en /productos/item-1234/descripcion
    ~producto-(?<sku>\d+)\.html   /productos/item-$sku/descripcion;
}

Notas:

  • request_uri es una variable de Nginx que contiene la URI original y completa de la petición.
    Es posible crear mapas en base a otras variables de Nginx como: $scheme, $host, $server_name o $request_filename.
  • A la hora de crear los patrones hay que tener en cuenta que Nginx usa expresiones regulares de Perl (PCRE) y que soporta captura de elementos con la sintaxis:
    ?<name>

Paso 2. Redirigir si hay coincidencia en el mapa

Por último, hay que incluir el fichero de redirecciones para luego comprobar si existe $nueva_uri como nueva variable:

include mapa-de-redirecciones.conf;
server {
    # ...
    if ( $nueva_uri ) {
        return 301 $nueva_uri;
    }
}

El funcionamiento es así: cuando llega una solicitud al servidor, Nginx buscará el valor de $request_uri en el mapa de redirecciones. Si encuentra una coincidencia creará la variable $nueva_uri con el valor asociado a la clave. En caso, contrario la variable no existirá durante el procesamiento de la petición.

Dentro del bloque server, existe un if que comprueba la existencia de la variable $nueva_uri y, en caso de existir, crea una respuesta con la redirección y finaliza el procesamiento de la petición.

Como puedes ver existen varias maneras de crear redirecciones con Nginx. La directiva return es apropiada para redirigir el tráfico entre http y https o entre el dominio con y sin www. Mientras que con rewrite es posible hacer redirecciones basadas en patrones complejos.

Por último te he explicado una técnica para organizar un gran número de redirecciones con map.

César Maeso

Lecturas recomendadas

Creative Commons License

Esta obra está bajo una licencia de Creative
Commons Reconocimiento-NoComercial-CompartirIgual
4.0 Internacional
.