1

This is a bit hard to describe. I basically want nginx to respond with the autoindex instead of the set index.html file, if there's ?listing=true in the URI.

I already tried having this inside my location / {...}, to make it not have any index to show:

if ($arg_listing = "true") { index =404; add_header Content-Type application/json; return 200; } 

But that made the nginx service not start, because apparently you cannot have index or autoindex inside an if block. I know that the if block works at least, because the 200 is returned if I remove the index.

I'm not that experienced in using nginx, so I have no idea what I should do. Here's the full /etc/nginx/sites-enabled/default configuration: https://pastebin.com/iRiMpCk9

Edit: Changed the Pastebin link, because it was the wrong one before.

2 Answers 2

0

Actually, an if nginx directive, when being used in location context, has a very little in common with similar constructions from imperative programming languages. One of the best explanations of how this directive actually works was provided by Yichun Zhang, the author of the famous lua-nginx-module and the OpenResty bundle. In fact, every if directive implicitly creates a nested location that tries to inherit all the declarations from the parent location. There are, however, certain limitations on which directives can be used in the so-called "if in location" context (if they can, it will be explicitly stated in documentation), and you have just encountered one of them (the autoindex directive cannot be used in this context). The most common solution to such situations is to use variables as arguments for these directives.

Unfortunately, not all nginx directives allow the use of variables as their parameters (as a rule, if this is possible, it is explicitly stated in the documentation for the corresponding directive). In particular, the autoindex directive does not support specifying its parameter as a variable whose value could be either on or off. Therefore, indeed, the solution involving the use of two separate named locations with different configurations for this directive is most likely the only possible option. However, as I already said, you can't jump to the named location via rewrite directive. Instead, you can do it via the try_files directive, as described here:

map $arg_listing $autoindex { true @autoindex_on; default @autoindex_off; } server { ... listen, server_name, root and other common "server" block parameters here location / { try_files "" $autoindex; } location @autoindex_on { autoindex on; autoindex_format json; } location @autoindex_off { return 403; } ... your other locations here } 

But keep in mind, that in order for autoindex directive to take effect, there must not be an index file (index.html by default) in the requested web server directory.

4
  • I was not able to get this working. It always sent the index.html file instead of the autoindex and at some point, my browser (firefox) completely stopped accessing the page and just said "This page isn't redirecting properly." Commented Jan 26 at 14:36
  • After some more tinkering around, setting the index to some random file that doesn't exist before all the locations has fixed the issue. Then I just had to set index index.html ...; inside the @autoindex_off location. Main brain was just not braining. Thank you for your help, really appreciate it! Commented Jan 26 at 14:46
  • @MarcPG This is exactly what I wrote: in order for autoindex directive to take effect, there must not be an index file (index.html by default) in the requested web server directory. Unfortunatelly, as far as I know there is no way to completely disable index module (i.e. specifying something like index off;). Commented Jan 26 at 15:05
  • @MarcPG Added some more explanations to the answer, maybe you'd find them of interest. Commented Jan 26 at 19:25
-1

try this:

server { listen 80; server_name example.com; root /var/www/html; # Default behavior: Serve files or the index.html location / { try_files $uri $uri/ /index.html; } # Named location for autoindex location @listing { autoindex on; autoindex_exact_size off; # Optional: Makes file sizes human-readable autoindex_localtime on; # Optional: Displays local times for files } # Rewrite based on the presence of the query parameter location / { if ($arg_listing = "true") { rewrite ^ /@listing last; } try_files $uri $uri/ /index.html; } } 
1
  • This won't work, resulting in nginx: [emerg] duplicate location "/" in ... error message. Moreover, you can't jump to the named location via rewrite directive. Commented Jan 26 at 13:53

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.