What is the difference between Nginx variables $host, $http_host, and $server_name?

Jeff Widman asked:

What is the difference between the three Nginx variables $host, $http_host, and $server_name?

I have a rewrite rule where I’m not sure which one I should be using:

location = /vb/showthread.php {
    # /vb/showthread.php?50271-What-s-happening&p=846039
    if ($arg_p) {
        return 301 $scheme://$host/forum/index.php?posts/$arg_p/;

I’m looking for an answer that doesn’t just say ‘use ___ variable in your rewrite rule’ but also explains the theoretical differences between them.

My answer:

You should almost always use $host, as it’s the only one guaranteed to have something sensible regardless of how the user-agent behaves, unless you specifically need the semantics of one of the other variables.

The difference is explained in the nginx documentation:

  • $host contains “in this order of precedence: host name from the request line, or host name from the ‘Host’ request header field, or the server name matching a request”
  • $http_host contains the content of the HTTP “Host” header field, if it was present in the request
  • $server_name contains the server_name of the virtual host which processed the request, as it was defined in the nginx configuration. If a server contains multiple server_names, only the first one will be present in this variable.

Since it is legal for user-agents to send the hostname in the request line rather than in a Host: header, though it is rarely done except when connecting to proxies, you have to account for this.

You also have to account for the case where the user-agent doesn’t send a hostname at all, e.g. ancient HTTP/1.0 requests and modern badly-written software. You might do so by diverting them to a catch-all virtual host which doesn’t serve anything, if you are serving multiple web sites, or if you only have a single web site on your server you might process everything through a single virtual host. In the latter case you have to account for this as well.

Only the $host variable accounts for all the possible things that a user-agent may do when forming an HTTP request.

View the full question and any other answers on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.