Como remover o caminho com um nginx proxy_pass

49

Eu tenho um aplicativo da web em execução em http://example.com/ e quero "montar" outro aplicativo em um servidor separado em http://example.com/en . Servidores upstream e proxy_pass parecem funcionar, mas por um problema:

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location /en {
    proxy_pass http://luscious;
  }
}

Ao abrir example.com/en , meu aplicativo de envio de dados retorna 404 not found /en . Isso faz sentido, pois o upstream não possui o caminho /en .

A proxy_path é a solução correta? Devo reescrever "upstream" para que ele ouça /en , como caminho raiz? Ou existe uma diretiva que me permita reescrever o caminho passado para o upstream?

    
por berkes 20.12.2013 / 16:17

3 respostas

93

Esta é provavelmente a maneira mais eficiente de fazer o que você deseja, sem o uso de expressões regulares:

location = /en {
    return 302 /en/;
}
location /en/ {
    proxy_pass http://luscious/;  # note the trailing slash here, it matters!
}
    
por 21.12.2013 / 04:09
11

Gostaria de abordar uma nova resposta baseada em regex que está crescendo em popularidade.

location ~ ^/en(/?)(.*)$ {  # OOPS!
  proxy_pass http://luscious/$2$is_args$args;  # OOPS!
}

A solução pode parecer mais fofa à primeira vista, mas está errada por vários motivos.

  • A regex acima corresponderia a uma solicitação uri de /enjoy , redirecionando-a para /joy upstream. Isso é realmente pretendido?

  • Uma solicitação para /en não resultará em nenhum redirecionamento, atendendo diretamente a / do upstream (quase como se uma solicitação para /en/ fosse feita, mas não totalmente). Se você usa URIs relativos dentro do upstream da sua página raiz (caso contrário, por que você não teria o prefixo /en/ ali dentro dos URIs do upstream?), src="style.css" (que pode referenciar um url("menu.png") específico do idioma, por exemplo), o navegador solicitará isso como /style.css em vez de /en/style.css . (Ou mesmo se você usar URIs absolutos em todos os lugares, e se alguém referenciar um recurso semi-opcional obscuro relativamente?) Ops, de repente o site pode não funcionar, mas apenas às vezes ou em casos extremos.

  • De acordo com meu aconselhamento anterior em outra pergunta já mencionada pela resposta do próprio OP , o uso de expressões regulares impede a diretiva proxy_redirect de ter o valor padrão de default , desviando-o para off . Isso significa que, se o upstream responder com Location: http://127.0.0.1:8080/en/dir/ quando uma solicitação para /en/dir for feita, é isso que o cliente verá, o que obviamente não funcionará corretamente. (O que seria especialmente irônico para uma solicitação de /en que solicita o uso de regex, mas essa implementação específica, ao contrário, sofre de outro problema, como já mencionado acima.) Além disso, se você já estiver usando o upstream directiva, então pode ficar ainda mais feio se você tentar usar um custom, especialmente se você tiver mais de um servidor upstream - como você tem um proxy_redirect separado para cada um desses? Também é possível usar expressões regulares em proxy_redirect , talvez até para corresponder a qualquer host, mas e se você decidir fornecer um redirecionamento de vários domínios no futuro?

Para tentar resolver alguns dos pontos acima com um único local baseado em regex, poderíamos fazer o seguinte (observe que em proxy_pass também tivemos que descartar a referência a um servidor de uma diretiva baseada em upstream , para tornar proxy_redirect mais simples):

location ~ ^/en/?((?<=/).*)?$ {
  location = /en { return 302 /en/; }
  proxy_pass http://127.0.0.1:8080/$1$is_args$args;
  proxy_redirect http://127.0.0.1:8080/ /en/;
}

Então, se você me perguntar, a solução original com os dois locais irmãos de nível superior ainda seria melhor idéia do que cavar-se em um buraco de coelho, indo a rota regex vez.

    
por 14.10.2015 / 06:51
6

Então, encontrei a resposta no stackoverflow :

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location ~ ^/en(/?)(.*) {
    proxy_pass http://luscious/$2;
  }
}

Basicamente: passando um regex para o local e passando o backref ao longo do URL proxy_pass.

    
por 20.12.2013 / 16:30