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

15

Вот мой текущий файл nginx conf:

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

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

wong2
источник
Вы все еще хотите обслуживать тот же контент, даже после перенаправления?
Поти Калимуту,
@ Поти да, точно
wong2
Ok. Пожалуйста, проверьте мой ответ.
Поти Калимуту

Ответы:

12

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

  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;
    }
    
serverliving.com
источник
Прямая цитата из nginx.com/resources/wiki/start/topics/depth/ifisevil ... «Единственные 100% безопасные вещи, которые могут быть сделаны внутри, если в контексте местоположения: возвращай и переписывай».
Pothi Kalimuthu
6

Шаг 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
  }
}
Поти Калимуту
источник
Вместо 301 вы также можете использовать 302, в зависимости от вашего варианта использования.
Pothi Kalimuthu
хм, я думаю, что это решение содержит слишком много дублирующих кодов
wong2
Есть несколько способов решить проблему. Я разместил свое решение только для того, чтобы вы увидели логику его решения. Есть несколько способов избежать дубликатов.
Поти Калимуту,
4

Рекомендуемый способ, вероятно, будет использовать, а 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;
  }
}

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

Koen.
источник