Location Matching and Routing
Introduction
Nginx routes requests using location blocks. Prefix, exact, and regex matches follow priority rules—getting them wrong sends API traffic to static files or vice versa. This chapter explains match types, order of evaluation, and a practical split between /, /assets/, and /api/.
Prerequisites
Location Match Types
| Modifier | Syntax | Matches |
|---|---|---|
| Exact | location = /favicon.ico | URI exactly /favicon.ico |
| Prefer prefix | location ^~ /static/ | Prefix; stops regex search if matched |
| Regex (case sensitive) | location ~ \.php$ | Pattern in URI |
| Regex (case insensitive) | location ~* \.(jpg|png)$ | Pattern, ignore case |
| Prefix (default) | location /api/ | URI starting with /api/ |
Priority Order (Simplified)
Nginx chooses one location per request:
- Exact
=— highest if match - Longest prefix match among
^~and plain prefix - If longest prefix is plain (not
^~), try regex~/~*in config file order; first match wins - If no regex, use the longest prefix match
Tip
Draw a Table for Complex Sites
List your paths (/, /api/, /assets/, /admin/) and assign location types before editing config.
Examples
Code explanation:
= /health— exact probe, no file lookup^~ /assets/— static hashed files; regex locations skipped if this prefix matches/api/— proxy before catch-all//— SPA fallback toindex.html
Longest Prefix Wins
location / {
return 200 'root';
}
location /api/ {
return 200 'api';
}Request /api/users → api (longer prefix /api/ beats /).
Regex for File Extensions
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff2)$ {
expires 30d;
try_files $uri =404;
}Useful when not using a dedicated /assets/ prefix—be careful regex order if multiple patterns overlap.
Named Locations (Preview)
location / {
try_files $uri @backend;
}
location @backend {
proxy_pass http://127.0.0.1:8080;
include /etc/nginx/proxy_params;
}@name — internal redirect target, not client-visible URL. Used with try_files and error_page.
default_server and server_name
Multiple server blocks on port 80:
server {
listen 80 default_server;
server_name _;
return 444;
}Catches requests with unknown Host header—optional hardening.
Debugging Which location Matched
Add temporary headers (remove after debug):
add_header X-Debug-Location "api" always;Only inside one location at a time—or use error_log notice and rewrite_log (verbose).
Test paths:
curl -I http://app.example.com/
curl -I http://app.example.com/api/items
curl -I http://app.example.com/assets/main.cssAnti-Patterns
| Mistake | Effect |
|---|---|
Catch-all / before /api/ in file order without prefix length | Still OK if prefixes differ—longest wins; confusion is order of regex vs prefix |
Regex catches .js but proxy needed | API JSON mistaken—use ^~ or precise prefixes |
| Duplicate overlapping regex | First in file wins—unpredictable |
Full Split-Host Pattern
FAQ
location order in file?
Prefix length and match type matter more than physical order—except regex order among regexes.
Why ^~?
Stops searching regex locations when prefix matches—faster and predictable for /static/.
Can one URI match two locations?
Nginx picks one winner per request.
internal locations?
location @foo and internal directive restrict internal redirects only.
Case sensitivity in paths?
URI paths are case-sensitive on Linux backends—/API/ ≠ /api/.
Merge with map?
map directive sets variables for complex routing—advanced alternative to many locations.