Requests: socket.error : [Errno 54] Réinitialisation de la connexion par le pair

Créé le 22 sept. 2011  ·  19Commentaires  ·  Source: psf/requests

J'obtiens actuellement l'erreur socket.error: [Errno 54] Connection reset by peer lorsque j'utilise requests.get(url, params=kwargs) et que le params contient de gros corps de texte. Si je tronque les deux gros corps de texte à moins de 2 900 caractères chacun, cela fonctionne. Si j'exécute la même demande d'obtention à partir de la ligne de commande en utilisant curl cela fonctionne. J'utilise la version 0.6.1 des requêtes que j'ai installées à l'aide de pip install python-requests .

Je ne sais pas comment vous dire de reproduire le problème car j'utilise la bibliothèque python-sendgrid pour ajouter une newsletter à mon compte sendgrid et je ne veux pas publier mon nom d'utilisateur et mon mot de passe API dans le ticket de problème. :)

Pour tester à partir de la ligne de commande à l'aide de curl, j'ai créé deux fichiers contenant chacun du texte brut et du texte html codé en urlen à l'aide d'un urlencoder . Ensuite, j'ai exécuté la commande suivante.

export IDENTITY='<my identity number>'
export API_KEY='<my smtp password>'
export API_USER='<my smtp username>'
export NAME='<My Urlencoded Newsletter Name>'
export SUBJECT='<My Urlencoded Newsletter Subject>'
TEXT=`cat urlencoded.txt`; HTML=`cat urlencoded.html`; curl -d "api_user=$API_USER&api_key=$API_KEY&identity=$IDENTITY&name=$NAME&subject=$SUBJECT&text=$TEXT&html=$HTML" https://sendgrid.com/api/newsletter/newsletter/add.json

Commentaire le plus utile

Douce action ! Le passage de requests.get(url, params=kwargs) à requests.post(url, data=kwargs) résolu le problème ! Désolé de vous déranger avec ça et merci pour votre aide !

Tous les 19 commentaires

Hum ... intéressant. Si c'est l'erreur qui est signalée, j'ai peu de raisons de croire que le serveur _n'est pas_ en train de réinitialiser la connexion.

Disposez-vous d'un proxy HTTP comme Charles ? Cela pourrait aider à faire la lumière sur ce qui se passe réellement.

Désolé, j'ai oublié de fournir le retraçage complet. Voici le retraçage que j'obtiens lorsque j'obtiens l'erreur. De plus, je ne comprends pas comment utiliser le proxy HTTP et pourquoi cela ferait une différence lorsqu'il fonctionne à partir de la ligne de commande avec curl.

Traceback (most recent call last):
  File "/Users/oconnor/.virtualenvs/emails/bin/django-admin.py", line 5, in <module>
    management.execute_from_command_line()
  File "/Users/oconnor/.virtualenvs/emails/lib/python2.7/site-packages/django/core/management/__init__.py", line 429, in execute_from_command_line
    utility.execute()
  File "/Users/oconnor/.virtualenvs/emails/lib/python2.7/site-packages/django/core/management/__init__.py", line 379, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/oconnor/.virtualenvs/emails/lib/python2.7/site-packages/django/core/management/base.py", line 191, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/Users/oconnor/.virtualenvs/emails/lib/python2.7/site-packages/django/core/management/base.py", line 220, in execute
    output = self.handle(*args, **options)
  File "/Users/oconnor/Sites/wenworld/emails/emails/management/commands/ww_daily_headlines_send.py", line 114, in handle
    self.add_newsletter_to_sendgrid(sendgrid_newsletter_name, NEWSLETTER_SLUG)
  File "/Users/oconnor/Sites/wenworld/emails/emails/management/commands/ww_daily_headlines_send.py", line 94, in add_newsletter_to_sendgrid
    html=email.html
  File "/Users/oconnor/.virtualenvs/emails/src/sendgrid/src/sendgrid/__init__.py", line 67, in newsletter_add
    subject=subject, text=text, html=html)
  File "/Users/oconnor/.virtualenvs/emails/src/sendgrid/src/sendgrid/__init__.py", line 157, in get
    return self.call(method, **kwargs)
  File "/Users/oconnor/.virtualenvs/emails/src/sendgrid/src/sendgrid/__init__.py", line 56, in call
    result_json = json.loads(response.content)
  File "/Users/oconnor/.virtualenvs/emails/lib/python2.7/site-packages/requests/models.py", line 429, in __getattr__
    self._content = self.read()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 351, in read
    data = self._sock.recv(rbufsize)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 553, in read
    s = self.fp.read(amt)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 1276, in read
    return s + self._file.read(amt - len(s))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 380, in read
    data = self._sock.recv(left)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 219, in recv
    return self.read(buflen)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py", line 138, in read
    return self._sslobj.read(len)
