如何在 Nginx map 指令中使用通配符?

如何在 Nginx map 指令中使用通配符?

我正在尝试使用 Nginx 来提供由 Web 应用程序生成的缓存文件,并发现了一个潜在的问题;url 空间很宽,将超过 32000 个子目录的 Ext3 限制。

我想拆分子目录,比如说,创建一个两级文件系统缓存。因此,我目前缓存文件的位置

/var/cache/www/arbitrary_directory_name/index.html

我会把它存储在类似

/var/cache/www/a/r/arbitrary_directory_name/index.html

我的问题是我无法获得try_files,甚至rewrite无法进行映射。我对这个问题的搜索让我相信我需要做这样的事情(大量缩写):

http {
    map $request_uri $prefix {
        /aa*   a/a;
        /ab*   a/b;
        /ac*   a/c;
        ...
        /zz*   z/z;
    }

    location / {
        try_files /var/cache/www/$prefix/$request_uri/index.html @fallback;

        # or
        # if (-f /var/cache/www/$prefix/$request_uri/index.html) {
        #     rewrite ^(.*)$ /var/cache/www/$prefix/$1/index.html;
        # }
    }
}

但我无法让/aa*模式匹配传入的 uri。如果没有*,它将匹配精确的 uri,但我无法让它仅匹配前两个字符。

Nginx 文档建议允许使用通配符,但我看不出有什么方法可以让它们工作。有办法吗?我是不是错过了一些简单的东西?还是我的方法不对?

答案1

我怀疑只有特殊的主机名模式。您需要使用正则表达式来实现这一点,因此您的地图应该是这样的:

map $request_uri $prefix {
    ~^/aa(?<suffix>.*)$ /a/a/$suffix;
    ...
}

答案2

仔细阅读 Nginx 文档后发现,我想要的功能是 Rewrite 模块的一部分。我认为需要的是:

map $request_uri $prefix {
    /aa* a/a;
    /ab* a/b;
    /ac* a/c;
    ...
    /zz* z/z;
}

可以轻松实现:

if ($request_uri ~= "/(\w)(\w)(.*)") {
    set $prefix $1/$2;
}

然后 try_files 指令的工作方式如下:

location / {
    root /var/www/cache;
    try_files /$prefix$request_uri @fallback;
}

相关内容