Назад | Перейти на главную страницу

Перенаправление Nginx на основе пользовательского агента

Вот моя текущая конфигурация nginx:

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
  }
}

работает нормально, оба www.domain.com и www.domain2.com обслуживают тот же контент.

теперь я хочу добавить

если пользователь посещает www.domain.com, а пользовательский агент - xxx, перенаправьте на www.domain2.com

Я искал и пробовал много методов, но ни один из них не работает.

Есть два способа решить эту проблему.

  1. Создайте два отдельных «серверных» блока для www.domain.com и www.domain2.com и добавьте следующие строки правил в «серверный» блок www.domain.com. Это рекомендуемый способ решить эту проблему.

    if ($http_user_agent ~* "^xxx$") {
       rewrite ^/(.*)$ http://www.domain2.com/$1 permanent;
    }
    
  2. Если вы хотите управлять перенаправлением с помощью единого «серверного» блока для обоих доменов, попробуйте следующие правила

    set $check 0;
    if ($http_user_agent ~* "^xxx$") {
        set $check 1;
    }
    if ($host ~* ^www.domain.com$) {
        set $check "${check}1";
    }
    if ($check = 11) {
        rewrite ^/(.*)$ http://www.domain2.com/$1 permanent;
    }
    

Шаг 1. Создайте два серверных блока, по одному для domain.com и domain2.com.

Шаг 2: Используйте если правильно поскольку это зло, если его использовать неправильно.

Вот полное решение ...

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

  # redirect if 'xxx' is found on the user-agent string
  if ( $http_user_agent ~ 'xxx' ) {
    return 301 http://www.domain2.com$request_uri;
  }

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

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

Рекомендуемый способ, вероятно, будет использовать map, также потому, что эти переменные оцениваются только тогда, когда они используются.

Также использование return 301 ... предпочтительнее перезаписи, потому что не нужно компилировать регулярное выражение.

Вот пример того, как хост и пользовательский агент в виде объединенной строки сравниваются с одним регулярным выражением:

map "$host:$http_user_agent" $my_domain_map_host {
  default                      0;
  "~*^www.domain.com:Agent.*$" 1;
}

server {
  if ($my_domain_map_host) {
    return 302 http://www.domain2.com$request_uri;
  }
}

И это может быть еще более гибким, например, если задействовано не 2, а больше домена.

Здесь мы отображаем www.domain.com с пользовательскими агентами, начинающимися с Agent к http://www.domain2.com и www.domain2.com с точным пользовательским агентом Other Agent к http://www.domain3.com:

map "$host:$http_user_agent" $my_domain_map_host {
  default                             0;
  "~*^www.domain.com:Agent.*$"        http://www.domain2.com;
  "~*^www.domain2.com:Other Agent$"   http://www.domain3.com;
}

server {
  if ($my_domain_map_host) {
    return 302 $my_domain_map_host$request_uri;
  }
}

NB вам понадобится nginx 0.9.0 или выше, чтобы объединенная строка в карте работала.