socket.error: [Errno 54] Connection reset by peer

La réponse que je reçois de github est...

<html>
<head><title>414 Request-URI Too Large</title></head>
<body bgcolor="white">
<center><h1>414 Request-URI Too Large</h1></center>
<hr><center>nginx/0.7.65</center>
</body>
</html>

Ce qui est étrange car, comme je l'ai mentionné précédemment, cela fonctionne avec curl .

Si vous prenez le temps de jeter un œil aux deux demandes via Charles (ou similaire), je suis sûr que vous verrez le problème assez rapidement.


Comme l'indique l'erreur, le Request-URI est trop volumineux pour que le serveur le traite, il interrompt donc la connexion.

Avec les requêtes, vous envoyez toutes les données sous la forme d'une chaîne de requête massive dans l'URI de la requête, connue sous le nom de paramètre GET. Lorsque vous utilisez curl, vous téléchargez des données codées par formulaire dans le corps de la demande, appelées données POST.

J'ai essayé d'utiliser à la fois requests.get(url, params=kwargs) et requests.post(url, params=kwargs) et les deux renvoient la même erreur. Pour une raison quelconque, Charles ne capture pas les demandes de curl et il capture simplement les demandes de mon navigateur et de mon script de lignes de commande python qui utilise des requêtes python.

Pas de soucis.

params est pour les chaînes de requête, data est pour les données POST.

Douce action ! Le passage de requests.get(url, params=kwargs) à requests.post(url, data=kwargs) résolu le problème ! Désolé de vous déranger avec ça et merci pour votre aide !

Pas de soucis du tout :)

C'est étrange que j'obtienne la même erreur avec des données similaires, la seule différence est que dans mon cas, je n'ai pas une grande liste ou une grande taille de paramètres. La même demande faite via CURL fonctionne bien mais via les demandes me donne cette erreur.

request.exceptions.ConnectionError : HTTPSConnectionPool(host='sbarnea.com', port=443) : Nombre maximal de tentatives dépassé avec l'url : /jira/rest/api/2/group?groupname=jira-administrators&expand=users (causé par: [Errno 54] Réinitialisation de la connexion par le pair)

Plus intéressant encore, il semble que la requête n'atteigne même pas le serveur web.

Une idée de ce que cela pourrait être la cause ?

@ssbarnea Ce problème date de plus de deux ans : il n'a rien à voir avec le problème que vous rencontrez actuellement. =) Pouvez-vous ouvrir un nouveau numéro pour suivre votre problème s'il vous plaît ?

Mieux encore, n'ouvrez pas de problème, allez parler à StackOverflow, vous posez une question et vous n'avez aucune raison de croire qu'il s'agit d'un problème avec le comportement des requêtes. Renseignez les détails sur StackOverflow, puis nous pourrons déposer un rapport de bogue (si nécessaire).

C'est un comportement très étrange et j'ai des raisons de croire que ce n'est pas un bogue dans les requêtes, c'est pourquoi j'ai ouvert un nouveau bogue. Je suis toujours en train d'enquêter sur ce qui pourrait causer cela, cela ne se produit que depuis ma machine, mais la partie la plus intéressante est que CURL fonctionne (et les navigateurs aussi). Merci.

