Nginx location match multiple extensions unless path starts with specific word

7,905

Solution 1

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

Solution 2

Write location "/rails" block above of defined block for safety.

Quotes from the nginx location description

To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the location with the longest matching prefix is selected and remembered. Then regular expressions are checked, in the order of their appearance in the configuration file. The search of regular expressions terminates on the first match, and the corresponding configuration is used. If no match with a regular expression is found then the configuration of the prefix location remembered earlier is used.

Share:
7,905

Related videos on Youtube

Felipe Zavan
Author by

Felipe Zavan

Updated on September 18, 2022

Comments

  • Felipe Zavan
    Felipe Zavan over 1 year

    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.

  • Felipe Zavan
    Felipe Zavan over 5 years
    I already have a “location /“ block above that sends the request to rails/puma, this way i’d need to declare it again with the same contents but with “location /rails” instead, no? I don’t send just “/rails” paths to rails.
  • Felipe Zavan
    Felipe Zavan over 5 years
    I tried a negative lookahead before but I must've done something wrong, this one works perfectly. Thank you!