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 ofrewrite
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:
location = /+
- Exact match (highest priority)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