13

我有 3 个不同的存储区域:“头像”、“文章”、“趋势”,用于存储我的图像。

我想将 URL“/trends/123.jpg”“链接”到趋势文件夹,“/avatars/23.jpg”链接到头像等等。

配置一:

server
{
    listen 8089;
    server_name localhost;

    root /var/www;

    location /trends/
    {
            alias  /var/storage/hottrend/;
    }

    location ~* ^.+\.(jpeg|gif|png|jpg)
    {
            add_header Cache-control "public";
            access_log   off;
            expires      90d;
    }
}

配置 1:“GET /trends/123.jpg”永远不匹配 /trends/ 位置,为什么?

配置二:

server
{
    listen 8089;
    server_name localhost;

    root /var/www;

    location ~ ^/trends/(.*)\.jpg$
    {
            rewrite ^/trends/(.*)$ /$1 break;

            root  /var/storage/hottrend;
    }

    location ~* ^.+\.(jpeg|gif|png|jpg)
    {
            add_header Cache-control "public";
            access_log   off;
            expires      90d;
    }
}

配置 2:与缓存内容的最后一条规则不匹配。来自不同位置/根的服务器 JPG 文件的最佳方法是什么?

4

3 回答 3

33

这两种配置有不同但相关的问题。这两个问题是:

  1. 位置顺序匹配;和
  2. 匹配位置时会发生什么。

我将首先解释它是如何工作的,然后我将解决您的配置问题。

这个怎么运作

位置匹配

您可以在此nginx wiki 页面上找到详细信息,但我一直觉得措辞令人困惑。(它在行为描述中混合了实现细节。)这意味着位置按以下顺序匹配:

  1. 完全匹配,例如location = /robots.txt
  2. 急切的非正则表达式前缀,例如location ^~ /trends/
  3. 正则表达式匹配location ~* \.(jpg|png), 或区分大小写location ~ \.(jpg|png)
  4. 惰性非正则表达式前缀,如location /trends/orlocation /

如果多个正则表达式匹配,则第一个匹配击败其他匹配。如果多个非正则表达式前缀匹配,我认为它会选择最具体的匹配——我会检查并更新。

位置行为

匹配位置负责提供指定内容。它还负责提供缓存控制标头等。您可以拥有与特定 URL 模式匹配的位置以应用特定标头,但该位置还必须提供内容。如果它无法提供内容,您很可能会收到 404 错误——它不会寻找其他匹配的位置。

最后,如果您在某个位置进行了重写,请格外小心。内部重定向可能比某些指令更早发生,在这种情况下,在重定向导致再次搜索位置之前,这些指令可能不适用。

配置1

您的趋势位置是一个惰性非正则表达式前缀,因此只有在正则表达式位置不匹配时才会匹配。您可以通过使用急切的非正则表达式匹配来解决此问题,例如

location ^~ /trends {
    ...
}

但是,这样做会突出另一个配置问题。

配置2

您有两个可能与 jpg 文件匹配的位置。只有一个人会成功。如果第一个匹配,则不会应用第二个位置的缓存控制。如果第二个匹配,则别名将不会生效。

解决方法是确保在匹配的位置应用所有需要的指令。您可以在一个文件中明确表示,例如

location ^~ /trends
{
    alias /var/storage/hottrend;

    add_header Cache-control "public";
    access_log   off;
    expires      90d;
}

location ~* ^.+\.(jpeg|gif|png|jpg)
{
    add_header Cache-control "public";
    access_log   off;
    expires      90d;
}

管理必须应用于多个位置的指令的更简洁的解决方案是将这些详细信息分解到另一个文件中,然后include在两个位置进行处理。(Mohammad AbuShady 在他的例子中就是这样做的。)这样的事情:

# Inside your main .conf
location ^~ /trends
{
    alias /var/storage/hottrend;
    include image-headers.conf;
}

location ~* ^.+\.(jpeg|gif|png|jpg)
{
    include image-headers.conf;
}

# Inside image-headers.conf
add_header Cache-control "public";
access_log   off;
expires      90d;
于 2013-10-01T08:59:17.740 回答
5

好吧,我通常不使用别名,但我认为这是使用别名的一个很好的例子,您可以将缓存设置放入/etc/nginx/image_caching.conf. 如果trends仅用于图像,我不会尝试使正则表达式复杂化并假设它总是有图像

location /trends {
    alias /var/storage/trends;
    include /etc/nginx/image_caching.conf;
}

对于您的示例配置,您不应该在/trends内部添加,root /var/storage/trends;因为它已经在该位置使用,所以我认为它会显示,404因为它正在寻找/var/storage/trends/trends/123.jpg

于 2013-09-30T22:43:16.980 回答
0

Nginx 按照它们在配置文件中出现的顺序检查定义为正则表达式的位置,并将该位置与第一个匹配的表达式一起使用。

因此,您应该确保location ~\.jpg$出现在定义为正则表达式的任何其他位置之前

于 2013-10-01T07:51:15.763 回答