Comment Nginx traite une requête
Nginx traite les requêtes HTTP en suivant un processus structuré. Lorsqu'une requête arrive, Nginx commence par analyser l'entête pour déterminer le nom d'hôte et l'URI. Ensuite, il sélectionne le bloc serveur correspondant en fonction de la directive server_name ou listen. Si aucune correspondance n'est trouvée, le premier bloc serveur défini pour un listen donné est utilisé. Une fois le bloc serveur sélectionné, Nginx cherche un bloc location correspondant à l'URI pour déterminer comment traiter la requête, qu'il s'agisse de servir des fichiers statiques, de faire du proxying ou de traiter des scripts dynamiques.
Pour éviter de traiter des requêtes avec des noms de serveurs non définis, il est possible de configurer un bloc serveur par défaut renvoyant un code d'état 444 pour fermer immédiatement la connexion. Cela peut être fait en utilisant la directive default_server avec un server_name _, ce qui permet de capturer les requêtes sans nom valide et de les rejeter sans réponse. Cette méthode protège le serveur contre les requêtes non désirées et non définies.
Nginx permet également d'utiliser des serveurs virtuels à la fois basés sur des noms de domaine et des adresses IP. Par exemple, vous pouvez configurer un serveur virtuel basé sur l'IP pour des requêtes envoyées à une adresse IP spécifique, tout en ayant un autre serveur virtuel répondant aux requêtes avec des noms de domaine. L'utilisation de la directive listen avec des adresses IP spécifiques permet de séparer les deux types de serveurs sans conflit, offrant ainsi une plus grande flexibilité dans la gestion des requêtes.
Enfin, une configuration simple pour un site PHP avec Nginx passe par l'utilisation de PHP-FPM pour traiter les fichiers PHP. Le serveur écoute sur le port 80, et les requêtes PHP sont envoyées à PHP-FPM via la directive fastcgi_pass. La directive try_files est utilisée pour vérifier l'existence des fichiers avant de renvoyer un 404 si le fichier n'existe pas. Cette configuration assure non seulement un traitement dynamique des fichiers PHP, mais aussi une sécurité renforcée, par exemple en empêchant l'accès aux fichiers cachés comme .htaccess.
Serveurs virtuels basés sur le nom
Nginx décide d'abord quel serveur doit traiter la requête. Commençons par une configuration simple où les trois serveurs virtuels écoutent sur le port *:80 :
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; ... } |
Dans cette configuration, Nginx teste uniquement le champ d'entête de la requête «Host» pour déterminer vers quel serveur la requête doit être acheminée. Si sa valeur ne correspond à aucun nom de serveur ou si la requête ne contient pas du tout ce champ d'entête, alors Nginx acheminera la requête vers le serveur par défaut pour ce port. Dans la configuration ci-dessus, le serveur par défaut est le premier, ce qui correspond au comportement par défaut standard de Nginx. Il est également possible de définir explicitement quel serveur doit être utilisé par défaut, avec le paramètre default_server dans la directive listen :
server { listen 80 default_server; server_name example.net www.example.net; ... } |
Le paramètre default_server est disponible depuis la version 0.8.21. Dans les versions antérieures, le paramètre default doit être utilisé à la place.
Notez que le serveur par défaut est une propriété du port d'écoute et non du nom du serveur.
Comment empêcher le traitement des requêtes avec des noms de serveur non définis
Si les requêtes sans le champ d'entête «Host» ne doivent pas être autorisées, un serveur qui abandonne simplement les requêtes peut être défini :
server { listen 80; server_name ""; return 444; } |
Ici, le nom du serveur est défini sur une chaîne de caractères vide correspondant aux requêtes sans le champ d'entête «Host», et un code spécial non standard de nginx 444 est renvoyé qui ferme la connexion.
Depuis la version 0.8.48, il s'agit du paramètre par défaut pour le nom du serveur, donc le server_name "" peut être omis. Dans les versions antérieures, le nom d'hôte de la machine était utilisé comme nom de serveur par défaut.
Serveurs virtuels mixtes basés sur le nom et sur l'IP
Examinons une configuration plus complexe où certains serveurs virtuels écoutent sur des adresses différentes :
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; ... } |
Dans cette configuration, nginx teste d'abord l'adresse IP et le port de la requête par rapport aux directives d'écoute des blocs de serveur. Il teste ensuite le champ d'en-tête «Host» de la requête par rapport aux entrées server_name des blocs de serveur correspondant à l'adresse IP et au port. Si le nom du serveur n'est pas trouvé, la requête sera traitée par le serveur par défaut. Par exemple, une requête pour www.example.com reçue sur le port 192.168.1.1:80 sera traitée par le serveur par défaut du port 192.168.1.1:80, c'est-à-dire par le premier serveur, car aucun www.example.com n'est défini pour ce port.
Comme indiqué précédemment, un serveur par défaut est une propriété du port d'écoute, et différents serveurs par défaut peuvent être définis pour différents ports :
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; ... } |
Une configuration de site PHP simple
Voyons maintenant comment nginx choisit un emplacement pour traiter une requête pour un site PHP simple et typique :
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 recherche d'abord l'emplacement de préfixe le plus spécifique donné par des chaînes littérales, quel que soit l'ordre indiqué. Dans la configuration ci-dessus, le seul emplacement de préfixe est «/» et comme il correspond à n'importe quelle requête, il sera utilisé en dernier recours. Ensuite, Nginx vérifie les emplacements donnés par l'expression régulière dans l'ordre indiqué dans le fichier de configuration. La première expression correspondante arrête la recherche et Nginx utilisera cet emplacement. Si aucune expression régulière ne correspond à une requête, Nginx utilise l'emplacement de préfixe le plus spécifique trouvé précédemment.
Notez que les emplacements de tous types ne testent qu'une partie URI de la ligne de requête sans paramètres. Cela est fait parce que les paramètres dans la chaîne de requête peuvent être donnés de plusieurs manières, par exemple :
/index.php?user=jean&page=1 /index.php?page=1&user=jean |
De plus, n'importe qui peut demander n'importe quoi dans la chaîne de requête :
/index.php?page=1&something+else&user=jean |
Voyons maintenant comment les requêtes seraient traitées dans la configuration ci-dessus :
- Une requête «/logo.gif» est d'abord associée à l'emplacement du préfixe «/», puis à l'expression régulière « \.(gif|jpg|png)$ ». Elle est donc gérée par ce dernier emplacement. À l'aide de la directive «root /data/www», la requête est cartographiée sur le fichier /data/www/logo.gif, et le fichier est envoyé au client.
- Une requête «/index.php» est également associée à l'emplacement du préfixe «/», puis à l'expression régulière « \.(php)$ ». Elle est donc gérée par ce dernier emplacement et la requête est transmise à un serveur FastCGI écoutant sur localhost:9000. La directive fastcgi_param définit le paramètre FastCGI SCRIPT_FILENAME sur «/data/www/index.php», et le serveur FastCGI exécute le fichier. La variable $document_root est égale à la valeur de la directive root et la variable $fastcgi_script_name est égale à l'URI de la requête, c'est-à-dire «/index.php».
- Une requête «/about.html» est associée uniquement à l'emplacement du préfixe «/», elle est donc traitée à cet emplacement. En utilisant la directive «root /data/www», la requête est cartographiée au fichier /data/www/about.html, et le fichier est envoyé au client.
- La gestion d'une requête «/» est plus complexe. Elle est associée uniquement à l'emplacement du préfixe «/», elle est donc traitée à cet emplacement. Ensuite, la directive index teste l'existence de fichiers d'index en fonction de ses paramètres et de la directive «root /data/www». Si le fichier /data/www/index.html n'existe pas et que le fichier /data/www/index.php existe, la directive effectue une redirection interne vers « /index.php », et nginx recherche à nouveau les emplacements comme si la requête avait été envoyée par un client. Comme nous l'avons vu précédemment, la requête redirigée sera finalement traitée par le serveur FastCGI.