When configuring URL redirection in Nginx, developers often face the dilemma between using return
versus rewrite
directives. Let's examine the technical differences through concrete examples.
# Option 1: Using return directive
server {
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
}
# Option 2: Using rewrite directive
server {
server_name example.com;
rewrite ^ http://www.example.com$request_uri? permanent;
}
The return
directive is more efficient because:
- It immediately terminates processing and returns to client
- No regular expression matching occurs
- Lower CPU overhead (benchmarks show ~15% faster response)
Both methods can achieve 301 (permanent) redirects, but implementation matters:
# Correct 301 redirect with return
curl -I example.com
HTTP/1.1 301 Moved Permanently
Location: http://www.example.com/
# Potential pitfall with rewrite
# (If not properly configured, might send 302 instead)
The original issue with rewrite showing 302 likely occurs because:
- The rewrite rule might be getting overridden elsewhere
- Browser cache interfering with redirect testing
- Missing
?
after $request_uri in rewrite pattern
For most cases, this canonical solution works best:
server {
listen 80;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
# SSL configuration and other settings...
}
For complex redirect needs, combine both methods:
# Preserve query strings in redirects
if ($args ~* "^(.+)$") {
rewrite ^/(.*)$ /newpath/$1?$args? permanent;
}
# Domain migration example
server {
server_name olddomain.com;
return 301 $scheme://newdomain.com$request_uri;
}
In Nginx configuration, both return
and rewrite
directives can handle redirections, but they operate differently at the processing level:
# Return directive (immediate response)
return 301 $scheme://www.example.com$request_uri;
# Rewrite directive (regex processing)
rewrite ^(.*)$ http://www.example.com$1 permanent;
For simple domain redirects (non-www to www or HTTP to HTTPS), return
is more efficient because:
- It doesn't involve regex pattern matching
- Generates less CPU overhead
- Provides clearer configuration intent
- Consistent behavior across all clients
The 302 response you're seeing with rewrite might occur when:
# Problematic case (might get interpreted as 302)
rewrite ^ http://$host$request_uri? permanent;
# Working solution (explicit scheme)
rewrite ^ https://www.example.com$request_uri permanent;
Here's the optimal setup for www/non-www redirection:
server {
listen 80;
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
}
server {
listen 80;
server_name www.example.com;
# Your main configuration here
}
Rewrite becomes valuable for:
- Complex URL pattern changes (changing URL structures)
- Conditional redirects based on query parameters
- When you need to capture and reuse path components
# Example where rewrite is appropriate
rewrite ^/old-path/(.*)$ /new-path/$1 permanent;
Both methods properly implemented with 301 will preserve SEO value, but:
- Return is faster (better for crawl budget)
- Rewrite offers more flexibility for complex migrations
- Always test with tools like Screaming Frog after implementation
Remember to clear your Nginx cache (nginx -s reload
) after making changes and verify with curl -I
to check response codes.