Why Nginx Matches Locations the Way It Does: Unraveling Literal vs Regex Rules
This article explains Nginx's location matching order, clarifying the difference between literal (prefix) and regular‑expression locations, how exact, ^~, and = prefixes affect the search, and provides step‑by‑step examples with curl tests to illustrate the resulting behavior.
Background
Nginx uses the location directive to select configuration blocks based on the request URI. The directive can be prefixed with =, ^~, ~, ~*, or @, or have no prefix at all. Understanding the matching order is essential for writing correct access‑control rules.
Matching Order Overview
The matching process consists of four steps:
Exact match ( = prefix) : If a location with = matches the URI exactly, the search stops immediately.
Literal string locations : All remaining locations that use literal strings are examined. If the best literal match uses the ^~ prefix, the search stops and regular‑expression locations are ignored.
Regular‑expression locations : These are checked in the order they appear in the configuration file. The first regex that matches stops further regex evaluation.
Result selection : If a regex matched, its result is used; otherwise the best literal‑string match from step 2 is applied.
In short, regular‑expression locations yield to exact literal matches but can override the "maximum‑prefix" literal match.
Key Prefixes Explained
=– exact match only; stops all further matching. ^~ – non‑regex prefix; once matched, regular‑expression locations are not evaluated. ~ – case‑sensitive regex. ~* – case‑insensitive regex. @ – defines a named location used only for internal redirects (e.g., via error_page).
Practical Examples
#1 Literal then Regex
server {
listen 9090;
server_name localhost;
location / {
root html;
index index.html index.htm;
deny all;
}
location ~ \.html$ {
allow all;
}
}Tested with curl:
# curl http://localhost:9090/ → 403 Forbidden (matched exact literal "/")
# curl http://localhost:9090/index.html → Welcome to nginx! (regex ".html$" overrides the prefix match)
# curl http://localhost:9090/index_notfound.html → 404 Not Found (regex matches but file missing)#2 Implicit Exact Match
Adding an exact‑match location stops regex evaluation for that URI:
server {
listen 9090;
server_name localhost;
location /exact/match.html { allow all; }
location / { root html; index index.html; deny all; }
location ~ \.html$ { allow all; }
}Requesting /exact/match.html returns 404 because the exact‑match location is defined but the file does not exist; other URIs behave as in example #1.
#3 Using ^~ to Block Regex Search
server {
listen 9090;
server_name localhost;
location ^~ / { root html; index index.html; deny all; }
location ~ \.html$ { allow all; }
}Now /index.html also returns 403 Forbidden because the ^~ prefix stops the later regex from being considered.
#4 Using = for Strict Exact Matching
server {
listen 9090;
server_name localhost;
location = / { root html; index index.html; deny all; }
location ~ \.html$ { allow all; }
}Only the request for / is blocked; other URIs that end with .html are served normally.
#5 Regex Order Matters
When multiple regex locations exist, the one that appears first in the file wins.
# Config A
location ~ \.html$ { allow all; }
location ~ ^/prefix/.*\.html$ { deny all; }
# Config B (order swapped)
location ~ ^/prefix/.*\.html$ { deny all; }
location ~ \.html$ { allow all; }In Config A, /prefix/file.html is allowed (first regex matches). In Config B, the same URI is denied because the more specific regex appears earlier.
#6 Named Location with @
server {
listen 9090;
server_name localhost;
location / { root html; index index.html; allow all; }
error_page 404 = @fallback;
location @fallback { proxy_pass http://www.baidu.com; }
}If a requested file is missing, Nginx internally redirects to @fallback, which proxies the request to Baidu. This demonstrates how @ locations are used for internal redirects rather than normal client‑visible routing.
Important Takeaways
Literal (prefix) locations are always evaluated before any regex locations.
Exact literal matches ( =) and ^~ prefixes stop further regex processing.
When a literal location matches by maximum prefix, regex locations are still checked and can override the result.
Regex locations are evaluated in the order they appear; the first match wins.
Named locations ( @name) are only reachable via internal redirects such as error_page or try_files.
Reference
Original article: https://www.cnblogs.com/zhaojiankai/p/10606565.html
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
