Nginx 正在提供默认内容而不是我的内容

Nginx is serving the default content instead of my content

我在 Ubuntu 16.04.2 LTS 上有一个 nginx version: nginx/1.10.3 (Ubuntu) 运行。

我使用 nginx 来提供静态文件,由 webpack 生成的包,但这无关紧要。

我要实现的是:

example.com 我想发球 /home/bundles/main/index.html。我可以做到。

projects.example.com/project_1 我想服务 /home/bundles/project_1/index.html

projects.example.com/project_2 我想服务 /home/bundles/project_2/index.html

最后两个,我做不到。当我转到 projects.example.com/project_1projects.example.com/project_2 时,我会看到默认的 nginx 页面。

为了让事情更混乱 /etc/nginx/sites-enabled/default 被完全注释掉了。

此外,如果在 projects.example.comlocation 块中我将 project_1 替换为 /,我将获得该特定项目,但随后我将无法为对方服务。

下面,我将向您展示我的 nginx 配置


server {
    listen 80;
    server_name example.com;

    location / {
        root /home/bundles/main;
        try_files $uri /index.html;
    }

    if ($scheme != "https") {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name example.com;

    location / {
        root /home/bundles/main;
        try_files $uri /index.html;
    }

    ssl_certificate ...
    ssl_certificate_key ...
}

server {
    listen 80;
    server_name projects.example.com;

    location /project_1 {
        root /home/bundles/project_1;
        try_files $uri /index.html;
    }

    location /project_2 {
        root /home/bundles/project_2;
        try_files $uri /index.html;
    }

    if ($scheme != "https") {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name projects.example.com;

    location /project_1 {
        root /home/bundles/project_1;
        try_files $uri /index.html;
    }

    location /project_2 {
        root /home/bundles/project_2;
        try_files $uri /index.html;
    }

    ssl_certificate ...
    ssl_certificate_key ...
}

感谢您的帮助!


编辑

我的回答

我找到的解决方案是将 root 更改为 alias

server {
    listen 80;
    server_name example.com;

    location / {
        root /home/bundles/main;
        try_files $uri /index.html;
    }

    if ($scheme != "https") {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name example.com;

    location / {
        root /home/bundles/main;
        try_files $uri /index.html;
    }

    ssl_certificate ...
    ssl_certificate_key ...
}

server {
    listen 80;
    server_name projects.example.com;

    location /project_1 {
        alias /home/bundles/project_1;
        index index.html;
    }

    location /project_2 {
        alias /home/bundles/project_2;
        index index.html;
    }

    if ($scheme != "https") {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name projects.example.com;

    location /project_1 {
        alias /home/bundles/project_1;
        index index.html;
    }

    location /project_2 {
        alias /home/bundles/project_2;
        index index.html;
    }

    ssl_certificate ...
    ssl_certificate_key ...
}

解决方案基于这两个答案。第一个 answer showing how to solve the problem and the second answer 解释了为什么 alias 有效而 root 无效。

引用@treecoder

In case of the root directive, full path is appended to the root including the location part, whereas in case of the alias directive, only the portion of the path NOT including the location part is appended to the alias.

在我的特殊情况下,这将像这样翻译;

使用 rootnginx 尝试访问的路径将是 /home/bundles/project_1/project_1

使用 alias 它访问正确的路径,/home/bundles/project_1

返回一级,例如,说:

root /home/bundles/ 也不是真正的选择。那是因为我的项目实际上并没有被称为project_1project_2。实际结构与此更相似。

/bundles 中,我有目录 project_aproject_b。我想将 project_1 路由到 project_a 目录,将 project_2 路由到 project_b 目录。

这就是我使用 alias 的原因。

希望对您有所帮助。

你有:

location /project_1 {
    root /home/bundles/project_1;
    try_files $uri /index.html;
}

因此 root 仅针对以 /project_1 开头的 URI 定义。对于任何其他 URI,将使用默认 root

如果您提供 URI /project_1/(尾随 /),假设 default index directive 有效,nginx 应该 return 您的/project_1/index.html内容。

但是,未找到 URI /project_1 - 因此 /index.html 改为 returned。 URI /index.html 不以 /project_1 开头,因此使用默认根。


如果您希望 URI /project_1 按预期工作,并且默认操作转到项目的 index.html 文件,请更改 try_files 指令。

location /project_1 {
    root /home/bundles/project_1;
    try_files $uri $uri/ /project_1/index.html;
}

有关更多信息,请参阅 this document


由于两个项目共享一个共同的根,您可以简化如下:

server {
    listen 80;
    server_name projects.example.com;

    root /home/bundles
    index index.html;

    location /project_1 {
        try_files $uri $uri/ /project_1/index.html;
    }
    location /project_2 {
        try_files $uri $uri/ /project_2/index.html;
    }
    location / {
        deny all;
    }
}

我添加了 index 指令以避免依赖默认值(这是相同的),并添加了 location 块来拒绝访问项目以外的区域。

我遇到了同样的问题......结果对我来说,默认站点“超越”了我想要的辅助站点并提供默认文件......它允许 IP6 请求,而我的新站点没有。

这是我的例子 access.log:

::1 - - [05/Sep/2020:15:05:16 -0600] "GET / HTTP/1.1" 200 40 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36"

注意到 ::1 位了吗?这是我猜我的浏览器默认的 IP6 请求。所以我只是确保通过更改在我的站点配置文件中为相关站点启用本地 IP6 请求:

listen 80;
server_name example.local;

至:

listen 80;
listen [::]:80;
server_name example.local;

就是这样。