如何将 www 上的请求重定向到非 www 版本?
这应该包括对根域以及任何(通配符)子域的请求。
根据 nginx 陷阱文档,我也不想要任何不必要的 if 语句。
这是我目前所拥有的但它似乎只适用于根域,而不适用于子域。
server {
listen 80 default_server;
server_name www.*;
rewrite "^www\.(.*)" $scheme://$1 permanent;
}
答案1
我对您的问题的理解如下:以合理通用的方式将到达任意根域的任何子域的所有请求重定向到根域。例如:
- www.example1.com -> example1.com
- abcd.example2.com -> example2.com
- *.exampleN.com -> exampleN.com
让我们首先从简单的情况开始——一个已知的根域,带有任意子域:
server{
server_name *.example.com;
rewrite ^ $scheme://example.com permanent;
}
server{
listen 80 default_server;
server_name example.com;
#your main config
}
这是相当好的优化 - 没有 if 语句,重写中没有不必要的捕获 - 并且通配符 server_names 被散列以提高性能。第一个服务器块匹配任何子域,并将发出重定向到仅匹配根域的第二个服务器块。(请注意,虽然在一个服务器块中很容易匹配两个条件(server_name .example.com
-*
不需要)但需要两个服务器块来防止重定向循环)。
更普遍的情况需要某种方式来识别域,因为它是“未知的”。因此,我们需要解析 server_name - 并且可以使用正则表达式捕获来完成。
server{
server_name ~^(.+\.)(?<domain>.+\..+)$;
rewrite ^ $scheme://$domain permanent;
}
server{
listen 80 default_server;
server_name _;
#your main config
}
这里我们有一个(必需的)子域 -(.+\.)
意味着任何字符(.
)重复一次或多次(+
)后跟实际的“。” (用反斜杠转义) -$1
如果需要,将分配给此捕获。
下一节非常相似 - 我们使用 Perl 5.1/PCRE7 符号表示“命名捕获” -?<domain>
将捕获分配给$domain
。我们的域可以是任何内容(.
)长度为一个或多个字符(+
),后跟实际的“。”,然后是另一组任意字符(TLD)。此正则表达式不适用于包含“。”的 TLD - 例如“co.uk” - 如果您要使用这些,最好在正则表达式中指定有效的 TLD。例如:
server_name ^(.+\.)(?<domain>.+\.(co\.uk|net|org|com))$
我们使用与上面相同的重写,只是用捕获的域替换静态根域。
由于“未知”域场景的常见情况是您将相同的文件传递到所有域,因此您可能不需要在 default_server 块中捕获域名(尽可能避免使用正则表达式会更有效)。
需要注意的是,正则表达式匹配的优先级最低 - 精确名称和通配符条目优先于正则表达式。此外,与精确名称和通配符条目不同,正则表达式不会被散列。最后,当使用带有捕获的正则表达式时,即使只定义了一个服务器块,也必须对每个请求评估表达式才能获得捕获。
因此,如果您确实需要对特定域名执行某些特定操作,只需为其定义一个新的服务器块,它将优先于上面定义的 default_server 块。
如果您知道域名,即使域名很多,如果您可以包含静态名称而不是使用正则表达式,您将获得更好的性能。话虽如此,在某些情况下(例如允许用户将其(未知)域名指向您的 IP 作为服务的一部分),您可能不知道域名,并且需要使用正则表达式方法。
(当然,这需要匹配的通配符 DNS 条目才能使请求到达服务器。)
答案2
有几种方法可以做到这一点。为 www.servername.org 域名设置一个配置文件,并给它一个到 servername.org 的通用重定向,或者将以下内容添加到您的配置中,而不是重写行。
if ($host = 'www.site.com' ) {
rewrite ^/(.*)$ http://site.com/$1 permanent;
}
答案3
把事情简单化。
server {
listen 80;
server_name nginx.org www.nginx.org www1.nginx.org;
...
}
http://nginx.org/en/docs/http/server_names.html
更好的是
server {
listen 80;
server_name *;
...
}
或者说这太简单了?