这个问题已经以各种方式问了一百万遍。我仍然找不到足够通用的答案来涵盖所有情况。
我想要的是从任何传入URL中删除www
,并将其应用于所有子域。这是我的Nginx配置,否则可以正常工作:
# redirect HTTP to HTTPS, no www
server {
listen 80;
listen [::]:80;
server_name ~^(?<www>www\.)(?<subdomain>.+)\.example\.com$;
# redirect
return 301 https://${subdomain}.example.com$request_uri;
}
#redirect HTTPS www to non-www
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ~^(?<www>www\.)(?<subdomain>.+)\.example\.com$;
# ssl config...
# redirect
return 301 https://${subdomain}.example.com$request_uri;
}
#default server
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com *.example.com;
# other calls below this point include
# root dir
# ssl config
# security headers
# various location blocks, specific to my project
# error page
# error/access logs...
}
所有这些映射都可以通过上面的配置很好地处理:
http://example.com
-> https://example.com
http://client1.example.com
-> https://client1.example.com
http://dev.client1.example.com
-> https://dev.client1.example.com
http://stage.client1.example.com
-> https://stage.client1.example.com
但是这些不是:
http://www.example.com
-> https://example.com
http://www.client1.example.com
-> https://client1.example.com
http://www.dev.client1.example.com
-> https://dev.client1.example.com
您能帮助我了解我需要在配置中进行哪些更改或如何对其进行调试吗?
答案 0 :(得分:0)
对于http块:
由于HSTS,仅为首次访问的客户提供服务。因此,您可以使用简单的重定向并在https块中执行www.
删除。
例如:
server {
listen 80;
listen [::]:80;
return 301 https://$host$request_uri;
}
如果要在此阶段删除www.
前缀,则需要一个始终匹配的正则表达式。
例如:
server {
listen 80;
listen [::]:80;
server_name ~^(www\.)?(?<domain>.+)$;
return 301 https://$domain$request_uri;
}
有关详细信息,请参见this document。
对于https块:
您需要一个正则表达式来捕获www.
之后的那部分域名。您有两种选择:
使用两个server
块(如现在所述),但不要在第二个块中放入通配符server_name
语句。您可以使用其他正则表达式(例如server_name ~example\.com$;
)或根本不使用server_name
并将其设置为默认值。
例如:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ~^www\.(?<domain>.+)$;
# ssl config...
return 301 https://$domain$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
# no server_name statement needed
...
}
或者使用单个server
块,并使用$http_host
语句测试if
变量。
例如:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name .example.com;
if ($http_host ~ ~^www\.(.+)$) { return 301 https://$1$request_uri; }
...
}
有关if
的使用,请参见this caution。