ChatGPT解决这个技术问题 Extra ChatGPT

Nginx——静态文件与根和别名混淆

我需要通过我在 8080 的应用服务器提供我的应用程序,并从一个目录中提供我的静态文件,而无需接触应用程序服务器。我拥有的 nginx 配置是这样的......

    # app server on port 8080
    # nginx listens on port 8123
    server {
            listen          8123;
            access_log      off;

            location /static/ {
                    # root /var/www/app/static/;
                    alias /var/www/app/static/;
                    autoindex off;
            }


            location / {
                    proxy_pass              http://127.0.0.1:8080;
                    proxy_set_header        Host             $host;
                    proxy_set_header        X-Real-IP        $remote_addr;
                    proxy_set_header        X-Forwarded-For  $proxy_add_x_forwarded_for;
            }
    }

现在,有了这个配置,一切正常。请注意,root 指令已被注释掉。

如果我激活 root 并停用 alias - 它会停止工作。但是,当我从 root 中删除尾随 /static/ 时,它又开始工作了。

有人可以解释发生了什么。还请清楚详细地解释 rootalias 之间的区别及其用途。


t
treecoder

rootalias 指令之间有一个非常重要的区别。这种差异存在于处理 rootalias 中指定的路径的方式上。

root

位置部分附加到根部分

最终路径 = 根 + 位置

alias

位置部分被别名部分替换

最终路径 = 别名

为了显示:

假设我们有配置

location /static/ {
    root /var/www/app/static/;
    autoindex off;
}

在这种情况下,Nginx 将派生的最终路径将是

/var/www/app/static/static

这将返回 404,因为 static/ 中没有 static/

这是因为位置部分附加到 root 中指定的路径。因此,对于 root,正确的方法是

location /static/ {
    root /var/www/app/;
    autoindex off;
}

另一方面,使用 alias,位置部分会丢弃。所以对于配置

location /static/ {
    alias /var/www/app/static/;
    autoindex off;           ↑
}                            |
                             pay attention to this trailing slash

最终路径将正确形成为

/var/www/app/static

在某种程度上,这是有道理的。 alias 只是让您定义一个新路径来表示现有的“真实”路径。位置部分是新路径,因此它被替换为真实路径。将其视为符号链接。

另一方面,根不是一条新路径,它包含一些必须与其他信息进行比较才能形成最终路径的信息。因此,位置部分被使用,而不是被丢弃。

别名中尾部斜杠的情况

对于每个 Nginx documentation 是否必须使用尾部斜杠,没有明确的指导方针,但这里和其他地方的人们的共同观察似乎表明它是强制性的。

更多的地方已经讨论过这个问题,虽然不是最终的。

https://serverfault.com/questions/376162/how-can-i-create-a-location-in-nginx-that-works-with-and-without-a-trailing-slas

https://serverfault.com/questions/375602/why-is-my-nginx-alias-not-working


别名路径上的斜杠是必不可少的!
这一切都很好(它帮助我解决了我的配置问题),但我想知道人们可以使用哪些日志记录设置来帮助诊断这些类型的问题?就像,任何会打印到日志的东西,比如“收到的 [...] 请求,与“位置 [...]”配置块匹配,搜索目录 [...]”
@Pistos:将 log_format scripts '$document_root | $uri | > $request'; 放入 http 部分,将 access_log /var/log/nginx/scripts.log scripts; 放入 nginx 配置的 server 部分。
谢谢!确实,别名的尾部斜杠是必不可少的,否则我得到 nginx: [emerg] invalid number of arguments in "alias" directive,并且服务器在重新启动期间停机。
@mafrosis 为什么它很重要?
M
Mahmoud Al-Qudsi

正如@treecoder 所说

在 root 指令的情况下,完整路径将附加到包含位置部分的根,而在别名指令的情况下,仅将不包括位置部分的路径部分附加到别名。

一张图片胜过千言万语

root

https://i.stack.imgur.com/vCgqh.png

alias

https://i.stack.imgur.com/Oahx0.png


第二张图片中的第一个箭头应该是“+”吗?
a
aioobe

在您的情况下,您可以使用 root 指令,因为 location 指令的 $uri 部分与最后一个 root 指令部分相同。

Nginx 文档也给出了建议:当 location 与指令值的最后一部分匹配时: location /images/ { alias /data/w3/images/;最好使用 root 指令: location /images/ { root /data/w3; }

root 指令会将 $uri 附加到路径中。


为什么更好?文档也没有说。
我看到的好处是在使用别名时避免重复给定示例中的 $uri, /images
m
meloncholy

只是对@good_computer 非常有用的答案的快速补充,我想用文件夹替换 URL 的根目录,但前提是它与包含静态文件的子文件夹匹配(我想将其保留为路径的一部分)。

例如,如果请求的文件在 /app/js/app/css 中,则在 /app/location/public/[that folder] 中查找。

我使用正则表达式让它工作。

 location ~ ^/app/((images/|stylesheets/|javascripts/).*)$ {
     alias /home/user/sites/app/public/$1;
     access_log off;
     expires max;
 }

感谢您的回答。我知道这是 3 年后的事了,但是谁能解释使用别名与 root 之间是否存在性能和/或安全性权衡?
@Mina如果可以的话,最好使用root。 (文档 wiki.nginx.org/HttpCoreModule#alias 中有一条评论)
这正是我来这里的目的👍👏
两者都是安全的,但在使用位置不以 / 结尾的别名时要小心。这是一个漏洞github.com/yandex/gixy/blob/master/docs/en/plugins/…
Y
Yao Zhao

alias 用于替换请求路径中的位置部分路径 (LPP),而 root 用于添加到请求路径的前面。

它们是将请求路径映射到最终文件路径的两种方式。

alias 只能在位置块中使用,它会覆盖外部的 root

aliasroot 不能在位置块中一起使用。


T
Tapish
server {
    server_name xyz.com;
    root /home/ubuntu/project_folder/;

    client_max_body_size 10M;
    access_log  /var/log/nginx/project.access.log;
    error_log  /var/log/nginx/project.error.log;

    location /static {
        index index.html;
    }

    location /media {
        alias /home/ubuntu/project/media/;
    }
}

服务器块在 nginx 上运行静态页面。


使用位置不以 / 结尾的别名时要小心。这是一个漏洞 github.com/yandex/gixy/blob/master/docs/en/plugins/… 项目目录中的文件可以根据要求使用 /media.. 显示
J
Jean-Philippe Caruana

虽然不需要我的回答,但我认为有必要添加这个,rootalias 在使用正则表达式时的工作方式不同。

 location ~ /static/my.png$ {
     alias /var/www/static/;
     access_log off;
     expires max;
 }

在这种情况下,正则表达式匹配不会添加别名,nginx 将仅搜索 /var/www/static/ 而不是 /var/www/static/my.png。您必须使用正则表达式捕获。

 location ~ /static/my.png$ {
     root /var/www;
     access_log off;
     expires max;
 }

在这种情况下,匹配的 url 将添加 root,nginx 将搜索 /var/www/static/my.png


佚名

换句话说,保持简短:在 root 的情况下,指定的位置参数是 文件系统的路径和 URI 的一部分。另一方面,对于 alias 指令,location 语句的参数是 URI only 的一部分

因此,alias 是一个不同的名称,它将某个 URI 映射到文件系统中的某个路径,而 root 将 location 参数附加到作为 root 指令参数给出的根路径。


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