Backend Development 28 min read

Understanding Nginx Location Matching: Rules, Prefixes, and Practical Examples

This article explains Nginx's location matching order, distinguishes literal and regex locations, clarifies the effects of prefixes like =, ^~, and @, provides detailed configuration examples, test results, and installation tips for the rewrite module.

Raymond Ops
Raymond Ops
Raymond Ops
Understanding Nginx Location Matching: Rules, Prefixes, and Practical Examples

Official Documentation Explanation

Reference: http://wiki.nginx.org/NginxHttpCoreModule#location

location syntax: location [=|~|~*|^~|@] /uri/ { … }

default: no

context: server

This directive allows different configurations depending on the URI.

Literal vs. Regular‑Expression Locations

Literal locations use plain strings, while regular‑expression locations use patterns prefixed with

~

(case‑sensitive) or

~*

(case‑insensitive). The prefixes

=

,

^~

, and

@

have special meanings.

Matching Order

When processing a request, Nginx checks locations in the following order:

Exact match directives with the "=" prefix. If found, search stops.

All remaining literal string locations. If a match uses the "^~" prefix, search stops.

Regular‑expression locations, in the order they appear in the configuration file. The first matching regex stops further searching.

If a regex matched, its result is used; otherwise the result from step 2 is used.

Literal strings are matched first; the most specific (longest) prefix wins. If the best literal match is an exact match (or uses

=

or

^~

), Nginx does not evaluate regular‑expression locations.

Prefix Effects

=

– exact match only; stops further searching.

^~

– non‑regex prefix; stops regex search even if the match is a longest‑prefix match.

@

– defines a named location used for internal redirects (e.g., with

error_page

).

Practical Examples

Example 1 – Literal then Regex

<code>server {
    listen 9090;
    server_name localhost;
    location / {
        root html;
        index index.html index.htm;
        deny all;
    }
    location ~ \.html$ {
        allow all;
    }
}
</code>

Requests:

curl http://localhost:9090/

→ 403 Forbidden (matched exact literal

/

with

deny all

).

curl http://localhost:9090/index.html

→ Welcome page (literal

/

matches as longest prefix, then regex

~ \.html$

overrides and allows access).

curl http://localhost:9090/index_notfound.html

→ 404 Not Found (allowed by regex but file missing).

curl http://localhost:9090/index.txt

→ 403 Forbidden (no regex match, longest‑prefix literal applies).

Example 2 – Exact Literal Match Stops Regex

<code>server {
    listen 9090;
    server_name localhost;
    location /exact/match.html { allow all; }
    location / { root html; index index.html index.htm; deny all; }
    location ~ \.html$ { allow all; }
}
</code>

Request

curl http://localhost:9090/exact/match.html

returns 404 because the exact literal location is matched first and prevents the regex from being evaluated.

Example 3 – Using ^~ Prefix

<code>server {
    listen 9090;
    server_name localhost;
    location /exact/match.html { allow all; }
    location ^~ / { root html; index index.html index.htm; deny all; }
    location ~ \.html$ { allow all; }
}
</code>

Now any request starting with

/

(including

/index.html

) is stopped after the

^~ /

block, so the regex no longer overrides it.

Example 4 – Using = Prefix

<code>server {
    listen 9090;
    server_name localhost;
    location /exact/match.html { allow all; }
    location = / { root html; index index.html index.htm; deny all; }
    location ~ \.html$ { allow all; }
}
</code>

The

= /

block matches only the root URI exactly; other URIs follow the normal literal‑then‑regex order.

Example 5 – Regex Order Depends on Definition Sequence

<code># Config 3.1
location ~ \.html$ { allow all; }
location ~ ^/prefix/.*\.html$ { deny all; }

# Config 3.2 (reversed order)
location ~ ^/prefix/.*\.html$ { deny all; }
location ~ \.html$ { allow all; }
</code>

In Config 3.2, a request to

/prefix/regextest.html

is denied because the first regex (the prefix‑specific one) matches and stops further searching.

Named Location with @

<code>server {
    listen 9090;
    server_name localhost;
    location / { root html; index index.html index.htm; allow all; }
    error_page 404 = @fallback;
    location @fallback { proxy_pass http://www.baidu.com; }
}
</code>

If a requested URI does not exist, Nginx internally redirects to

@fallback

, which proxies the request to an external site.

Installation Note for the Rewrite Module

<code>wget http://nginx.org/download/nginx-1.4.6.tar.gz
tar zxvf nginx-1.4.6.tar.gz
./configure
make
make install
</code>

If

./configure

fails with

the HTTP rewrite module requires the PCRE library

, install PCRE development packages (e.g.,

yum -y install pcre-devel openssl openssl-devel

) or disable the module with

--without-http_rewrite_module

.

Key Takeaways

Literal locations are evaluated before regular‑expression locations.

Exact matches (

=

) and

^~

prefixes stop further regex evaluation.

Regular‑expression locations are checked in the order they appear.

Named locations (

@

) are used for internal redirects such as custom error handling.

The rewrite module depends on the PCRE library; ensure it is installed before configuring Nginx.

BackendNginxServer Configurationregexlocation
Raymond Ops
Written by

Raymond Ops

Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.