Question La réécriture Nginx https convertit le POST en GET


Mon serveur proxy fonctionne sur ip A et c’est ainsi que les gens accèdent à mon service Web. La configuration de nginx sera redirigée vers une machine virtuelle sur ip b.

Pour le serveur proxy sur IP A, je l’ai dans mes sites disponibles

server {
        listen 443;
        ssl on;
        ssl_certificate nginx.pem;
        ssl_certificate_key nginx.key;

        client_max_body_size 200M;
        server_name localhost 127.0.0.1;
        server_name_in_redirect off;

        location / {
                proxy_pass http://10.10.0.59:80;
                proxy_redirect http://10.10.0.59:80/ /;

                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

}

server {
        listen 80;
        rewrite     ^(.*)   https://$http_host$1 permanent;
        server_name localhost 127.0.0.1;
        server_name_in_redirect off;
        location / {
                proxy_pass http://10.10.0.59:80;
                proxy_redirect http://10.10.0.59:80/ /;
                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

le proxy_redirect a été pris de Comment puis-je obtenir que nginx transmette les requêtes HTTP POST par réécriture?

Tout ce qui touche l'IP publique atteindra 443 à cause de la réécriture. En interne, nous transmettons à 80 sur la machine virtuelle.

Mais quand je lance un script python tel que celui ci-dessous pour tester notre configuration

import requests

data = {'username': '....', 'password': '.....'}
url = 'http://IP_A/api/service/signup'

res  = requests.post(url, data=data, verify=False)
print res
print res.json
print res.status_code
print res.headers

Je reçois un 405 Method Not Allowed. Dans nginx, nous avons constaté que lorsqu’il atteignait le serveur interne, le nginx interne recevait un GET demande, même si dans l'en-tête d'origine, nous avons fait une POST (Cela a été montré dans le script Python).

Il semble donc que la réécriture pose problème. Une idée comment résoudre ce problème? Lorsque j'ai commenté la réécriture, elle atteint sans aucun doute 80 et elle a été acceptée. Puisque la réécriture a pu communiquer avec notre serveur interne, la réécriture en elle-même n’a aucun problème. C'est juste la réécriture abandonnée POST à GET.

Je vous remercie!

(Cela sera également demandé sur le forum Nginx car il s'agit d'un bloqueur critique ...)


13
2017-10-02 20:38


origine




Réponses:


Ce n'est pas Nginx, c'est votre navigateur.

Note de la RFC2616:

RFC 1945 et RFC 2068 spécifient que le client n'est pas autorisé à changer   la méthode sur la demande redirigée. Cependant, la plupart des utilisateurs existants   les implémentations d’agent traitent 302 comme s’il s’agissait d’une réponse 303,   effectuer un GET sur l'emplacement [..]

Ceci est vrai pour tous les navigateurs populaires et vous ne pouvez rien y faire.


7
2017-10-02 20:49



@ c2h50h Je comprends que la spécification HTTP a déclaré quelque chose de similaire comme ça. Mais que puis-je faire à Nginx? Je veux dire que ceci est une configuration triviale où les gens transmettent 443 à un port interne 80, mais ils peuvent toujours le faire PUT, POST, DELETE, GET. Dans ma configuration précédente, je n'avais pas ce proxy supplémentaire à l'avant servant la foule. J'ai eu la même configuration sur le même serveur interne (notre serveur de test). Cela fonctionne bien. - CppLearner
Rien. C'est 100% côté client. Si un serveur Web, quel qu’il soit, renvoie une redirection 301 ou 302, le navigateur, côté client, remplacera tout type de demande adressée à GET. Aucune configuration côté serveur ou aucun en-tête http renvoyé ne changera cela. C'est comme ça pour des raisons historiques (les premiers navigateurs se comportaient de la sorte à cause d'un malentendu et cela devint un standard de facto). - c2h5oh
Eh bien pour l'un, ce n'est pas vraiment un navigateur. Eh bien, vous pouvez dire que c'est un navigateur parce qu'il utilise le protocole HTTP..okay .. c'est bien. Mais là encore, il semble que cela ne se produise que si je le faisais sur cette configuration à deux couches. Si je devais mettre la même configuration directement sur la machine interne et y exécuter le test, je ne me plaindrai pas. Mais encore une fois, comment les gens font-ils dans leur production? Je suppose que certaines personnes font la même chose, inversez 443 sur une VM qui peut en exécuter 80 uniquement. S'il y a une meilleure pratique, j'aimerais l'apprendre et en entendre parler. - CppLearner
Par navigateur je voulais dire client HTTP et avec tous les clients populaires POST va devenir GET si c'est 301 ou 302 redirigé. Le POST restera POST sur la redirection de proxy, mais pas sur la réécriture. - c2h5oh
RFC2616 à nouveau: If the 307 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued. Ainsi, la plupart des navigateurs vont afficher un message d’avertissement, comme pour les autres clients HTTP, je ne peux même pas deviner leur comportement. - c2h5oh