تحقيق PHP: ما الذي يختبئ وراء HTTP_HOST و SERVER_NAME؟
\n\nإذا سبق لك أن ألقيت نظرة على المصفوفة الشاملة $_SERVER في PHP، فبالتأكيد رأيت مفتاحين متشابهين جدًا: HTTP_HOST و SERVER_NAME. للوهلة الأولى، يبدو أنهما نفس الشيء — اسم الخادم. لكن المطورين ذوي الخبرة يعرفون أن الشيطان يكمن في التفاصيل. هذا الموضوع حصد آلاف المشاهدات على Stack Overflow، وليس من دون سبب. الاختيار الخاطئ قد يؤدي إلى أخطاء في عمليات إعادة التوجيه، وأعطال في الطلبات عبر النطاقات، وحتى ثغرات أمنية.
في هذه المقالة، لن نكتفي بسرد التعريفات الجافة. بل سنقوم بتحقيق حقيقي: سنشرح من أين تأتي هذه القيم، وكيف تتصرف على الخوادم المختلفة (Apache, Nginx)، والأهم من ذلك — متى نستخدم أيًا منها. استعدوا، سيكون الأمر ممتعًا.
\n\nما هو HTTP_HOST؟
\nHTTP_HOST هو قيمة الترويسة Host التي يرسلها المتصفح (أو أي عميل HTTP) إلى الخادم كجزء من الطلب. هذه الترويسة إلزامية في HTTP/1.1 وتحتوي على اسم النطاق وربما رقم المنفذ.
مثال على طلب من المتصفح:
\nGET /page.php HTTP/1.1\nHost: pythonlib.com:8080\nUser-Agent: Mozilla/5.0\n...\nفي PHP، تصل هذه القيمة إلى $_SERVER['HTTP_HOST']. لاحظ أن هذه القيمة غير موثوقة. يمكن للعميل إرسال أي نص في ترويسة Host، مثل evil-site.com أو 192.168.1.1. وهنا يكمن الخطر الرئيسي.
ما هو SERVER_NAME؟
\nSERVER_NAME هي القيمة التي يحددها خادم الويب نفسه بناءً على إعداداته. عادةً ما تؤخذ من التوجيه ServerName في Apache أو server_name في Nginx. هذا هو اسم المضيف الافتراضي الذي عالج الطلب.
مثال على إعدادات Apache:
\n<VirtualHost *:80>\n ServerName pythonlib.com\n DocumentRoot /var/www/pythonlib\n</VirtualHost>\nفي هذه الحالة، ستكون $_SERVER['SERVER_NAME'] مساوية لـ pythonlib.com. على عكس HTTP_HOST، هذه القيمة يتحكم فيها مسؤول الخادم، وليس العميل. لكن هناك فارق بسيط: SERVER_NAME قد لا يحتوي على المنفذ (يعتمد على إعداد UseCanonicalName).
الاختلافات الرئيسية في جدول
\nلتوضيح الأمور، إليك جدول مقارن:
\n| المعيار | \nHTTP_HOST | \nSERVER_NAME | \n
|---|---|---|
| المصدر | \nترويسة طلب HTTP من العميل | \nإعدادات خادم الويب | \n
| التحكم | \nالعميل (يمكن تزويره) | \nمسؤول الخادم | \n
| المنفذ | \nيتضمن المنفذ إذا كان غير قياسي (مثل site.com:8080) | \n عادةً بدون منفذ (يعتمد على UseCanonicalName) | \n
| الموثوقية | \nمنخفضة (لا تثق بها دون تحقق) | \nعالية (ولكن ليست مطلقة) | \n
| الاستخدام | \nإعادة التوجيه، الروابط للمستخدم | \nالمنطق الداخلي، الأمان | \n
متى تستخدم كلًا منهما؟ أمثلة عملية
\nالآن ننتقل إلى الجزء الأهم — الكود. دعنا نستعرض ثلاثة سيناريوهات نموذجية.
\n\n