Have you ever wondered where PHP gets the domain name of its server? I know, the answer is $_SERVER['SERVER_NAME']
– but where does that value actually come from?
Obviously, it comes from the server (the clue is in the name of the superglobal!), but where does the server get it from? Let’s look at the two most common web servers, apache and nginx. We’ll use a simple test script;
# index.php <?= $_SERVER['SERVER_NAME'] . PHP_EOL ?>
We’ll add a couple of aliases to our server
# /etc/hosts 127.0.0.1 foo bar
OK, apache first.
$ telnet foo 80 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. GET / HTTP/1.1 host: foo HTTP/1.1 200 OK Content-Type: text/html (a few other headers, not relevant here) foo Connection closed by foreign host.
$ telnet bar 80 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. GET / HTTP/1.1 host: bar HTTP/1.1 200 OK Content-Type: text/html (a few other headers, not relevant here) bar Connection closed by foreign host.
Now, what happens if you pass an unexpected value in the host field?
$ telnet foo 80 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. GET / HTTP/1.1 host: Fish Are Best! HTTP/1.1 200 OK Content-Type: text/html (a few other headers, not relevant here) fish are best! Connection closed by foreign host.
Apache just converts the host field to lower case and passes it back to you. If you are using $_SERVER['SERVER_NAME']
in your PHP code, I hope you’re treating it a user-supplied, and hence unclean!
Next nginx. We’ll use the following line in our configuration:
server_name foo bar;
When we specify host: foo, we get back foo, and when we specify host: bar we also get foo! If we specify a bogus host host: Fish Are Best! we reassuringly also get foo.
Now, let us change the order of domains in the configuration block.
server_name bar foo;
Now, we get back bar for all requests. nginx always uses the first domain listed in the server_name
directive.
This could be a gotcha if you have
server_name example.com www.example.com;
and you use the server_name to set a cookie path.
So, to summarise,
apache – $_SERVER['SERVER_NAME']
is a lower-cased version of whatever you pass in the host field.
nginx – $_SERVER['SERVER_NAME']
is the first entry in the server_name
directive.