Nginx:如何仅将主域名与server_name匹配

问题描述

我的目标是将example.com重定向www.example.com而不将任何子域重定向www

这就是我所拥有的:

server {
  listen 443;
  server_name example.com;
  return 301 https://www.$server_name$request_uri;
}

通过这种配置,像我一样,每个子域(例如:foo.example.com)被重定向www.example.com,而不仅仅是重定向到没有子域的主要域(example.com)想。

我尝试清理缓存(并且也在其他浏览器中进行了清理),但结果相同。

编辑:

server_name与子域匹配的证明是,如果我将重定向URL更改为:https://www.$host$request_uri,则:

foo.example.com重定向www.foo.example.com

解决方法

尝试使用多个server_name指令:

server {
  listen 443;
  server_name example.com;
  return 301 https://www.$server_name$request_uri;
}

server {
  listen 443;
  server_name ~^(?<name>\w+)\.example\.com$;
  
  ... # insert your directives (location etc.)
}

nginx documentation上指定:

按名称搜索虚拟服务器时,如果名称匹配更多 而不是指定变体之一,例如通配符名称和 正则表达式匹配,将选择第一个匹配变体, 按照以下优先顺序:

  1. 确切名称
  2. 最长的通配符名称,以星号开头,例如“ * .example.org”
  3. 以星号结尾的最长通配符名称,例如“邮件。*”
  4. 第一个匹配的正则表达式(按在配置文件中出现的顺序)
,

实际上,example.com仅与主域匹配。

但是,如果hostname与任何server_name不匹配(并且在您的示例中,您的子域也不匹配,因为主域只有一个服务器规则),则默认服务器将被使用,if you didn't specify it with the default_server tag in the listen parameter,it uses by default the first server,在您的情况下是主域的重定向规则。

TD; TR

您的子域与任何规则都不匹配,因此它们会被调用回您设置的唯一规则,即重定向。

您需要对子域有特定的规则:

server {
  listen 443;
  server_name *.example.com;
  # do something,or leave it blank for default nginx page
}

这将防止子域使用默认服务器,因此将其重定向到www,但是未将其配置为不执行任何操作,因此将显示默认的nginx页面。我建议直接为每个子域指定所需的行为,或者将注释替换为所有子域的实际预期行为。