HTTP_HOST vs SERVER_NAME in PHP: What's the Catch?

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

PHP Detective: What Lies Behind HTTP_HOST and SERVER_NAME?

\n\n

If you've ever looked into the PHP superglobal array $_SERVER, you've probably seen two very similar keys: HTTP_HOST and SERVER_NAME. At first glance, they seem to be the same thing — the server name. But experienced developers know: the devil is in the details. This topic has garnered thousands of views on Stack Overflow, and for good reason. Choosing the wrong one can lead to bugs in redirects, failures in cross-domain requests, and even vulnerabilities.

\n

In this article, we won't just list dry definitions. We'll conduct a real investigation: we'll break down where these values come from, how they behave on different servers (Apache, Nginx), and most importantly — when to use which one. Buckle up, it's going to be interesting.

\n\n

What is HTTP_HOST?

\n

HTTP_HOST is the value of the Host header that the browser (or any other HTTP client) sends to the server as part of the request. This header is mandatory in HTTP/1.1 and contains the domain name and, optionally, the port number.

\n

Example request from a browser:

\n
GET /page.php HTTP/1.1\nHost: pythonlib.ru:8080\nUser-Agent: Mozilla/5.0\n...
\n

In PHP, this value ends up in $_SERVER['HTTP_HOST']. Note: this is an unverified value. The client can send any text in the Host header, for example, evil-site.com or 192.168.1.1. This is where the main danger lies.

\n\n

What is SERVER_NAME?

\n

SERVER_NAME is a value set by the web server itself based on its configuration. It is usually taken from the ServerName directive in Apache or server_name in Nginx. This is the name of the virtual host that processed the request.

\n

Example Apache configuration:

\n
<VirtualHost *:80>\n    ServerName pythonlib.ru\n    DocumentRoot /var/www/pythonlib\n</VirtualHost>
\n

In this case, $_SERVER['SERVER_NAME'] will be equal to pythonlib.ru. Unlike HTTP_HOST, this value is controlled by the server administrator, not the client. However, there is a nuance: SERVER_NAME may not include the port (depends on the UseCanonicalName setting).

\n\n

Key Differences in a Table

\n

For clarity, let's summarize everything in a table:

\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
ParameterHTTP_HOSTSERVER_NAME
SourceHTTP request header from clientWeb server configuration
ControlClient (can be spoofed)Server administrator
PortIncludes port if non-standard (e.g., site.com:8080)Usually without port (depends on UseCanonicalName)
ReliabilityLow (do not trust without validation)High (but not absolute)
UsageRedirects, user-facing linksInternal logic, security
\n\n

When to Use What? Practical Examples

\n

Now let's move on to the most important part — code. Let's look at three typical scenarios.

\n\n

1. Redirect to the same domain (e.g., with www

Blogs

Book Recommendations