Przekierowanie Nginx na podstawie klienta użytkownika


15

Oto mój aktualny conf 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
  }
}

działa dobrze, zarówno www.domain.comi www.domain2.comobsługuje tę samą treść.

teraz chciałbym dodać

jeśli użytkownik odwiedza www.domain.com, a agentem użytkownika jest xxx, wówczas przekieruj na www.domain2.com

Szukałem i wypróbowałem wiele metod, ale żadna z nich nie działa.


Czy nadal chcesz wyświetlać te same treści, nawet po przekierowaniu?
Pothi Kalimuthu

@Pothi tak, dokładnie
wong2

Dobrze. Proszę sprawdź moją odpowiedź.
Pothi Kalimuthu

Odpowiedzi:


12

Istnieją dwa sposoby rozwiązania tego problemu.

  1. Posiadaj dwa oddzielne bloki „serwerowe” dla www.domain.com i www.domain2.com i dodaj następujące wiersze reguł do bloku „serwer” www.domain.com. Jest to zalecany sposób rozwiązania tego problemu.

    if ($http_user_agent ~* "^xxx$") {
       rewrite ^/(.*)$ http://www.domain2.com/$1 permanent;
    }
    
  2. Jeśli chcesz zarządzać przekierowaniem za pomocą jednego bloku „serwera” dla obu domen, wypróbuj poniższe reguły

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

Bezpośredni cytat z nginx.com/resources/wiki/start/topics/depth/ifisevil ... „Jedyne w 100% bezpieczne rzeczy, które można zrobić wewnątrz, jeśli w kontekście lokalizacji to: powrót i przepisanie”.
Pothi Kalimuthu

6

Krok 1: Posiadaj dwa bloki serwera, po jednym dla domain.com i domain2.com.

Krok 2: Użyj, jeśli jest poprawny, ponieważ jest zły, jeśli jest używany nieprawidłowo.

Oto kompletne rozwiązanie ...

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

Zamiast 301 możesz również użyć 302, w zależności od przypadku użycia.
Pothi Kalimuthu

hmm, myślę, że to rozwiązanie zawiera zbyt wiele powielających się kodów
wong2

Istnieje wiele sposobów rozwiązania problemu. Opublikowałem moje rozwiązanie tylko po to, abyś zobaczył logikę, w jaki sposób można go rozwiązać. Istnieje wiele sposobów uniknięcia duplikatów.
Pothi Kalimuthu

4

Zalecanym sposobem byłoby prawdopodobnie użycie a map, również dlatego, że zmienne te są oceniane tylko wtedy, gdy są używane.

Również użycie opcji return 301 ...jest lepsze niż przepisywanie, ponieważ nie trzeba kompilować żadnego wyrażenia regularnego.

Oto przykład porównania hosta i klienta użytkownika jako łańcucha łączonego z pojedynczym wyrażeniem regularnym:

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

Może to być jeszcze bardziej elastyczne, na przykład, jeśli nie ma tam 2, ale więcej domen.

Tutaj mapujemy www.domain.comz klientami użytkownika zaczynającymi się Agentod http://www.domain2.comi www.domain2.comz dokładnym klientem użytkownika Other Agentna 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;
  }
}

Uwaga: do poprawnego działania połączonego łańcucha w mapie potrzebujesz nginx w wersji 0.9.0 lub nowszej.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.