Détective PHP : que se cache-t-il derrière HTTP_HOST et SERVER_NAME ?
\n\nSi vous avez déjà jeté un œil au tableau superglobal $_SERVER en PHP, vous avez sûrement vu deux clés très similaires : HTTP_HOST et SERVER_NAME. À première vue, on dirait la même chose — le nom du serveur. Mais les développeurs expérimentés le savent : le diable se cache dans les détails. Ce sujet a rassemblé des milliers de vues sur Stack Overflow, et ce n'est pas pour rien. Un mauvais choix peut entraîner des bugs dans les redirections, des échecs dans les requêtes cross-domain, et même des vulnérabilités.
Dans cet article, nous ne nous contenterons pas de lister des définitions sèches. Nous allons mener une véritable enquête : analyser d'où viennent ces valeurs, comment elles se comportent sur différents serveurs (Apache, Nginx), et surtout — quand utiliser quelle option. Attachez vos ceintures, ça va être intéressant.
\n\nQu'est-ce que HTTP_HOST ?
\nHTTP_HOST est la valeur de l'en-tête Host que le navigateur (ou tout autre client HTTP) envoie au serveur dans le cadre de la requête. Cet en-tête est obligatoire en HTTP/1.1 et contient le nom de domaine et éventuellement le numéro de port.
Exemple de requête du navigateur :
\nGET /page.php HTTP/1.1\nHost: pythonlib.ru:8080\nUser-Agent: Mozilla/5.0\n...\nEn PHP, cette valeur se retrouve dans $_SERVER['HTTP_HOST']. Notez bien : il s'agit d'une valeur non vérifiée. Le client peut envoyer n'importe quel texte dans l'en-tête Host, par exemple evil-site.com ou 192.168.1.1. C'est là que réside le principal danger.
Qu'est-ce que SERVER_NAME ?
\nSERVER_NAME est la valeur définie par le serveur web lui-même en fonction de sa configuration. Elle provient généralement de la directive ServerName dans Apache ou server_name dans Nginx. C'est le nom de l'hôte virtuel qui a traité la requête.
Exemple de configuration Apache :
\n<VirtualHost *:80>\n ServerName pythonlib.ru\n DocumentRoot /var/www/pythonlib\n</VirtualHost>\nDans ce cas, $_SERVER['SERVER_NAME'] sera égal à pythonlib.ru. Contrairement à HTTP_HOST, cette valeur est contrôlée par l'administrateur du serveur, et non par le client. Cependant, il y a une nuance : SERVER_NAME peut ne pas contenir le port (cela dépend du paramètre UseCanonicalName).
Principales différences dans un tableau
\nPour plus de clarté, résumons tout dans un tableau :
\n| Paramètre | \nHTTP_HOST | \nSERVER_NAME | \n
|---|---|---|
| Source | \nEn-tête de la requête HTTP du client | \nConfiguration du serveur web | \n
| Contrôle | \nClient (peut être falsifié) | \nAdministrateur du serveur | \n
| Port | \nInclut le port s'il est non standard (ex. site.com:8080) | \n Généralement sans port (dépend de UseCanonicalName) | \n
| Fiabilité | \nFaible (ne faites pas confiance sans vérification) | \nÉlevée (mais pas absolue) | \n
| Utilisation | \nRedirections, liens pour l'utilisateur | \nLogique interne, sécurité | \n
Quand utiliser quoi ? Exemples pratiques
\nPassons maintenant au plus important — le code. Examinons trois scénarios typiques.
\n\n