Lesson 5 / 25

Location Matching Rules

Predict which location block NGINX chooses for a URI.

The precedence everybody gets wrong

Within a server, NGINX selects a location for the request URI using these rules. 1. An exact match location = /path wins immediately. 2. Otherwise NGINX finds the longest matching prefix among plain prefix locations (location /images/) and remembers it. If that longest prefix is marked ^~, it is used and regular expressions are not checked. 3. Otherwise NGINX checks regular-expression locations (~ case-sensitive, ~* case-insensitive) in the order they appear in the file; the first that matches wins. 4. If no regex matches, the remembered longest prefix is used. So a regex such as location ~* \.(png|jpg)$ overrides a longer prefix like location /images/ unless that prefix uses ^~. Named locations (location @fallback) are not matched directly; they are targets for try_files and error_page. Keep configurations readable by preferring prefix locations and using regexes sparingly.

Which location wins?

Comments show the location chosen for each request URI.

location = /health           { return 200 "ok\n"; }      # exact
location /                   { proxy_pass http://app; }   # shortest prefix, fallback
location /static/            { root /var/www; }           # prefix
location ^~ /static/vendor/  { root /var/www; expires 30d; }  # prefix, blocks regex
location ~* \.(png|jpg|svg)$ { expires 7d; root /var/www; }  # regex

# /health                   -> = /health
# /static/app.css           -> /static/                 (no regex matches .css)
# /static/logo.png          -> ~* \.(png|jpg|svg)$      (regex beats a plain prefix)
# /static/vendor/icon.svg   -> ^~ /static/vendor/       (^~ stops regex checks)
# /orders/42                -> /

Sorting post by address

An exact address gets hand-delivered first. Otherwise the clerk finds the most specific postcode bin, but a few special rules on the wall (regexes) are checked in order and can redirect the letter, unless the bin is marked "do not reroute" (^~).

Quick check: A request for /static/logo.png matches `location /static/` and `location ~* \.png$`. Neither uses ^~. Which wins?

  • location /static/, because it is longer
  • location ~* \.png$, because regex locations are checked after the prefix and the first matching regex wins
  • Whichever appears first in the file, always
  • Neither; NGINX returns 404
Answer

location ~* \.png$, because regex locations are checked after the prefix and the first matching regex wins — A matching regex overrides the longest prefix unless that prefix is marked ^~.