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

标签 nginx configuration server configuration-files nginx-location

我有一个在 Ubuntu 16.04.2 LTS 上运行的 nginx 版本: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 block 中,我将 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 ...
}

感谢您的帮助!


编辑

我的回答

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

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展示如何解决第二个问题 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.

在我的具体情况下,这将像这样翻译;

使用 root 时,nginx 尝试访问的路径将为 /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 目录。

这就是我使用别名的原因。

我希望这会有所帮助。

最佳答案

你有:

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 应返回您的 /project_1/index.html 内容。

但是,找不到 URI /project_1 - 因此返回 /index.html。 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 block 来拒绝访问项目外部的区域。

关于Nginx 正在提供默认内容而不是我的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48688492/

相关文章:

node.js - comet 与 node.js 的 250k 连接

python - 从 nginx 传递到 uwsgi 的客户端连接 ID

python - CherryPy配置tools.staticdir.root问题

tomcat - 使用zabbix监控其他Tomcat服务器

javascript - Nodejs : ReferenceError: express is not defined

ruby-on-rails - 部署react-native应用程序但不在应用程序商店或Play商店上

nginx - 是否可以通过 Kubernetes 中具有 OpenVPN 和 Nginx 反向代理的 Pod 路由流量?

ubuntu - 示例 nginx Dockerfile 有问题

asp.net-mvc - 网页:Version setting do?是什么意思

ssl - HTTP2 不适用于 Nginx 1.10.1、Openssl 1.2.h 和 Chrome 51.0.2704.103