When working with Nginx configuration, there are cases where you need to match all paths under a specific prefix except one particular path. The common approach using location ~ ^/newsletter/(.*)$
will indeed match all paths starting with /newsletter/
, but we need to exclude /newsletter/one
specifically.
The most elegant solution uses regex negative lookahead:
location ~ ^/newsletter/(?!one($|/)).*$ {
# Your configuration here
# This will match /newsletter/anything
# but NOT /newsletter/one
# and NOT /newsletter/one/extra
}
For those who prefer different methods, here are two additional solutions:
Method 1: Separate Location Blocks
location = /newsletter/one {
# Configuration for the excluded path
# (or empty if you want to bypass it)
}
location /newsletter/ {
# Configuration for all other newsletter paths
}
Method 2: Using Regex Alternation
location ~ ^/newsletter/((?!one($|/)).*)$ {
# Configuration here
# $1 now contains the path after /newsletter/
# excluding 'one'
}
Here's a complete configuration example for handling newsletter endpoints:
server {
listen 80;
server_name example.com;
# Handle the excluded path
location = /newsletter/one {
proxy_pass http://special_backend;
}
# Handle all other newsletter paths
location ~ ^/newsletter/(?!one($|/)).*$ {
proxy_pass http://regular_backend;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
While negative lookahead works perfectly, it's worth noting:
- Exact match (
location =
) is fastest in Nginx - Prefix match (
location ^~
) is faster than regex - Complex regex patterns have higher overhead
For high-traffic sites, consider using multiple simple location blocks instead of complex regex.
When working with Nginx location blocks, we often need to match multiple paths under a common prefix while excluding specific routes. In this case, we want to capture all paths starting with /newsletter/
except /newsletter/one
.
The basic regex pattern ^/newsletter/(.*)$
correctly matches all newsletter paths, but doesn't provide exclusion capability:
location ~ ^/newsletter/(.*)$ {
# This matches ALL /newsletter/ paths
# including /newsletter/one which we want to exclude
}
The most elegant solution uses negative lookahead in regex:
location ~ ^/newsletter/(?!one$).*$ {
# Configuration for all newsletter paths except /newsletter/one
}
Breaking down the pattern:
^/newsletter/
- matches the base path(?!one$)
- negative lookahead ensuring "one" isn't the complete segment.*$
- matches the rest of the path
If negative lookahead isn't supported in your Nginx version, consider these approaches:
Method 1: Exact Match First
location = /newsletter/one {
# Special handling for the excluded path
}
location /newsletter/ {
# General handling for all other newsletter paths
}
Method 2: Regex with Alternation
location ~ ^/newsletter/((?!one$).*)$ {
# Alternative regex approach
}
Always verify your configuration with:
nginx -t
service nginx reload
And test with various URLs to confirm the matching behavior:
/newsletter/subscribe
- should match/newsletter/one
- should NOT match/newsletter/onetwo
- should match/newsletter/one/
- should match (trailing slash differs)
Remember that regex locations are evaluated in order and have performance implications. For high-traffic sites, consider organizing your location blocks with exact matches (=
) first, then prefixes (^~
), then regex matches (~
).