nginx problema de balanceamento de carga com 301 do backend

4

Eu estou correndo em um problema estranho para o qual eu não tenho certeza se é um problema de configuração ou um bug no nginx. Minha configuração é um proxy reverso nginx que possui servidores backend Apache2. O balanceador de carga é bastante básico, semelhante ao exemplo do wiki , por exemplo simplificado:

http {
  upstream myproject {
    server 127.0.0.1:8000;
  }

  server {
    listen 80;
    location / {
      proxy_pass http://myproject;
    }
  }
}

Agora, surge um problema, por exemplo, quando tento solicitar um diretório no Apache, sem a barra final no final do URL. Por exemplo, um cliente solicita:

http://apache.myserver.com/somedirectory

O Apache responderá com um HTTP 302 para redirecionar o cliente para

http://apache.myserver.com/somedirectory/

Observe que o URL tem uma barra no final para observar que é um diretório. Observe também que o Apache é "inteligente" usando o nome de host do pedido recebido no cabeçalho de redirecionamento. Tudo bem até agora. No entanto, ao usar nginx com balanceamento de carga, este 301 é enviado para o cliente sem converter o nome upstream nginx em um servidor / domínio real. Então o cliente receberá o seguinte:

GET http://nginx.myserver.com/somedirectory
HTTP 301 Moved Permanently
...
Location: http://myproject:8000/somedirectory/

O myproject é o nome do backend upstream do nginx. Não é um host real que o cliente possa resolver. Parece-me que, em vez disso, o cliente deveria ter sido redirecionado para

http://nginx.myserver.com/somedirectory/  

Ou seja. o nome do back-end upstream deveria ter sido substituído no cabeçalho de resposta. Isso é um bug no nginx ou estou fazendo algo errado?

    
por Jeroen 18.04.2012 / 02:17

2 respostas

2

Acontece que o nginx tem um monte de opções redirect proxy para lidar com esse tipo de problema. Acabei usando algo assim:

location / {
    proxy_pass  http://myproject;
    proxy_set_header Host myproject;
    proxy_redirect http://myproject/ $scheme://$host/;
    proxy_redirect http://myproject:8000/ $scheme://$host/;
}

Isso basicamente substitui o nome do upstream pelo $ host e remove a porta. Isso funcionou no meu caso porque eu estou hospedando nginx nas portas padrão para HTTP / HTTPS. Se o nginx estiver sendo executado em uma porta não padrão, algo como isto é necessário:

    proxy_redirect http://myproject/ $scheme://$host:$server_port/;
    proxy_redirect http://myproject:8000/ $scheme://$host:$server_port/;
    
por 18.04.2012 / 05:38
0

Tente usar server_name_in_redirect assim:

server_name_in_redirect off;

Se isso não funcionar, talvez seja necessário fazer algo com proxy_redirect , embora pareça que seu backend está se comportando corretamente.

    
por 18.04.2012 / 02:31