Nginx:从不同的根和位置提供JPG图像

时间:2013-09-30 19:07:51

标签: nginx

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

我想将URL“/trends/123.jpg”链接到trend文件夹,将“/avatars/23.jpg”链接到avatar等等。

配置1:

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”永远不匹配/趋势/位置,为什么?

配置2:

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:与缓存内容的最后一条规则不匹配。从不同位置/ root服务器JPG文件的最佳方法是什么?

3 个答案:

答案 0 :(得分:26)

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

  1. 匹配地点的顺序;和
  2. 匹配位置时会发生什么。
  3. 我首先会解释它是如何工作的,然后我会解决你的配置问题。

    工作原理

    位置匹配

    您可以找到关于此nginx wiki page的详细信息,但我始终认为措辞令人困惑。 (它在行为描述中混合了实现细节。)这意味着位置按以下顺序匹配:

    1. 完全匹配location = /robots.txt
    2. 急切的非正则表达式前缀,如location ^~ /trends/
    3. 正则表达式匹配location ~* \.(jpg|png)或区分大小写location ~ \.(jpg|png)
    4. 懒惰的非正则表达式前缀,如location /trends/location /
    5. 如果多个正则表达式匹配,则第一个匹配胜过其他正则表达式。如果多个非正则表达式前缀匹配,我认为它会选择最具体的匹配 - 我会检查并更新。

      位置行为

      匹配位置负责提供指定内容。它还负责提供缓存控制头等。您可以使用与特定网址格式匹配的位置来应用特定标头,但该位置也必须提供内容。如果它无法提供内容,您很可能会收到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;
      

答案 1 :(得分:4)

我通常不会使用别名,但我认为这是使用别名的一个很好的示例,您可以将您的缓存设置放在/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 1}}

答案 2 :(得分:0)

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

因此,您应确保在定义为正则表达式

的任何其他位置之前出现location ~\.jpg$