NGINX – Match Multiple Extensions Unless Path Starts with Specific Word

nginxpattern matchingregexurl

How can I write a location block that matches any path ending in the following extensions:

jpg|jpeg|gif|css|png|js|ico|json|xml|txt|html

Unless the path starts with "/rails" (eg: /rails/randomstring/image.png)?

I currently have this basic block:

location ~* \.(jpg|jpeg|gif|css|png|js|ico|json|xml|txt|html)$ {
  gzip_static on;
  gzip on;
  expires max;
  add_header Cache-Control public;
}

But this would match "/rails/randomstring/image.png" and I don't want that.

Best Answer

You can use location ^~ definition, for example:

location ^~ /rails/ {
    # your directives for "/rails/..." URIs here
}

location ~* \.(jpg|jpeg|gif|css|png|js|ico|json|xml|txt|html)$ {
    gzip_static on;
    gzip on;
    expires max;
    add_header Cache-Control public;
}

According to documentation:

If the longest matching prefix location has the “^~” modifier then regular expressions are not checked.

Update

Another way to do this without declaring extra location block is to use negative regex assertion:

location ~ ^(?!/rails/).*\.(jpg|jpeg|gif|css|png|js|ico|json|xml|txt|html)$ {
    gzip_static on;
    gzip on;
    expires max;
    add_header Cache-Control public;
}