Pour notre service web, j'ai écrit une logique pour empêcher multipart/form-data
POST plus grand que, disons, 4mb.La réinitialisation de la connexion TCP se produit lorsque l'application WSGI répond avant de consommer environ ['wsgi.input']
Il se résume à ce qui suit (je l'ai débarrassais tout usage de WebOb et juste réduit à code WSGI plain vanilla):
import paste.httpserver
form = """\
<html>
<body>
<form method="post" enctype="multipart/form-data" action="/">
<input type="file" name="photopicker" />
<input type="submit" />
</form>
</body>
</html>
"""
limit = 4 * 1024 * 1024
def upload_app(environ, start_response):
if environ['REQUEST_METHOD'] == 'POST':
if int(environ.get('CONTENT_LENGTH', '0')) > limit:
start_response('400 Ouch', [('content-type', 'text/plain')])
return ["Upload is too big!"]
# elided: consume the file appropriately
start_response('200 OK', [('content-type', 'text/html')])
return [form]
paste.httpserver.serve(upload_app, port=7007)
Les œuvres présentées logique droite lorsque l'appareil testé. Mais dès que j'essayé d'envoyer des fichiers réels de plus de 4 Mo à ce point final, je suis arrivé des erreurs comme celles-ci sur le côté client:
Error 101 (net::ERR_CONNECTION_RESET): Unknown error.
de Google ChromeThe connection to the server was reset while the page was loading.
de Firefox
même erreur se produit lors de l'utilisation de Python wsgiref
serveur HTTP intégré.
Fait: une fois que j'ai ajouté environ['wsgi.input'].read()
juste avant de répondre avec HTTP 400, le problème de réinitialisation de la connexion a disparu. Bien sûr, ce n'est pas une bonne solution. Il montre juste ce qui se passe lorsque vous consommez complètement l'entrée.
J'ai lu HTTP: The Definitive Guide et j'ai trouvé quelques lignes directrices intéressantes sur la façon dont il était important de gérer soigneusement les connexions TCP lors de l'implémentation de serveurs et de clients HTTP. Il a continué sur comment, au lieu de close
-socket, il était préférable de faire shutdown
, de sorte que le client ait eu la chance de réagir et d'arrêter d'envoyer plus de données au serveur. Peut-être qu'il me manque des détails d'implémentation cruciaux qui empêchent de telles réinitialisations de connexion. Insights quelqu'un?
Voir the gist.
J'ai fait d'autres recherches en ligne. Il s'avère que limiter la taille du corps gracieusement est mal adressée. auteur Nginx Igor Sysoev a une écriture à ce sujet: http://translate.google.com/translate?hl=en&sl=ru&tl=en&u=http://sysoev.ru/web/upload.html Pour résumer: vous devez effectuer une danse "close close", où le serveur envoie la réponse d'erreur, arrête le socket pour l'écriture, et attend le client pendant un certain temps afin d'éviter juste de tuer la connexion à droite. –
Un autre lien pertinent: http://tools.ietf.org/html/draft-ietf-http-connection-00#section-8 Il conseille que le serveur HTTP doit fermer "la moitié de la connexion". –