Redirecionamento Nginx com base no agente do usuário

15

Aqui está o meu atual 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
  }
}

funciona bem, ambos www.domain.come www.domain2.comveicula o mesmo conteúdo.

agora eu gostaria de adicionar

se o usuário estiver visitando www.domain.com e o agente do usuário for xxx, redirecione para www.domain2.com

Eu pesquisei e tentei muitos métodos, mas nenhum deles funciona.

wong2
fonte
Você ainda deseja veicular o mesmo conteúdo, mesmo após o redirecionamento?
Pothi Kalimuthu
@Pothi sim, exatamente
wong2
Está bem. Por favor, verifique minha resposta.
Pothi Kalimuthu

Respostas:

12

Existem duas maneiras de corrigir esse problema.

  1. Tenha dois blocos de "servidor" separados para www.domain.com e www.domain2.com e adicione as seguintes linhas de regras ao bloco "servidor" www.domain.com. Essa é a maneira recomendada de resolver esse problema.

    if ($http_user_agent ~* "^xxx$") {
       rewrite ^/(.*)$ http://www.domain2.com/$1 permanent;
    }
    
  2. Se você deseja gerenciar o redirecionamento com um único bloco "servidor" para os dois domínios, tente as regras abaixo

    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
fonte
Citação direta de nginx.com/resources/wiki/start/topics/depth/ifisevil ... "As únicas coisas 100% seguras que podem ser feitas dentro de um ambiente de localização são: retornar e reescrever".
Pothi Kalimuthu
6

Etapa 1: tenha dois blocos de servidor, um para domínio.com e domínio2.com.

Etapa 2: use se corretamente , pois é mau se usado incorretamente.

Aqui está a solução 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
fonte
Em vez de 301, você também pode usar 302, dependendo do seu caso de uso.
Pothi Kalimuthu
hmm, penso que esta solução contém muitos códigos de duplicação
wong2
Existem várias maneiras de resolver um problema. Postei minha solução apenas para fazer você ver a lógica por trás de como ela poderia ser resolvida. Existem várias maneiras de evitar duplicatas.
Pothi Kalimuthu
4

A maneira recomendada provavelmente seria usar a map, também porque essas variáveis ​​são avaliadas apenas quando são usadas.

Também return 301 ...é preferível o uso de reescritas, porque nenhuma expressão regular precisa ser compilada.

Aqui um exemplo de onde host e user-agent como uma cadeia concatenada são comparados a uma única 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 isso pode ser ainda mais flexível, por exemplo, se não houver 2, mas mais domínios envolvidos.

Aqui nós mapear www.domain.comcom user-agents começando com Agenta http://www.domain2.come www.domain2.comcom a exata user-agent Other Agentpara 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: você precisará do nginx 0.9.0 ou superior para que a sequência concatenada no mapa funcione.

Koen.
fonte