Desativando a decodificação de URL no proxy nginx

21

Quando eu navego para este URL: http://localhost:8080/foo/%5B-%5Dserver ( nc -l 8080) recebe como está:

GET /foo/%5B-%5D HTTP/1.1

No entanto, quando eu proxy esse aplicativo via nginx (1.1.19):

location /foo {
        proxy_pass    http://localhost:8080/foo;
}

A mesma solicitação roteada pela porta nginx é encaminhada com o caminho decodificado:

GET /foo/[-] HTTP/1.1

Os colchetes decodificados no caminho GET estão causando os erros no servidor de destino ( HTTP Status 400 - Caractere ilegal no caminho ... ) à medida que chegam sem escape.

Existe uma maneira de desativar a decodificação de URL ou codificá-la de volta para que o servidor de destino obtenha exatamente o mesmo caminho quando roteado pelo nginx? Alguma regra de reescrita inteligente de URL?

Tomasz Nurkiewicz
fonte
Bug reportado ao nginx: trac.nginx.org/nginx/ticket/262
Tomasz Nurkiewicz

Respostas:

19

Citando Valentin V. Bartenev (que deve receber todo o crédito por esta resposta):

Uma citação da documentação :

  • Se proxy_pass for especificado com URI , ao transmitir uma solicitação ao servidor, parte de uma URI de solicitação normalizada correspondente ao local será substituída por uma URI especificada na diretiva

  • Se proxy_passfor especificado sem URI , um URI de solicitação será passado para o servidor no mesmo formato enviado por um cliente ao processar uma solicitação original

A configuração correta no seu caso seria:

location /foo {
   proxy_pass http://localhost:8080;
}
Tomasz Nurkiewicz
fonte
8
Eu tive que mudar http://localhost:8080/para o http://localhost:8080caso de alguém ter a mesma situação que eu.
precisa saber é o seguinte
4
Por que o Nginx decodifica o URI antes de passá-lo ao servidor de back-end? Não faria mais sentido se mantivesse o URI intocado?
ornitorrinco
@platypus, ele é mantido intacto, até que você comece explicitamente executar as substituições
CNST
2

Observe que a decodificação de URL, comumente conhecida como $uri"normalização" na documentação do nginx, ocorre antes do IFF de back-end:

  • qualquer URI é especificado em proxy_passsi mesmo, mesmo que apenas a barra final por si só,

  • ou, o URI é alterado durante o processamento, por exemplo, através rewrite.


Ambas as condições estão explicitamente documentadas em http://nginx.org/r/proxy_pass (ênfase minha):

  • Se a proxy_passdiretiva for especificada com um URI , quando uma solicitação for passada ao servidor, a parte de uma URI de solicitação normalizada correspondente ao local será substituída por uma URI especificada na diretiva

  • Se proxy_passfor especificado sem um URI , o URI da solicitação será passado para o servidor da mesma forma que foi enviado por um cliente quando a solicitação original for processada ou o URI da solicitação normalizada completa será transmitido ao processar o URI alterado


A solução é omitir o URI como no caso dos OPs ou, de fato, usar uma rewriteregra inteligente :

# map `/foo` to `/foo`:
location /foo {
    proxy_pass  http://localhost:8080;  # no URI -- not even just a slash
}

# map `/foo` to `/bar`:
location /foo {
    rewrite  ^  $request_uri;            # get original URI
    rewrite  ^/foo(/.*)  /bar$1  break;  # drop /foo, put /bar
    return 400;   # if the second rewrite won't match
    proxy_pass    http://localhost:8080$uri;
}

Você pode vê-lo ao vivo em uma resposta de Estouro de pilha relacionada , incluindo um grupo de controle.

cnst
fonte
A documentação é confusa aqui. Ambos os formulários contêm um URI. É o componente do caminho que está presente em um e está ausente no outro.
Michael Hampton
@ MichaelHampton, eu discordo - o PATH é geralmente chamado de URI, portanto, aquele sem o caminho, não contém o URI.
CNST
Apenas um caminho relativo também pode ser um URL válido, é claro. O ponto é que o restante também é um URI válido (por exemplo http://localhost:8080). Se você não concorda, pode aceitar os autores da RFC 3986.
Michael Hampton
@MichaelHampton Unforturnately, parece esquema e caminho são obrigatórios para ser um URI, autoridade, argumentos, fragmento são opcionais
Norman Xu