Éviter les paramètres de requête de décodage nginx sur le pass proxy (équivalent à AllowEncodedSlashes NoDecode)
j'utilise nginx comme balanceur de charge devant plusieurs tomcats. Dans Mes requêtes entrantes, j'ai encodé les paramètres de requête. Mais lorsque la requête arrive à tomcat, les paramètres sont décodés:
requête entrante vers nginx:
curl -i "http://server/1.1/json/T;cID=1234;pID=1200;rF=http%3A%2F%2Fwww.google.com%2F"
requête entrante à tomcat:
curl -i "http://server/1.1/json/T;cID=1234;pID=1200;rF=http:/www.google.com/"
Je ne veux pas que mes paramètres de requête soient transformés, car dans ce cas, mon tomcat lance une erreur 405.
ma configuration nginx est la suivante: :
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;
}
}
dans ma configuration actuelle d'Apache load balancer, j'ai le la directive allowencodedslashes directive qui préserve mes paramètres encodés:
AllowEncodedSlashes NoDecode
je dois passer d'apache à nginx.
ma question est tout le contraire de celle - ci:Evitez que nginx échappe aux paramètres de requête sur proxy_pass
5 réponses
j'ai finalement trouvé la solution: j'ai besoin de passer $request_uri
paramètre:
location / {
proxy_pass http://tracking/webapp$request_uri;
}
de cette façon, les caractères qui ont été encodés dans la requête originale seront être décodé, c'est-à-dire être passé tel quel au serveur mandaté.
la réponse de Jean c'est bon, mais il ne fonctionne pas avec sublocations. Dans ce cas, la réponse plus générale est:
location /path/ {
if ($request_uri ~* "/path/(.*)") {
proxy_pass http://tracking/webapp/;
}
}
il y a une option documentée pour Nginx proxy_pass la directive
S'il est nécessaire de transmettre L'URI sous la forme non traitée, la directive proxy_pass doit être utilisée sans URI part:
location /some/path/ {
proxy_pass http://127.0.0.1;
}
location / {
proxy_pass http://tracking;
}
j'Espère que ça aide.
notez que le décodage D'URL, communément appelé$uri
"normalisation" dans la documentation de nginx, se produit avant le backend IFF:
l'un ou l'autre des URI est spécifié dans
proxy_pass
lui-même, même si seulement le slash arrière tout seul,ou, URI est modifiée au cours du traitement, par exemple, par le biais de
rewrite
.
les deux conditions sont explicitement documentées à http://nginx.org/r/proxy_pass (l'emphase est mienne):
Si le
proxy_pass
la directive est spécifié avec un URI, puis, quand une demande est transmise au serveur, la partie d'un normalisé URI de requête correspondant à l'emplacement est remplacé par un URI spécifié dans la directiveSi
proxy_pass
est spécifié sans URI, L'URI de requête est passé au serveur dans le même formulaire envoyé par un client lorsque la requête originale est traitée,ounormalisé demander URI is passed quand traitement de l' changé URI
le la solution dépend de si oui ou non vous devez changer L'URL entre le front-end et le backend.
Si aucun URI changement est nécessaire:
# map `/foo` to `/foo`: location /foo { proxy_pass http://localhost:8080; # no URI -- not even just a slash }
Sinon, si vous avez besoin d'échanger ou de cartographier
/api
de l'avant avec/app
sur le dos, alors vous pouvez obtenir L'URI original de$request_uri
variable, et l'utilisation de larewrite
les directives sur le$uri
variable semblable à un DFA (BTW, si vous voulez plusrewrite
DFA action, jetez un coup d'oeil à mdoc.su). Notez que l'return 400
une partie est nécessaire au cas où quelqu'un essaie de contourner votre deuxième règle de réécriture, car elle ne correspondrait pas à quelque chose comme//api/
.# map `/api` to `/app`: location /foo { rewrite ^ $request_uri; # get original URI rewrite ^/api(/.*) /app break; # drop /api, put /app return 400; # if the second rewrite won't match proxy_pass http://localhost:8080$uri; }
Si vous souhaitez simplement ajouter un préfixe pour le backend, vous pouvez simplement utiliser le
$request_uri
variable:# add `/webapp` to the backend: location / { proxy_pass http://localhost:8080/webapp$request_uri; }
Vous pouvez également prendre un coup d'oeil à une réponse similaire, qui montre quelques essais de code semblable à celui ci-dessus.
dans certains cas, le problème n'est pas du côté de nginx - vous devez configurer L'encodage uri sur le connecteur Tomcat en UTF-8.