I've been running across an odd behavior in Nginx with requests that have a trailing dot in the hostname, i.e. domain.com.
rather than domain.com
alone. I set up a simple server config to test, like so:
server {
listen 80;
server_name example.com.;
root /var/www/example;
index server1.txt;
}
server {
listen 80;
server_name example.com;
root /var/www/example;
index server2.txt;
}
Initially, I expected that requests made to example.com.
would be sent to the first block and requests made to example.com
would be sent to the second. Requests whose Host
header didn't match any block, e.g. www.example.com
, I expected to be sent to the first block again as it was the implicit default.
However, upon testing I discovered that requests made to example.com.
were sent instead to the second block. After messing around for a good while with various alternate names, regular expressions etc. I decided to write the $host
variable to a custom header so I could look at it. Turns out that Nginx is actually dropping the trailing dot from the $host
value. As far as I can tell a request received at example.com.
is considered identical to one received at example.com
, at least as far as server-selection goes. This seems undesirable, as trailing dots can result in various errors..
To make matters even more confusing, after some googling I found the Nginx changelog page, which has in the 0.1.29 changelog:
Bugfix: nginx did not take into account trailing dot in "Host" header line.
Then, years later, the 1.5.9 changelog says:
Bugfix: resolver did not understand domain names with a trailing dot. Thanks to Yichun Zhang.
Although I'm not sure whether the "resolver" refers to a component of Nginx that is in play when it receives a request. (From reading the docs, it sounds like maybe the resolver doesn't do anything unless a request is being forwaded to some other host, whose name must then be resolved.)
What's going on here? Should Nginx be dropping the trailing dot when it evaluates server names? If this is intended behavior, shouldn't the trailing dot also be dropped from the server_name
parameter to yield a "conflicting server name" error?
I know that a domain name without a trailing dot is technically a "relative" domain name rather than "absolute," although most people these days seem to treat them as all relative to the .
zone so it doesn't make a practical difference. But shouldn't Nginx at least be able to make this distinction if desired?
Finally, is there any better way to catch and redirect requests made to example.com.
than adding if ($http_host = 'domain.com.')
? I've been told that this is inefficient, as it requires the Host
header to be evaluated twice.