proxy_pass example nginx load-balancing reverse-proxy

example - Evite los parámetros de consulta de decodificación nginx en proxy_pass(equivalente a AllowEncodedSlashes NoDecode)



nginx vs apache (5)

En algunos casos, el problema no está en el lado de nginx: debe configurar la codificación uri en el conector Tomcat en UTF-8.

Yo uso nginx como un balencer de carga delante de varios tomcats. En mis solicitudes entrantes, he codificado los parámetros de consulta. Pero cuando la solicitud llega a tomcat, los parámetros se decodifican:

solicitud entrante a nginx:

curl -i "http://server/1.1/json/T;cID=1234;pID=1200;rF=http%3A%2F%2Fwww.google.com%2F"

solicitud entrante al tomcat:

curl -i "http://server/1.1/json/T;cID=1234;pID=1200;rF=http:/www.google.com/"

No quiero que mis parámetros de solicitud se transformen, porque en ese caso, mi gato arroja un error 405.

Mi configuración de nginx es la siguiente:

upstream tracking { server front-01.server.com:8080; server front-02.server.com:8080; server front-03.server.com:8080; server front-04.server.com:8080; } server { listen 80; server_name tracking.server.com; access_log /var/log/nginx/tracking-access.log; error_log /var/log/nginx/tracking-error.log; location / { proxy_pass http://tracking/webapp; } }

En mi configuración actual del equilibrador de carga de Apache, tengo la directiva AllowEncodedSlashes que conserva mis parámetros codificados:

AllowEncodedSlashes NoDecode

Necesito pasar de apache a nginx.

Mi pregunta es bastante opuesta a esta pregunta: Evite los parámetros de consulta de escape nginx en proxy_pass


Finalmente encontré la solución: necesito pasar el parámetro $request_uri :

location / { proxy_pass http://tracking/webapp$request_uri; }

De esa manera, los caracteres que se codificaron en la solicitud original no se descodificarán, es decir, se pasarán como están al servidor proxy.


Hay una opción documentada para la directiva Nginx proxy_pass

Si es necesario transmitir URI en la forma no procesada, la directiva proxy_pass debe usarse sin la parte URI :

location /some/path/ { proxy_pass http://127.0.0.1; }

Así que en tu caso podría ser así. No se preocupe por la solicitud de URI, se pasará a los servidores ascendentes

location / { proxy_pass http://tracking; }

Espero eso ayude.


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

  • cualquier URI se especifica dentro del propio proxy_pass , incluso si solo la barra diagonal final es por sí sola,

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

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

  • Si la directiva proxy_pass 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 se especifica proxy_pass sin un URI , el URI de solicitud se pasa al servidor en la misma forma en que lo envía un cliente cuando se procesa la solicitud original, o se pasa el URI de solicitud normalizado completo cuando se procesa el URI modificado

La solución depende de si necesita o no cambiar la URL entre el front-end y el backend.

  • Si no se requiere un cambio de URI:

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

  • De lo contrario, si necesita intercambiar o mapear /api del front-end con /app en el backend, entonces puede obtener el URI original de la variable $request_uri , y usar las directivas de rewrite sobre la variable $uri similar a un DFA (Por cierto, si desea rewrite más acciones de DFA, eche un vistazo a mdoc.su ). Tenga en cuenta que la parte de return 400 es necesaria en caso de que alguien intente sortear su segunda regla de reescritura, ya que no coincidirá con algo como //api/ .

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

  • Si simplemente desea agregar un prefijo para el backend, entonces puede usar la variable $request_uri inmediato:

    # add `/webapp` to the backend: location / { proxy_pass http://localhost:8080/webapp$request_uri; }

También es posible que desee ver una respuesta relacionada , que muestra algunas ejecuciones de prueba del código similar a la anterior.


La respuesta de Jean es buena, pero no funciona con sublocaciones. En ese caso, la respuesta más genérica es:

location /path/ { if ($request_uri ~* "/path/(.*)") { proxy_pass http://tracking/webapp/$1; } }