Redirección de Nginx basada en agente de usuario

15

Aquí está mi conf nginx actual:

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

funciona bien, ambos www.domain.comy www.domain2.comsirven el mismo contenido.

ahora me gustaría agregar

si el usuario visita www.dominio.com y el agente de usuario es xxx, redirija a www.dominio2.com

He buscado y probado muchos métodos, pero ninguno de ellos funciona.

wong2
fuente
¿Todavía quieres servir el mismo contenido, incluso después de la redirección?
Pothi Kalimuthu
@Pothi sí, exactamente
wong2
Okay. Por favor revisa mi respuesta.
Pothi Kalimuthu

Respuestas:

12

Hay dos formas de solucionar este problema.

  1. Tenga dos bloques de "servidor" separados para www.dominio.com y www.dominio2.com y agregue las siguientes líneas de reglas al bloque de "servidor" www.dominio.com. Esta es una forma recomendada de resolver este problema.

    if ($http_user_agent ~* "^xxx$") {
       rewrite ^/(.*)$ http://www.domain2.com/$1 permanent;
    }
    
  2. Si desea administrar la redirección con un solo bloque "servidor" para ambos dominios, pruebe las siguientes reglas

    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
fuente
Cita directa de nginx.com/resources/wiki/start/topics/depth/ifisevil ... "Las únicas cosas 100% seguras que se pueden hacer en el interior si están en un contexto de ubicación son: regresar y reescribir".
Pothi Kalimuthu
6

Paso 1: Tenga dos bloques de servidor, uno para cada dominio.com y dominio2.com.

Paso 2: Úselo correctamente, ya que es malo si se usa incorrectamente.

Aquí está la solución 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
  }
}
Pothi Kalimuthu
fuente
En lugar de 301, también puede usar 302, dependiendo de su caso de uso.
Pothi Kalimuthu
hmm, creo que esta solución contiene demasiados códigos duplicados
wong2
Hay varias formas de resolver un problema. Publiqué mi solución solo para hacerle ver la lógica detrás de cómo podría resolverse. Hay varias formas de evitar duplicados.
Pothi Kalimuthu
4

La forma recomendada probablemente sería usar a map, también porque estas variables se evalúan solo cuando se usan.

También return 301 ...se prefiere el uso de las reescrituras, ya que no es necesario compilar ninguna expresión regular.

Aquí un ejemplo de dónde el host y el agente de usuario como una cadena concatenada se comparan con una única expresión regular:

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

Y esto podría ser aún más flexible, por ejemplo, si no hay 2 sino más dominios involucrados.

Aquí hacemos un mapa www.domain.comcon los agentes de usuario a partir de Agenta http://www.domain2.comy www.domain2.comcon la exacta de agente de usuario 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;
  }
}

Nota : necesitará nginx 0.9.0 o superior para que la cadena concatenada en el mapa funcione.

Koen
fuente