Nginx Location Directives: Understanding Case-Sensitive (~) vs Case-Insensitive (~*) Regex Matching


2 views

In Nginx configuration, the location directive supports several matching modifiers:

  • ~ - Case-sensitive regular expression match
  • ~* - Case-insensitive regular expression match
  • ^~ - Prefix-based match that stops regex evaluation
  • = - Exact match
  • (none) - Prefix-based match

The key distinction between ~ and ~* is case sensitivity:

location ~ ^/images/ {
    # Will match /images/logo.png but NOT /Images/logo.png
}

location ~* ^/images/ {
    # Will match both /images/logo.png and /Images/logo.png
}

Your approach to routing everything except /api/postdataV1 is correct. Here's a more detailed implementation:

location = /api/postdataV1 {
    # Exact match for /api/postdataV1 only
    proxy_pass http://cluster1;
}

location / {
    # All other requests
    proxy_pass http://cluster2;
}

Using = for exact matching is more efficient than regex when appropriate.

Here are some practical examples of regex location matching:

# Case-sensitive image files
location ~ \.(jpg|png|gif)$ {
    expires 30d;
}

# Case-insensitive PHP files
location ~* \.php$ {
    fastcgi_pass unix:/var/run/php-fpm.sock;
}

# Exclude specific paths
location ~ ^/(?!api/postdataV1).*$ {
    proxy_pass http://fallback_server;
}

When using regex locations:

  • Nginx evaluates locations in specific order (exact > ^~ > regex > prefix)
  • Frequent regex matches can impact performance - use exact or prefix matches when possible
  • Complex regex patterns are evaluated sequentially until first match

To test your location matching:

# Add to server block
error_log /var/log/nginx/error.log debug;

# Or use return to test matches
location /test {
    return 200 "Matched!";
}

The ~ and ~* are regex match modifiers in Nginx location blocks:

  • location ~ - Case-sensitive regular expression match
  • location ~* - Case-insensitive regular expression match

For routing all URLs except /api/postdataV1 to different servers:

# Case-sensitive match for /api/postdataV1
location ~ ^/api/postdataV1$ {
    proxy_pass http://primary_cluster;
    # Other config for this specific endpoint
}

# Catch-all for other requests  
location / {
    proxy_pass http://secondary_cluster;
    # Config for all other endpoints
}

Consider these examples showing the difference:

# Matches /user/123 but not /USER/123
location ~ ^/user/(\d+)$ {
    # Configuration
}

# Matches both /user/123 and /USER/123  
location ~* ^/user/(\d+)$ {
    # Configuration
}

Important considerations when using regex locations:

  1. Regex locations have lower priority than prefix matches (location /path)
  2. The order of location blocks matters in Nginx configuration
  3. Overly broad regex patterns can cause unexpected matches

If you prefer positive matching for exclusions:

location / {
    # First try exact match for the excluded path
    if ($request_uri = /api/postdataV1) {
        proxy_pass http://primary_cluster;
        break;
    }
    
    # All other requests
    proxy_pass http://secondary_cluster;
}

Regex matching has some performance impact:

  • Simple prefix matches are fastest
  • Case-sensitive (~) is slightly faster than case-insensitive (~*)
  • Complex regex patterns should be avoided in high-traffic scenarios