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 directivaSi 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 derewrite
sobre la variable$uri
similar a un DFA (Por cierto, si desearewrite
más acciones de DFA, eche un vistazo a mdoc.su ). Tenga en cuenta que la parte dereturn 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;
}
}