Werkzeug: Les requêtes groupées ne fonctionnent toujours pas vraiment

Créé le 16 juil. 2017  ·  4Commentaires  ·  Source: pallets/werkzeug

(Mise à jour, car j'ai réalisé que j'avais essayé de résoudre ce problème, j'ai donc été confus par le problème d'origine et le problème qui m'a fait abandonner)

Je fais une requête fragmentée à une application qui utilise Werkzeug (actuel git master). get_input_stream finit par appeler LimitedStream(wsgi.input, min(content_length, max_content_length)) . min(content_length, max_content_length) sera toujours None si vous utilisez un encodage fragmenté.

Pour tenter de progresser, j'ai essayé d'utiliser LimitedStream(stream, content_length or max_content_length) , mais je finis par obtenir une exception ClientDisconnected , car nous ne pouvons pas faire la différence entre un client qui se déconnecte et la demande fragmentée simplement en cours , car wsgi.input.read() renvoie simplement une chaîne de longueur 0 dans les deux cas.

bug

Commentaire le plus utile

Quel wsgi prend actuellement en charge input_terminated ? Après avoir passé toute la journée à déboguer pourquoi les données sont vides, puis pourquoi le flux est vide, puis j'ai réalisé que c'était dû à l'encodage de flux fragmenté.

Tous les 4 commentaires

C'est plus qu'un simple bug avec min . Après avoir corrigé cela, le problème est que faire wsgi.input.read(max_content_length) avec Werkzeug bloque pour toujours s'il y a moins de max_content_length à lire. Ou en utilisant Gunicorn, qui prend en charge les morceaux en analysant et en mettant en mémoire tampon l'ensemble du message, la longueur est inférieure à max_content_length , donc LimitedStream pense que le client est déconnecté.

J'ai testé cela sur Django juste pour être sûr que nous ne faisons pas quelque chose de bizarre, il voit aussi un flux vide.

Le moyen le plus simple est de fournir un middleware qui définit environ['wsgi.input_terminated'] et de dire aux gens de l'utiliser lorsqu'ils utilisent un serveur qui prend en charge le transfert en bloc.

Quel wsgi prend actuellement en charge input_terminated ? Après avoir passé toute la journée à déboguer pourquoi les données sont vides, puis pourquoi le flux est vide, puis j'ai réalisé que c'était dû à l'encodage de flux fragmenté.

En plus de vérifier environ.get('wsgi.input_terminated') devrions-nous également vérifier environ.get('HTTP_TRANSFER_ENCODING') == 'chunked' et dans ce cas également renvoyer le flux déballé directement ? Cela résout des problèmes comme un simple curl -H 'Transfer-Encoding: chunked' ... renvoyant un flux vide.

Selon RFC2616

4.4.2
Si un champ d'en-tête Transfer-Encoding (section 14.41) est présent et
a une valeur autre que "identité", alors la longueur de transfert est
défini par l'utilisation du codage de transfert "en morceaux" (section 3.6),
à moins que le message ne se termine par la fermeture de la connexion.

4.4.3
Si un champ d'en-tête Content-Length (section 14.13) est présent, son
la valeur décimale dans les OCTET représente à la fois la longueur de l'entité et le
longueur de transfert. Le champ d'en-tête Content-Length NE DOIT PAS être envoyé
si ces deux longueurs sont différentes (c'est-à-dire si un Transfer-Encoding
le champ d'en-tête est présent). Si un message est reçu avec à la fois un
un champ d'en-tête Transfer-Encoding et un champ d'en-tête Content-Length,
ce dernier DOIT être ignoré.

... notant que Transfer-Encoding de chunked exige que tout en-tête Content-Length soit ignoré, et donc aucun traitement de flux ne doit être effectué sur cette base. C'est actuellement le cas, sauf si wsgi.input_terminated est défini.

Devrait-il vraiment être nécessaire de définir wsgi.input_terminated pour que l'encodage en morceaux normal, par exemple une charge utile JSON de 10 octets, fonctionne ?

Cette page vous a été utile?
0 / 5 - 0 notes