Désolé de garder ça ici mais j'ai trouvé la cause de ça :

#  resolver 127.0.0.1;
#  ssl_protocols TLSv1.2 TLSv1.1 ; # TLSv1
#  ssl_stapling on;
#  ssl_stapling_verify on;
#  ssl_session_cache builtin:1000;
#  ssl_session_timeout 30m;
#  ssl_ciphers HIGH:!RC4:!aNULL:!MD5;
#  ssl_prefer_server_ciphers on;

En désactivant ces réglages sur le serveur nginx, il a commencé à fonctionner avec les demandes, l'un d'entre eux est clairement à l'origine du dysfonctionnement.

@ssbarnea
Il s'agit très probablement d'un serveur bogué qui fait des choses incorrectes lorsqu'on lui parle dans des versions SSL/TLS spécifiques comme décrit dans #1567 (et plusieurs autres).
Essayez de forcer une version différente comme cela est expliqué ici (plus de félicitations à @Lukasa)

Et le gagnant (perdant) est ssl_protocols TLSv1.2 TLSv1.1;
Il semble que la suppression de TLSv1 des protocoles pris en charge sur le serveur empêche les requêtes de fonctionner.

Maintenant, je peux appeler cela un bogue dans les requêtes ou une bibliothèque sous-jacente ?

Remarque : la suppression de TLSv1 est recommandée en raison de problèmes de sécurité, il y a des exploits avec.

@ssbarnea Vous constaterez que la limitation n'est pas dans les requêtes mais dans Python. Actuellement, aucune version livrée de Python ne prend en charge une version de TLS plus récente que la V1.0, comme vous pouvez le voir dans le tableau ici .

Python 3.4 (pas encore livré, aucune garantie que Requests soit compatible avec lui) permet la prise en charge de TLS1.2 et TLS1.1, vous pouvez donc essayer avec cela. Sinon, vous devrez autoriser TLSv1 à autoriser les requêtes.

Il y a quand même quelque chose d'étrange : dans les deux cas, j'ai utilisé Python, lorsqu'il a été testé à partir d'OS X, il a échoué, lorsqu'il a été testé à partir d'Ubuntu, cela a fonctionné.

Normalement, je ne toucherais pas aux paramètres par défaut pour SSL, mais j'exécute un rapport SSL et j'essaie de résoudre la plupart des avertissements :

FIPS requiert : SSL v2 et SSL v3 sont désactivés (seuls les protocoles de version TLS sont utilisés)
Lisez également à propos des attaques BEAST.

Vérifiez-le ici :
https://sslcheck.globalsign.com/en_US/sslcheck/?host=sbarnea.com

Donc, je me demande s'il est possible de résoudre ce problème, clairement si cela fonctionne avec Python sur Ubuntu, cela ne peut pas être spécifique à toutes les versions de python.

Mm, malheureusement c'est possible. Les fonctionnalités relatives du support ssl vous obtenez dépendent de la version d'OpenSSL que vous avez installée. Comparez les deux versions. =)

Juste pour clore un peu le sujet. Si votre serveur Web n'autorise pas TLSv1, vous obtiendrez TLSv1.1 et 1.2 avec python 2.7.9 (sortie prévue en décembre 2014). Cependant, vous pouvez également installer PYOpenSSL et l'injecter dans urrlib3 (http://urllib3.readthedocs.org/en/latest/security.html#openssl-pyopenssl) qui semble autoriser l'utilisation de requêtes pour un serveur Web qui a désactivé TLSv1 avec python 2.7.6 (et probablement d'autres).

import urllib3.contrib.pyopenssl
urllib3.contrib.pyopenssl.inject_into_urllib3()

Mais vraiment, le serveur Web ne devrait probablement pas désapprouver quelque chose qui oblige les gens à sauter à travers ces nombreux cerceaux étranges.

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