Como remover o caminho com um proxy_pass nginx

Como remover o caminho com um proxy_pass nginx

Eu tenho um aplicativo da web em execução http://example.com/e quero "montar" outro aplicativo em um servidor separado no http://example.com/en. Servidores upstream proxy_passparecem funcionar, mas com 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 upstream retorna 404 not found /en. Isso faz sentido, pois o upstream não possui o path /en.

É proxy_patha solução certa? Devo reescrever "upstream" para que ele ouça /en, como caminho raiz? Ou existe uma diretiva que me permite reescrever o caminho passado para o upstream?

Responder1

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

Responder2

Gostaria de abordar uma resposta mais recente baseada em regex que está ganhando popularidade.

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

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

  • O regex acima corresponderia a um uri de solicitação /enjoy, redirecionando-o para /joyo upstream. Isso é realmente intencional?

  • Uma solicitação for /ennão resultará em nenhum redirecionamento, atendendo diretamente a /partir do upstream (quase como se uma solicitação for /en/tivesse sido feita, mas não exatamente). Se você usar URIs relativos no upstream da sua página raiz (caso contrário, por que você não teria o /en/prefixo ali mesmo nos URIs upstream?), por exemplo src="style.css"(que pode fazer referência a um idioma específico url("menu.png"), por exemplo), então o navegador solicitará que como /style.cssem vez de /en/style.css. (Ou mesmo se você usar URIs absolutos em todos os lugares, e se alguém fizer referência relativa a um recurso semi-opcional obscuro?) Ops, de repente o site pode não funcionar, mas apenas às vezes ou em casos extremos.

  • De acordo com meuconselho anterior em outra questão já mencionada pela própria resposta do OP, o uso de expressões regulares evita oproxy_redirectdiretiva de ter o valor padrão de default, diminuindo-o offpara. Isso significa que se o upstream responder Location: http://127.0.0.1:8080/en/dir/quando uma solicitação /en/dirfor feita, então é isso que o cliente verá, o que obviamente não funcionará corretamente. (O que teria sido especialmente irônico para uma /ensolicitação que solicita o uso de regex em primeiro lugar, mas essa implementação específica sofre de outro problema, como já mencionado acima.) Além disso, se você já estiver usando oupstreamdiretiva, então pode ficar ainda mais feio se você tentar usar uma personalizada, especialmente se você tiver mais de um servidor upstream - como você tem um servidor separado proxy_redirectpara cada um deles? Você proxy_redirecttambém pode usar expressões regulares em , talvez até para corresponder a qualquer host, mas e se você decidir fornecer um redirecionamento entre 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 proxy_passtambém tivemos que eliminar a referência a um servidor de uma upstreamdiretiva baseada em -, para tornar proxy_redirectmais 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, osolução original com os dois locais irmãos de nível superiorainda seria uma ideia melhor do que se enterrar na toca do coelho seguindo a rota regex.

Responder3

Então, eu encontrei oresposta 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 location e passando o backref para o URL proxy_pass.

Responder4

Experimentei a solução aceita acima, mas descobri que ela estava causando redirecionamentos duvidosos para todos os ativos CSS e JS. No final, me inspirei na forma como são feitas as configurações do LinuxServer SWAG Nginx. Você pode encontrá-losaqui. Dê uma olhada pihole.subfolder.conf.sample.

Como tal, minha solução é assim:

location /en {
    return 302 $scheme://$host/en/;
}

location ^~ /en/ {
    set $upstream_app lixxxx.members.linode.com;
    set $upstream_port 9001;
    set $upstream_proto http;
    proxy_pass $upstream_proto://$upstream_app:$upstream_port;

    rewrite /en(.*) $1 break;
}

informação relacionada