Nginx-Weiterleitung basierend auf User Agent

15

Hier ist meine aktuelle 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
  }
}

es funktioniert gut, beide www.domain.comund www.domain2.comdienen den gleichen Inhalt.

Jetzt möchte ich hinzufügen

Wenn der Benutzer www.domain.com besucht und der Benutzeragent xxx ist, leiten Sie ihn zu www.domain2.com weiter

Ich habe eine Menge Methoden gesucht und ausprobiert, aber keine davon funktioniert.

wong2
quelle
Möchten Sie auch nach der Weiterleitung den gleichen Inhalt bereitstellen?
Pothi Kalimuthu
@Pothi ja, genau
wong2
In Ordnung. Bitte überprüfen Sie meine Antwort.
Pothi Kalimuthu

Antworten:

12

Es gibt zwei Möglichkeiten, um dieses Problem zu beheben.

  1. Haben Sie zwei separate "Server" -Blöcke für www.domain.com und www.domain2.com und fügen Sie die folgenden Zeilen von Regeln zum "Server" -Block www.domain.com hinzu. Dies ist eine empfohlene Lösung für dieses Problem.

    if ($http_user_agent ~* "^xxx$") {
       rewrite ^/(.*)$ http://www.domain2.com/$1 permanent;
    }
    
  2. Wenn Sie die Umleitung mit einem einzigen "Server" -Block für beide Domänen verwalten möchten, versuchen Sie es mit den folgenden Regeln

    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
quelle
Direktes Zitat von nginx.com/resources/wiki/start/topics/depth/ifisevil ... "Die einzigen 100% sicheren Dinge, die in einem Standortkontext ausgeführt werden können, sind: return and rewrite".
Pothi Kalimuthu
6

Schritt 1: Verfügen Sie über zwei Serverblöcke, jeweils einen für domain.com und domain2.com.

Schritt 2: Verwenden Sie es richtig, da es böse ist, wenn es falsch verwendet wird.

Hier ist die Komplettlösung ...

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
  }
}
Pothi Kalimuthu
quelle
Anstelle von 301 können Sie auch 302 verwenden, abhängig von Ihrem Anwendungsfall.
Pothi Kalimuthu
hmm, ich denke, diese Lösung enthält zu viele duplizierende Codes
wong2
Es gibt mehrere Möglichkeiten, ein Problem zu lösen. Ich habe meine Lösung nur veröffentlicht, damit Sie die Logik dahinter erkennen, wie sie gelöst werden kann. Es gibt mehrere Möglichkeiten, um Duplikate zu vermeiden.
Pothi Kalimuthu
4

Der empfohlene Weg wäre wahrscheinlich die Verwendung von a map, auch weil diese Variablen nur ausgewertet werden, wenn sie verwendet werden.

Auch wird die Verwendung von return 301 ...Rewrites vorgezogen, da keine regulären Ausdrücke kompiliert werden müssen.

Hier ein Beispiel, in dem Host und User-Agent als verkettete Zeichenfolge mit einer einzelnen Regex verglichen werden:

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

Und dies könnte noch flexibler sein, wenn zum Beispiel nicht 2, sondern mehr Domänen beteiligt sind.

Hier bilden wir www.domain.commit User-Agents , beginnend mit Agentbis http://www.domain2.comund www.domain2.commit dem genauen User-Agent Other Agentan 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;
  }
}

Hinweis: Sie benötigen Nginx 0.9.0 oder höher, damit die verkettete Zeichenfolge in der Karte funktioniert.

Koen.
quelle