How location blocks are matched

NGINX · Essentials · 12 min

Most confusing NGINX behaviour comes from a different location matching than the one you expected.

A server usually contains several location blocks, and exactly one handles each request. The modifiers are:

  • location = /path: exact match.
  • location /prefix: prefix match.
  • location ^~ /prefix: prefix match that, if it is the longest, disables regex checking.
  • location ~ regex (case-sensitive) and location ~* regex (case-insensitive).

The algorithm, which does not simply follow file order:

  • If an = location matches exactly, use it and stop.
  • Find the longest matching prefix location and remember it. If it has ^~, use it and stop.
  • Check regular expression locations in the order they appear; the first match wins.
  • If no regex matches, use the remembered longest prefix.

So a regex like ~ \.php$ beats the prefix /uploads/ for /uploads/x.php, unless that prefix is written ^~ /uploads/. Order matters only among regexes.

Matching uses the normalized URI path, without the query string. Locations can be nested, and named locations (location @fallback) are used only as targets of try_files or error_page, never matched directly.

Example

server {
    listen 80;
    location = / { return 200 "exact root\n"; }
    location / { return 200 "prefix /\n"; }
    location /images/ { return 200 "prefix images\n"; }
    location ^~ /static/ { return 200 "static, no regex\n"; }
    location ~* \.(png|jpg)$ { return 200 "regex image\n"; }
}
# GET /              -> exact root
# GET /about         -> prefix /
# GET /images/a.png  -> regex image   (regex beats a normal prefix)
# GET /static/a.png  -> static, no regex   (^~ stops regex search)
# GET /images/a.txt  -> prefix images

Remember

  • = exact wins immediately; ^~ longest prefix skips regexes
  • Otherwise the first matching regex in file order beats prefixes
  • Only one location handles a request

Watch out for

  • Expecting the longest prefix to win over a regex; regexes are checked after prefixes and win if they match.

Check yourself

  1. Locations /docs/ (prefix) and ~ \.pdf$ (regex) exist. Which handles /docs/guide.pdf?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: nginx.org/en/docs/http/ngx_http_core_module.html#location