É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

19
demandé sur Community 2013-12-10 18:22:47

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é.

36
répondu Jean-Philippe Caruana 2015-12-18 14:12:37

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/;
  }
}
11
répondu user1338062 2017-05-23 10:30:04

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.

10
répondu Casey 2016-03-11 03:23:53

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 directive

  • Si 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 la rewrite les directives sur le $uri variable semblable à un DFA (BTW, si vous voulez plus rewrite 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.

2
répondu cnst 2018-04-06 22:58:13

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.

-2
répondu Zeljko 2014-03-06 23:10:26