Deshabilitar la decodificación de URL en el proxy nginx


21

Cuando busco esta URL: http://localhost:8080/foo/%5B-%5Dserver ( nc -l 8080) lo recibe tal cual:

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

Sin embargo, cuando proxy esta aplicación a través de nginx (1.1.19):

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

La misma solicitud enrutada a través del puerto nginx se reenvía con la ruta decodificada:

GET /foo/[-] HTTP/1.1

Los corchetes decodificados en la ruta GET están causando los errores en el servidor de destino ( Estado HTTP 400 - Carácter ilegal en la ruta ... ) cuando llegan sin escapar.

¿Hay alguna manera de deshabilitar la decodificación de URL o codificarla de nuevo para que el servidor de destino obtenga exactamente la misma ruta cuando se enruta a través de nginx? ¿Alguna regla inteligente de reescritura de URL?


Respuestas:


19

Citando a Valentin V. Bartenev (quién debería obtener el crédito completo por esta respuesta):

Una cita de la documentación :

  • Si proxy_pass se especifica con URI , al pasar una solicitud al servidor, parte de un URI de solicitud normalizada que coincide con la ubicación se reemplaza por un URI especificado en la directiva

  • Si proxy_passse especifica sin URI , un URI de solicitud se pasa al servidor en la misma forma que lo envió un cliente al procesar una solicitud original

La configuración correcta en su caso sería:

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

8
Tuve que cambiar http://localhost:8080/a http://localhost:8080por si alguien tiene la misma situación que yo.
herrtim

44
¿Por qué Nginx decodifica el URI antes de pasarlo al servidor de fondo? ¿No tendría más sentido mantener intacto el URI?
ornitorrinco

@platypus, se mantiene intacto, hasta que comience explícitamente a realizar las sustituciones
cnst

2

Tenga en cuenta que la decodificación de URL, comúnmente conocida como $uri"normalización" dentro de la documentación de nginx, ocurre antes del IFF de fondo:

  • o cualquier URI se especifica dentro de proxy_passsí mismo, incluso si solo la barra inclinada final por sí misma,

  • o, URI se cambia durante el procesamiento, por ejemplo, a través de rewrite.


Ambas condiciones están explícitamente documentadas en http://nginx.org/r/proxy_pass (el énfasis es mío):

  • Si la proxy_passdirectiva se especifica con un URI , cuando se pasa una solicitud al servidor, la parte de un URI de solicitud normalizada que coincide con la ubicación se reemplaza por un URI especificado en la directiva

  • Si proxy_passse especifica sin un URI , el URI de solicitud se pasa al servidor en la misma forma que lo envió un cliente cuando se procesa la solicitud original, o el URI de solicitud normalizado completo se pasa al procesar el URI modificado


La solución es omitir el URI como en el caso de los OP, o, de hecho, usar una rewriteregla 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;
}

Puede verlo en vivo en una respuesta de desbordamiento de pila relacionada , incluido el grupo de control.


La documentación es confusa aquí. Ambas formas contienen un URI. Es el componente de ruta que está presente en uno y que falta en el otro.
Michael Hampton

@MichaelHampton, no estoy de acuerdo: la RUTA generalmente se llama URI, por lo que el que no tiene la ruta no contiene el URI.
cnst

Una ruta relativa sola también puede ser una URL válida, por supuesto. El punto es que el resto también es un URI válido (por ejemplo http://localhost:8080). Si no está de acuerdo, puede hablar con los autores de RFC 3986.
Michael Hampton

@MichaelHampton Desafortunadamente, parece que el esquema y el camino son obligatorios para ser un URI, la autoridad, los argumentos y el fragmento son opcionales
Norman Xu
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.