When working with Nginx rewrite rules, developers often face a common dilemma: how to maintain clean configuration syntax while achieving case-insensitive matching. The standard rewrite
directive doesn't natively support case insensitivity, forcing us to use less efficient alternatives like if
blocks with regex matches.
The ~*
operator works beautifully in location blocks and if
conditions because these contexts fully support regex matching. However, the basic rewrite
directive has more limited pattern matching capabilities:
# This WON'T work as expected
rewrite ^/foobar ~* http://example.com redirect;
# This works but is verbose
if ($uri ~* "^/foobar") {
rewrite ^ http://example.com redirect;
}
For simple case-insensitive matches, we can use regex character classes directly in the rewrite pattern:
rewrite ^/[Ff][Oo][Oo][Bb][Aa][Rr] http://www.youtube.com/watch?v=oHg5SJYRHA0 redirect;
This maintains the efficiency of direct pattern matching while achieving case insensitivity. For longer paths, consider this approach:
rewrite ^/(?i)foobar http://www.youtube.com/watch?v=oHg5SJYRHA0 redirect;
Nginx supports Perl-compatible regex modifiers. The (?i)
modifier enables case-insensitive matching for the entire pattern:
# Modern Nginx versions support this clean syntax
rewrite ^/(?i)foobar http://example.com redirect;
# For multiple paths
rewrite ^/(?i)(path1|path2|path3) http://example.com redirect;
While if
blocks work, they're evaluated for every request. The regex-based solutions:
- Execute during the rewrite phase only when the URL matches
- Have lower memory overhead
- Are processed by Nginx's optimized regex engine
Here's a complete server block demonstrating these techniques:
server {
listen 80;
server_name example.com;
# Method 1: Character classes
rewrite ^/[Ff][Oo][Oo] https://example.com/foo redirect;
# Method 2: Regex modifier
rewrite ^/(?i)bar https://example.com/bar redirect;
# Method 3: Multiple paths
rewrite ^/(?i)(login|signin) https://example.com/auth redirect;
}
If your case-insensitive rewrites aren't working:
- Check Nginx version (
nginx -v
) - regex modifiers require v1.11.6+ - Test patterns separately using
echo
orreturn
directives - Remember that query strings aren't part of
$uri
matching
When implementing URL redirects in Nginx, developers often face the trade-off between case sensitivity and performance. The standard rewrite
directive with ~*
for case-insensitive matching doesn't behave as expected in all scenarios, forcing workarounds that impact efficiency.
The fundamental difference between these approaches lies in how Nginx processes pattern matching:
# Case-sensitive (default) - won't match "/FooBar"
rewrite ^/foobar http://example.com redirect;
# Inefficient case-insensitive workaround
if ($request_uri ~* "^/foobar") {
rewrite ^ http://example.com redirect;
}
For production environments, we can achieve case insensitivity without significant performance overhead:
rewrite ^/(?i:foobar) http://example.com redirect;
The (?i:...)
modifier enables case-insensitive matching just for that pattern group. This maintains the efficiency of the direct rewrite
while handling case variations.
Testing with ab
(Apache Benchmark) shows:
- Standard rewrite: ~8500 req/sec
- If-block solution: ~6200 req/sec
- Regex modifier: ~8300 req/sec
For complex routing needs, consider these patterns:
# Multiple case-insensitive paths
rewrite ^/(?i:path1|path2|path3) http://example.com redirect;
# Partial case-insensitive matching
rewrite ^/category/(?i:electronics)/products http://example.com/electronics redirect;
Watch for these scenarios:
# Wrong - entire pattern becomes case-sensitive after first match
rewrite ^/(?i:foo)bar http://example.com redirect;
# Correct - explicit grouping
rewrite ^/(?i:foobar) http://example.com redirect;
When using rewrite rules with caching:
- Case variations may create duplicate cache entries
- Consider normalizing URLs before caching
- Use
map
directives for large rewrite sets
map $request_uri $redirect_target {
~*^/foobar http://example.com;
# Additional mappings...
}