Cómo procesa NGINX una petición.

Qué gran pregunta, ¿Verdad? Nginx, es un servidor web muy joven aún, pero con un futuro prometedor, como ya os contábamos en entradas anteriores:

  1. Permalinks de wordpress y su matrimonio con NGINX
  2. Cómo instalar LEMPP en Ubuntu 12.04

Desde DSLab estamos desarrollando algunos de nuestros proyectos basados en este primo de Zumosol de Apache. Como guinda a esta trilogía de post hemos decidido hacer una entrada mas técnica e intensa, traduciendo directamente al padre de la criatura,Igor Sysoev.

Como todo en esta vida, lo mejor es acudir a la fuente. Es decir, a la documentación oficial de Nginx. Como aún no está disponible en castellano, utilizaré este artículo como guía para el post.

Servidores virtuales basados ​​en nombre de dominio.

Lo primero que decide nginx es cual es el servidor que procesará la petición. empecemos con una configuración con tres servidores simples:

server {
        listen 80;
        server_name example.org www.example.org;
...
}

server {
        listen 80;
        server_name example.net www.example.net;
...
}

server {
        listen 80;
        server_name example.com www.example.com;
...
}

En esta configuración nginx solo comprueba el campo «Host» de la petición de cabecera, para determinar cual es el servidor por el que la petición debe ser encaminada. Si el valor no coincide con ningún server_name o la solicitud no contiene este campo de encabezado en absoluto, entonces nginx dirigirá la solicitud al servidor por defecto para este puerto. En la configuración anterior, el servidor por defecto es el primero – que es el comportamiento por defecto de nginx. Aunque también se puede establecer explícitamente qué servidor debe ser por defecto, con el parámetro default_server en la directiva listen, como vemos en el siguiente ejemplo:

server {
        listen      80 default_server;
        server_name example.net www.example.net;
    ...
}

Tenga en cuenta que el servidor por defecto es una propiedad del puerto de escucha (listen) y no del nombre del servidor (server_name). Más sobre esto más adelante.

Cómo prevenir las solicitudes de procesamiento con los nombres de servidor de dominio no definidos

Si las solicitudes sin el campo de cabecera «Host» No se deben permitir, es necesario definir un servidor que deja caer las solicitudes:

server {
      listen      80;
      server_name "";
      return      444;
}

En este caso, el nombre del servidor se establece en una cadena vacía que se ajuste a las peticiones sin el campo de cabecera «Host» y el código no estándar de nginx  444 es devuelto para que  se cierre la conexión. Desde la versión 0.8.48, este es el valor predeterminado para el nombre del servidor, por lo que el server "" puede ser omitido. En versiones anteriores, se utilizó el nombre de host de la máquina como el nombre del servidor predeterminado.

Configuración de Servidores virtuales mixtos basados ​​en nombre de dominio y basados ​​en IP

Echemos un vistazo a una configuración más compleja, donde algunos servidores virtuales escuchan en diferentes direcciones:

server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}

server {
    listen      192.168.1.1:80;
    server_name example.net www.example.net;
    ...
}

server {
    listen      192.168.1.2:80;
    server_name example.com www.example.com;
    ...
}

En esta configuración nginx comprueba primero  la dirección IP y el puerto, antes que las directivas listen de los bloques server_name. A continuación compara el campo «Host» del encabezado de la solicitud con las entradas de los bloques server_name que coincidan con la dirección IP y el puerto. Si el server_name no se encuentra, entonces la petición será procesada por el default_server. Por ejemplo, una petición de www.example.com recibida en la IP 192.168.1.1:80, será manejada por el default_server de la 192.168.1.1:80, es decir, por el primer servidor, ya que no hay www.example.com definido para este puerto. Como ya se ha indicado, un default_server es una propiedad del puerto de escucha, y diferentes default_servers puede ser definidos para diferentes puertos:

server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}

server {
    listen      192.168.1.1:80 default_server;
    server_name example.net www.example.net;
    ...
}

server {
    listen      192.168.1.2:80 default_server;
    server_name example.com www.example.com;
    ...
}

Configuración simple de un sitio en PHP

Ahora echemos un vistazo a cómo nginx elige una «location» para procesar una solicitud en una página típica de PHP.

server {
    listen      80;
    server_name example.org www.example.org;
    root        /data/www;

    location / {
        index   index.html index.php;
    }

    location ~* \.(gif|jpg|png)$ {
        expires 30d;
    }

    location ~ \.php$ {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME
                      $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

NGINX primero busca el prefijo de «location» más específico dado por cadenas literales sin importar el orden de la lista. En  la configuración de arriba el único prefijo de «location» es » / » y coincide con cualquier petición que se utiliza como último recurso. Entonces NGINX comprueba las «locations» dadas por expresiones regulares en el orden dado en la configuración. La primera coincidencia con la expresión regular, detiene la búsqueda y NGINX podrá utilizar la «location». Si ninguna expresión regular coincide con la petición, entonces NGINX utiliza el prefijo de «location» mas específico encontrado con anterioridad. Tenga en cuenta que las locations de todos los tipos  comprueban sólo una parte URI de línea de la petición sin argumentos. Esto se hace porque los argumentos de la cadena de consulta se pueden administrar de varias maneras, por ejemplo:

/index.php?user=john&page=1
/index.php?page=1&user=john

Además, cualquier persona podrá solicitar lo que sea en la cadena de consulta:

/index.php?page=1&something+else&user=john

Echemos un vistazo a cómo nginx procesa una petición con la configuración anterior:

  • Una petición «/logo.gif» coincide con el prefijo de location » / » primero y después con la expresión regular «\. (gif|jpj|png)$», por lo tanto, es manejada por la última location. Utilizando la directiva «root /data/www» la petición es mapeada al fichero /data/www/logo.gif, y el fichero es enviado al cliente.
  • Una petición «/index.php» también coincide con la location principal » / » y después con la expresión regular » \. (php)$». Por lo tanto, es manejada por ésta última. La petición es pasada a un servidor FastCGI que está escuchando por el puerto localhost:9000. La directiva fastcgi_param configura el parámetro FastCGI «SCRIPT_FILENAME» a la ruta «/data/www/index.php», y el servidor FastCGI ejecuta el fichero. La variable $document_root es igual al valor de la directiva root y la variable $fastcgi_script_name es igual a la petición URI, es decir, «index.php».
  • Una petición «/about.html» solo coincide con el prefijo de location » / «, por lo tanto ésta es la que lo maneja. Utilizando la directiva «root /data/www2 la petición es mapeada al fichero «/data/www/about.html», y es enviado al cliente.
  • El manejo de la petición » / » es mas complejo. Tan sólo coincide con el prefijo de location » / «, por lo tanto éste es el que lo maneja. Entonces las directivas de index comprueban la existencia de de ficheros tipo index de acuerdo con sus parámetros y la directiva «root /data/www». Si el fichero /data/www/index.html no existe, y el fichero /data/www/index.php si, entonces la directiva tiene una redirección interna hacia «index.php», y nginx busca de nuevo las locations si la petición ha sido enviada por un cliente. Como hemos visto anteriormente, la petición redireccionada eventualmente será manejada por el servidor FastCGI.Y hasta aquí la explicación de los gurús sobre este tema.

Hasta aquí la traducción, digamos libre, de la documentación oficial de Nginx. Para cualquier duda o aclaración, os remito a la fuente… Que no, que es broma. En lo que podamos os ayudaremos desde aquí. Aunque tened en cuenta que llevamos un cuarto de hora mas que vosotros en este mundo-nginx. Como siempre os digo, comentad, comentad ¡Malditos!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*