nginx 版本/1.18.0 (Ubuntu) — Ubuntu 22.04.01 LTS x86_64 内核 6.0.8
我有一台服务器(安装上面的规格),它有多个主机名,正在运行 nginx,并且一切正常(包括 nginx,从 http:重定向到 https:)。
事实上,我在默认服务器中是这样操作的:
listen 80 default_server;
listen 443 default_server ssl;
# force https-redirects
if ($scheme = http) {
return 301 https://$host$request_uri;
}
server_name _;
奇怪的行为如下:
网址 | 重定向至 | 笔记 |
---|---|---|
http://mumblefrotz/ |
https://mumblefrotz/ |
(按预期工作) |
http://mumblefrotz.fullyqualified.com/ |
https://mumblefrotz.fullyqualified.com/ |
(按预期工作) |
http://127.0.0.1/ |
https://127.0.0.1/ |
(按预期工作) |
http://localhost/ |
https://_ |
失败 |
它为什么会这样? 我怀疑这与server_name
指令被从字面上理解,尽管我不太确定为什么它只发生在localhost
。
在看着这个 Stack Overflow 建议,我尝试了以下两种方法,但仍然得到了令人惊讶的下划线:
server_name ~.;
server_name ~^(.+)$;
我的期望$host
是HTTP 请求中传递的主机名如果已定义虚拟主机,则采用虚拟主机;如果未定义,则返回默认服务器定义。
据我所知,http://localhost/
这是唯一一个无法正确解决的问题。我想修复它。
答案1
没有关于使用哪个客户端发出请求的信息。正如所写nginx 文档,$host
变量包含:
按以下优先顺序:请求行中的主机名,或“Host”请求标头字段中的主机名,或与请求匹配的服务器名称
这里的“请求行”是指GET
HTTP 请求中动词后面的主机名。
第二个表示Host
头字段。
第三个表示在中配置的名称server_name
。
就你的情况而言,我认为测试客户端发出了一个不包含Host
标头的请求。因此 nginx 使用server_name
配置作为变量的内容$host
。
就我个人而言,我只是为每个虚拟服务器生成 HTTP -> HTTPS 转发块,因为我使用 Ansible 管理 nginx 配置。这样,我就可return 404
以为所有其他我不感兴趣的主机名设置一个虚拟主机。
但是如果您需要为重定向实现一个通用的虚拟主机,则可以使用以下方法:
map $http_host $redirect_host {
~ (^.+$) $http_host;
default example.com;
}
server {
listen 80 default_server;
...
if ($scheme = http) {
return 301 https://$redirect_host$request_uri;
}
}
这始终使用 HTTP 主机标头作为重定向目标,除非没有Host
标头。在这种情况下,它用作example.com
重定向目标。例如,您可以将主域名指定为重定向目标。