How to Configure Nginx Redirect Rules with Exceptions: Redirect All Except Specific Location


2 views

When implementing domain consolidation with Nginx, we often face scenarios where we need to redirect all traffic except specific paths. The original configuration attempts to redirect all requests from exampleblog.org to blog.example.org, while making an exception for the /+ path that should go to Google+.

The issue stems from Nginx's processing order and location matching priority. In your current setup:

server {
  listen X.X.X.X:80;
  server_name .exampleblog.org;
  location /+ {
    rewrite ^ https://plus.google.com/12345678901234567890/ permanent;
  }
  rewrite ^(.*) http://blog.example.org$1 permanent;
}

The global rewrite rule executes before location processing, causing all requests (including /+) to be redirected.

Here's the proper way to implement this with two distinct approaches:

Method 1: Location Priority

server {
  listen X.X.X.X:80;
  server_name .exampleblog.org;
  
  location = /+ {
    return 301 https://plus.google.com/12345678901234567890/;
  }
  
  location / {
    return 301 http://blog.example.org$request_uri;
  }
}

Method 2: Regex Location

server {
  listen X.X.X.X:80;
  server_name .exampleblog.org;
  
  location ~ ^/\+$ {
    return 301 https://plus.google.com/12345678901234567890/;
  }
  
  location / {
    return 301 http://blog.example.org$request_uri;
  }
}
  • Use return 301 instead of rewrite for simple redirects (more efficient)
  • The = modifier makes an exact match (highest priority)
  • $request_uri preserves the original URI including query parameters
  • The tilde (~) enables regex matching if you need pattern flexibility

After implementing, test with:

curl -I http://exampleblog.org/+
curl -I http://exampleblog.org/any-path
curl -I http://www.exampleblog.org/+

All should return 301 status codes with the appropriate Location headers.


server {
  listen X.X.X.X:80;
  server_name .exampleblog.org www.exampleblog.org;

  # Special case for Google+ redirect
  location = /+ {
    return 301 https://plus.google.com/12345678901234567890/;
  }

  # Catch-all redirect for other paths
  location / {
    return 301 http://blog.example.org$request_uri;
  }
}

The initial configuration had a fundamental ordering issue. Nginx processes location blocks before rewrite directives, but the original setup placed the rewrite rule after the location block without proper priority handling. Here's why it failed:

# This won't work as expected because:
# 1. The location block gets processed first
# 2. But the rewrite at server level still overrides it
server {
  location /+ {
    rewrite ^ https://plus.google.com/...;
  }
  rewrite ^(.*) http://blog.example.org$1;
}

The working solution uses Nginx's location matching priorities:

  1. location = /+ - Exact match (highest priority)
  2. location / - Prefix match (lowest priority)
# Complete working example with multiple server names
server {
  listen 80;
  server_name exampleblog.org www.exampleblog.org;

  # Exact match for /+ path - will trigger first
  location = /+ {
    return 301 https://plus.google.com/12345678901234567890/;
  }

  # Everything else goes to main blog
  location / {
    return 301 http://blog.example.org$request_uri;
  }
}

While generally discouraged, this approach works when you need complex conditions:

server {
  listen 80;
  server_name .exampleblog.org;

  if ($request_uri = /+) {
    return 301 https://plus.google.com/12345678901234567890/;
  }

  return 301 http://blog.example.org$request_uri;
}

Always verify with curl before deploying:

# Test Google+ redirect
curl -I http://exampleblog.org/+
# Should return 301 to Google+

# Test normal redirect
curl -I http://exampleblog.org/any-path
# Should return 301 to blog.example.org/any-path

The location-based solution is more efficient than regex rewrites because:

  • Exact matches (=) are processed via hash lookup
  • No regular expression compilation overhead
  • Nginx can optimize the request processing path