Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I am trying to use Nginx to served cached files produced by a web application, and have spotted a potential problem; that the url-space is wide, and will exceed the Ext3 limit of 32000 subdirectories.

I would like to break up the subdirectories, making, say, a two-level filesystem cache. So, where I am currently caching a file at

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

I would store that instead at something like

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

My trouble is that I can't get try_files, or even rewrite to make that mapping. My searching on the subject leads me to believe that I need to do something like this (heavily abbreviated):

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;
        # }
    }
}

But I can't get the /aa* pattern to match the incoming uri. Without the *, it will match an exact uri, but I can't get it to match just the first two characters.

The Nginx documentation suggests that wildcards should be allowed, but I can't see a way to get them to work. Is there a way to do this? Am I missing something simple? Or am I going about this the wrong way?

share|improve this question
add comment

2 Answers

I suspect that globs are only supported with the special hostname mode. You need to use regular expressions to achieve this, so your map should look like this:

map $request_uri $prefix {
    ~^/aa(?<suffix>.*)$ /a/a/$suffix;
    ...
}
share|improve this answer
add comment

A more careful reading of the Nginx documentation reveals that the functionality that I want is part of the Rewrite module. What I thought needed to be:

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

is easily implemented with this:

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

And then the try_files directive works like this:

location / {
    root /var/www/cache;
    try_files /$prefix$request_uri @fallback;
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.