Reindirizzamento di Nginx basato sull'agente utente


15

Ecco la mia attuale conf di 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
  }
}

funziona bene, entrambi www.domain.come www.domain2.comoffrono lo stesso contenuto.

ora vorrei aggiungere

se l'utente visita www.domain.com e l'agente utente è xxx, reindirizza a www.domain2.com

Ho cercato e provato molti metodi, ma nessuno di questi funziona.


Vuoi comunque offrire lo stesso contenuto, anche dopo il reindirizzamento?
— Pothi Kalimuthu,

@Pothi sì, esattamente
— wong2,

Ok. Per favore, controlla la mia risposta.
— Pothi Kalimuthu,

Risposte:


12

Esistono due modi per risolvere questo problema.

  1. Disponi di due blocchi "server" separati per www.domain.com e www.domain2.com e aggiungi le seguenti righe di regole al blocco "server" www.domain.com. Questo è un modo consigliato per risolvere questo problema.

    if ($http_user_agent ~* "^xxx$") {
       rewrite ^/(.*)$ http://www.domain2.com/$1 permanent;
    }
    
  2. Se desideri gestire il reindirizzamento con un singolo blocco "server" per entrambi i domini, prova le regole seguenti

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

Citazione diretta da nginx.com/resources/wiki/start/topics/depth/ifisevil ... "Le uniche cose sicure al 100% che possono essere fatte all'interno se in un contesto di posizione sono: ritorno e riscrittura".
— Pothi Kalimuthu,

6

Passaggio 1: disporre di due blocchi server, uno ciascuno per domain.com e domain2.com.

Passaggio 2: utilizzare se correttamente in quanto è male se utilizzato in modo errato.

Ecco la soluzione completa ...

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

Invece di 301, puoi usare anche 302, a seconda del tuo caso d'uso.
— Pothi Kalimuthu,

hmm, penso che questa soluzione contenga troppi codici di duplicazione
— wong2,

Esistono diversi modi per risolvere un problema. Ho pubblicato la mia soluzione solo per farti vedere la logica dietro come potrebbe essere risolto. Esistono diversi modi per evitare duplicati.
— Pothi Kalimuthu,

4

Il modo consigliato sarebbe probabilmente usare a map, anche perché queste variabili vengono valutate solo quando vengono utilizzate.

Anche l'uso di return 301 ...è preferito rispetto alle riscritture, perché non è necessario compilare alcuna espressione regolare.

Ecco un esempio di dove host e user-agent come stringa concatenata vengono confrontati con una singola regex:

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

E questo potrebbe essere ancora più flessibile, ad esempio se non ci fossero 2 ma più domini coinvolti.

Qui mappiamo www.domain.comcon user-agent a partire Agentda http://www.domain2.come www.domain2.comcon l'esatto user-agent Other Agenta 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 è necessario nginx 0.9.0 o versione successiva affinché la stringa concatenata nella mappa funzioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.