Redirection Nginx basée sur l'agent utilisateur

15

Voici ma conf nginx actuelle:

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

cela fonctionne bien, les deux www.domain.comet www.domain2.comservent le même contenu.

maintenant j'aimerais ajouter

si l'utilisateur visite www.domain.com et que l'agent utilisateur est xxx, redirigez-le vers www.domain2.com

J'ai cherché et essayé beaucoup de méthodes, mais aucune d'entre elles ne fonctionne.

wong2
la source
Voulez-vous toujours diffuser le même contenu, même après la redirection?
Pothi Kalimuthu
@Pothi oui, exactement
wong2
D'accord. Veuillez vérifier ma réponse.
Pothi Kalimuthu

Réponses:

12

Il existe deux façons de résoudre ce problème.

  1. Disposez de deux blocs "serveur" séparés pour www.domain.com et www.domain2.com et ajoutez les lignes de règles suivantes au bloc "serveur" www.domain.com. Il s'agit de la méthode recommandée pour résoudre ce problème.

    if ($http_user_agent ~* "^xxx$") {
       rewrite ^/(.*)$ http://www.domain2.com/$1 permanent;
    }
    
  2. Si vous souhaitez gérer la redirection avec un seul bloc "serveur" pour les deux domaines, essayez les règles ci-dessous

    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
la source
Citation directe de nginx.com/resources/wiki/start/topics/depth/ifisevil ... "Les seules choses 100% sûres qui peuvent être faites à l'intérieur si dans un contexte d'emplacement sont: retourner et réécrire".
Pothi Kalimuthu le
6

Étape 1: avoir deux blocs serveur, un pour domain.com et domain2.com chacun.

Étape 2: Utilisez si correctement car il est mauvais s'il n'est pas utilisé correctement.

Voici la solution complète ...

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
la source
Au lieu de 301, vous pouvez également utiliser 302, selon votre cas d'utilisation.
Pothi Kalimuthu
hmm, je pense que cette solution contient trop de codes de duplication
wong2
Il existe plusieurs façons de résoudre un problème. J'ai posté ma solution uniquement pour vous faire voir la logique derrière la façon dont elle pourrait être résolue. Il existe plusieurs façons d'éviter les doublons.
Pothi Kalimuthu
4

La méthode recommandée serait probablement d'utiliser a map, également parce que ces variables ne sont évaluées que lorsqu'elles sont utilisées.

L'utilisation de return 301 ...est préférable à la réécriture, car aucune expression régulière ne doit être compilée.

Voici un exemple où l'hôte et l'agent utilisateur en tant que chaîne concaténée sont comparés à une expression régulière unique:

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

Et cela pourrait être encore plus flexible, par exemple s'il n'y a pas 2 mais plus de domaines impliqués.

Nous carte ici www.domain.comavec les agents utilisateurs en commençant par Agentà http://www.domain2.comet www.domain2.comavec l'exacte user-agent 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;
  }
}

NB vous aurez besoin de nginx 0.9.0 ou supérieur pour que la chaîne concaténée dans la carte fonctionne.

Koen.
la source