0

Occasionally I need some plain browsable directories on my site. I do achieve this with the following config:

  ...
  root /var/www/example.com/file_dump;
  autoindex off;

... location / { try_files $uri /error.html @django; }

location @django { ... }

location ~ ^/test/.+/? { autoindex on; }

So if I would create a directory /var/www/example.com/file_dump/test/something, I would get the list of files at the address example.com/test/something.

I have tried to be smarter than this with the following config:

  location / {
    if (!-d test/$uri) {
      autoindex on;
    }
    try_files $uri /error.html @django;
  }

But I've met the following error:

nginx: [emerg] "autoindex" directive is not allowed here...

Why Nginx does not allow autoindex within the conditional statements? Can I enable autoindex dynamically by the other means?

NarūnasK
  • 378
  • I'm not sure what answer you are expecting. What about "nginx does not allow autoindex directive within the if block in location because if in location is not listed as allowed contexts for the autoindex directive (unlike some others)"? nginx conditional statements is a very special thing and should be used with caution. The best practice is to avoid the if whenever possible. – Ivan Shatsky Nov 23 '20 at 16:12
  • if is still evil. – Michael Hampton Nov 23 '20 at 16:25
  • @IvanShatsky I guess my question is more about whether I can employ autoindex dynamically by the other means, thus without the if. @MichaelHampton Thank you, I'm aware of the ifisevil. – NarūnasK Nov 23 '20 at 18:28
  • @NarūnasK Documentation for every nginx directive specifies the context (http, server, location, if in location) where that directive can be used. – Ivan Shatsky Nov 23 '20 at 18:57

1 Answers1

0

Since the enabled/disabled autoindex feature is a location-only property, your only way is to use different locations for autoindex-enabled and autoindex-disabled requests. Although some nginx directives allow using the variables as their arguments, autoindex is not one of those.

It is completely unclear what do you want to achieve checking the if (!-d test/$uri) { ... } statement. If that was meaning if $uri is some existing directory under /var/www/example.com/file_dump/test/ directory, here is a possible workaround:

server {
    ...
    set $is_dir loc_default;
    if (-d $document_root$uri) { set $is_dir loc_index; }
    set $loc loc_default;
    if ($uri ~ ^/test/.) { set $loc $is_dir; }
location / {
    try_files /dev/null @$loc;
}
location @loc_default {
    try_files $uri /error.html @django;
}
location @loc_index {
    autoindex on;
    # try_files $uri $uri/ =404 is assumed by default
}
location @django {
    ...
}

}

However it is absolutely meaningless to check if the $uri is an existing directory, using just

    set $loc loc_default;
    if ($uri ~ ^/test/.) { set $loc loc_index; }

will give you the same behavior.

Same thing can be achieved using the map block:

map $uri $loc {
    ~^/test/.    loc_index;
    # you can check multiply patterns here, for example
    ~^/another/  loc_index;
    # if none matched
    default      loc_default;
}
server {
    ...
    location / {
        try_files /dev/null @$loc;
    }
    location @loc_default {
        try_files $uri /error.html @django;
    }
    location @loc_index {
        autoindex on;
        # try_files $uri $uri/ =404 is assumed by default
    }
    location @django {
        ...
    }
}

The try_files /dev/null <named_location> trick is taken from this excellent answer.

Ivan Shatsky
  • 2,866