I encountered this by accident. There are two location blocks in my nginx config:
location /static/ {
alias /app/static/;
}
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off; log_not_found off; expires max;
}
The second one was copy-pasted from an older configuration by mistake. The problem I encountered was that my images were not being served, and by turning on nginx debug and looking into it, nginx has matched the second location
block for the image file (which is located within the /static
tree), and then stopped processing and attempted to load it from the root path - which fails.
So, Is there a way to both have a working /static
location alias (or actually multiple such aliases) and have some rules that apply just to certain file extensions?
I can probably move the image matching rule within the /static
location, but what if I have dozen of such aliases and I'd like to add some special image rules to all of them? Can I tell nginx to continue looking even if it matches a location rule?
Nginx chooses a single location
to process the current request.
Your current configuration could be improved as follows:
location ^~ /static/ {
root /app;
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off; log_not_found off; expires max;
}
}
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off; log_not_found off; expires max;
}
Use ^~
so the prefix location takes precedence over the regular expression location.
The root
statement should be used instead of alias
where possible, as indicated here.
And, as you suggested, location blocks can be nested.
If you have many locations with a different root
or alias
, you could use a include
statement to pull the same snippet into multiple points in your configuration.
Alternatively, both the access_log
and expires
directives accept a variable, examples are shown here and here.
So, logic is applied to the original statements in http
or server
context.
You would need two maps, both testing $request_uri
with a pattern like:
~*\.(ogg|ogv|svg...wav|bmp|rtf)(\?|$)
The middle part is skipped to better see the end of the pattern.
AFAIK, log_not_found
does not accept variables.
This directive controls what Nginx writes to its error log. If you need to suppress 404 responses also generating file not found entries in the error log, use:
try_files $uri $uri/ =404;
in the respective location
blocks, which is similar to the default behaviour, but will suppress writing file not found errors to the error log.