Nginx User-Agent Based Redirect: How to Route Traffic from Domain1 to Domain2


3 views

When dealing with multi-domain setups in Nginx, we often need conditional routing based on client characteristics. A common requirement is redirecting specific user agents from one domain to another while maintaining normal traffic flow.

Here's the enhanced configuration that handles user-agent based redirects:

server {
  listen 90;
  server_name www.domain.com www.domain2.com;
  root /root/app;

  # User-agent detection and redirect
  if ($http_user_agent ~* (xxx|special_bot|crawler)) {
    set $ua_redirect 1;
  }

  if ($host = 'www.domain.com') {
    set $ua_redirect "${ua_redirect}1";
  }

  if ($ua_redirect = 11) {
    return 301 $scheme://www.domain2.com$request_uri;
  }

  location / {
    try_files $uri =404;
  }

  location ~ /([-\w]+)/(\w+)/ {
    proxy_pass http://backend;
    proxy_set_header Host $host;
  }
}

The solution uses a combination of Nginx variables and conditional logic:

  • First condition checks for matching user agents (case insensitive with ~*)
  • Second condition verifies the requested domain
  • Final condition combines both checks before issuing the redirect

For more complex user agent detection:

map $http_user_agent $redirect_ua {
  default 0;
  "~*bot" 1;
  "~*spider" 1;
  "~*crawler" 1;
  "~*special_client" 1;
}

server {
  # ... existing server config
  
  if ($redirect_ua = 1) {
    rewrite ^ $scheme://www.domain2.com$request_uri permanent;
  }
}

When implementing user-agent based rules:

  • Avoid complex regular expressions in high-traffic scenarios
  • The map directive is generally more efficient than multiple if conditions
  • Consider caching decisions for known user agents

Verify with curl commands:

curl -A "special_bot" -I http://www.domain.com
curl -A "Mozilla" -I http://www.domain.com

Recently I encountered a situation where I needed to redirect visitors from www.domain.com to www.domain2.com based on their user agent. The existing Nginx configuration served both domains with identical content, but the requirement demanded conditional redirection for specific user agents.

Here's the original Nginx server block:

server {
  listen 90;
  server_name www.domain.com www.domain2.com;
  root /root/app;
  location / {
    try_files $uri =404;
  }
  location ~ /([-\w]+)/(\w+)/ {
    proxy_pass bla bla
  }
}

To implement user-agent based redirects, we need to:

  1. Check the incoming Host header for www.domain.com
  2. Verify the User-Agent string matches our target pattern
  3. Perform a 301 redirect to www.domain2.com when conditions are met

Here's the complete working solution:

server {
  listen 90;
  server_name www.domain.com www.domain2.com;
  root /root/app;

  set $redirect_to_domain2 0;
  
  if ($http_user_agent ~* (xxx|special_bot|crawler)) {
    set $redirect_to_domain2 "${redirect_to_domain2}1";
  }
  
  if ($host = "www.domain.com") {
    set $redirect_to_domain2 "${redirect_to_domain2}1";
  }
  
  if ($redirect_to_domain2 = "11") {
    return 301 http://www.domain2.com$request_uri;
  }

  location / {
    try_files $uri =404;
  }
  
  location ~ /([-\w]+)/(\w+)/ {
    proxy_pass bla bla;
  }
}

For simpler cases, you could use this more concise version:

server {
  listen 90;
  server_name www.domain.com www.domain2.com;
  root /root/app;

  if ($host = "www.domain.com") {
    if ($http_user_agent ~* (xxx|special_bot)) {
      return 301 http://www.domain2.com$request_uri;
    }
  }

  # Rest of your configuration...
}
  • Always test redirects thoroughly before deploying to production
  • The regex pattern for user agents is case-insensitive due to the ~* operator
  • Multiple user agents can be matched using the pipe (|) character
  • Consider using 302 (temporary) redirects during testing

While if statements in Nginx are generally discouraged, they're acceptable for simple redirect logic like this. For complex user agent matching at scale, consider:

  • Using a map directive to handle multiple user agents
  • Implementing the logic at the application level if possible
  • Caching decisions for frequently seen user agents
# Example using map directive
map $http_user_agent $redirect_ua {
  default 0;
  "~*xxx" 1;
  "~*special_bot" 1;
}