7.2.2.2.3. Location

Ya se ha discutido que a grandes rasgos una URL está compuesta por esquema://maquina/ruta u cómo nginx selecciona el dominio virtual adecuado dependiendo de la máquina[1]. Sin embargo, ya elegido este, nginx permite también alterar el comportamiento dependiendo de cuál sea la ruta. Para ello existe la directiva location. Por ejemplo:

server {
   listen 80;
   server_name  _;

   root /srv/www;

   location /favicon.ico {
      log_not_found off;
      access_log off;
      return 410;
   }
}

En este caso, cuando un navegador pide el recurso /favicon.ico, se aplica una directiva que evita que se registre en los logs la petición del recurso[2] y, además, se devuelva un código 410 para que el navegador no vuelva a pedirlo más[3]. Por supuesto, si se pide cualquier otro recurso, la petición sí se registrará y no se devolverá un error.

Advertencia

No entienda location como una sentencia condicional que sirve para aplicar unas directivas particulares a la URL que cumpla su patrón, de manera que si varias localizaciones son adecuadas, se aplicarán las directivas particulares de todas esas localizaciones. Los bloques location son bloques terminales: cada petición acaba por aplicar la configuración de un único bloque location (más, obviamente, la configuración común del bloque server): y en caso de que varios bloques concuerden con la URL se escogerá uno según las reglas de precedencia que se verán más adelante. La única forma de que una petición salga de su bloque location y acabe aplicando otra configuración es quie se encuentre dentro con un redirección exitosa.

Nota

Pueden anidarse localizaciones, excepto las localicaciones nominales (las que usan @) que no pueden anidar ni ser anidadas.

7.2.2.2.3.1. Expresión de las rutas

La directiva location permite expresar el patrón a comparar con la ruta de diversos modos:

  • Sin modificador, implica que el patrón debe concordar con el principio de la ruta:

    location /docs/ {
       autoindex on;
    }
    

    de esta manera, direcciones como http://www.example.net/docs/uno.html o http://www.example.net/docs/subdir/dos.html concuerdan con el patrón.

  • Con el modificador =, el patrón debe concordar exactamente con la ruta:

    location = /errors/404.html {
       internal;
    }
    
  • Con el modificador ~, el patrón es una expresión regular:

    location ~ \.(jpg|jpeg|png)$ {
       expires max;
    }
    

    En este caso, la directiva expires se aplica a las imágenes.

    Nota

    La expresión regular también puede escribirse entre comillas:

    location ~ "\.(jpg|jpeg|png)$" {
       expires max;
    }
    

    lo cual cobra especial importancia cuando contiene algún carácter que puede malinterpretar nginx como la llave de apertura (»{«).

  • Con el modificador ~*, el patrón es una expresión regular en que no atienden mayúsculas o minusculas:

    location ~* \.(jpe?g|png)$ {
       expires max;
    }
    

    En este caso una imagen de nombre foto.JPG también concordaría.

  • Con el modificador ^~, el patrón no es una expresión regular, sino que debe concordar con el principio de la ruta exactamente igual que cuando no hay modificador. La diferencia la veremos al tratar el orden de precedencia.

  • Con el modificador @, el patrón no es un patrón para rutas, sino un nombre que puede usarse en redirecciones. Por ejemplo:

    try_files $uri $uri/ @nombre;
    
    location @nombre {
       rewrite ^(.*\.(?:jpe?g|png))$ /images$1 last;
    }
    

Nota

Como en el caso de server_name es posible capturar grupos para usarlos luego en directivas incluidas dentro del bloque. Véase un ejemplo más abajo al habilitar los perfiles de usuario.

7.2.2.2.3.2. Precedencia

Es muy habitual que dentro de un mismo bloque virtual, haya varias localizaciones. Una petición sólo puede aplicar las directivas incluidas dentro de una localización (o de ninguna), por lo que hay un orden de precedencia para determinar cuál de los bloques location concordante es aplicable. La precedencia es la siguiente:

  1. La localización con modificador =.

  2. La localización más larga con modificador ^~.

  3. La primera localización con expresión regular (indistintamente ~ y ~*).

  4. La localización más larga sin modificador.

Ver también

La página nginx.viraptor.info calcula, dada una configuración, cuál es el bloque server y, dentro de él, el bloque location aplicable para una URL determinada.

7.2.2.2.3.3. Alias

Ya introdujimos la directiva root, que permite indicar cuál es el directorio en el sistema de ficheros del servidor bajo el cual se sitúan los ficheros accesibles. Por tanto, si su valor es /srv/www y la ruta del recurso requirida es /themes/classic/main.css, el recurso se encuentra en el servidor en la ruta /srv/www/themes/classic/main.css, esto es, la concatenación del directorio raíz y la ruta expresada en la URL.

Pero hay otra forma de indicar cuál la ruta en el servidor del recurso y que requiere el uso location: alias. Con ella, la ruta absoluta del recurso en el servidor es la concatenación su valor y la ruta de la URL descontada la coincidencia con el patrón de location. Por ejemplo:

location /images/ {
   alias /usr/share/nginx/media/;
}

En este caso, si se pidiera el recurso http://www.example.net/images/foto.jpg, su ruta en el servidor sería /usr/share/nginx/media/foto.jpg y no /usr/share/nginx/media/images/foto.jpg, como habría ocurrido si se hubiera usado root.

7.2.2.2.3.4. Sitios personales

Es una práctica común, cuando en un servidor se desea que sus usuarios tengan sitio personal en el que puedan colgar contenidos, que se acceda a ellos a través de la dirección:

http://www.example.net/~USUARIO/ruta/hacia/el/recurso

donde USUARIO es el nombre de usuario; y que los contenidos se sitúen en el servidor bajo ~/public_html. Para lograr esto, en nginx basta con incluir en el dominio virtual (o sea, el bloque server) adecuado, lo siguiente:

# Sitios personales (contenido estático)
location ~ ^/~([^/]+)(.*)$ {
   alias /home/$1/public_html$2;
   autoindex on;
}

que logra lo que pretendemos.

Nota

Este trozo de configuración es muy apropiado para incluirlo como contenido de un fichero llamado snippets/personal.conf e incluirlo después dentro del bloque server adecuado mediante la directiva include:

include snippets/personal.conf;

Notas al pie