Requests: socket.error: [Errno 54] Conexión restablecida por par

Creado en 22 sept. 2011  ·  19Comentarios  ·  Fuente: psf/requests

Actualmente recibo el error socket.error: [Errno 54] Connection reset by peer cuando uso requests.get(url, params=kwargs) y params contienen grandes cuerpos de texto. Si trunco ​​los dos grandes cuerpos de texto a menos de 2900 caracteres cada uno, funciona. Si ejecuto la misma solicitud de obtención desde la línea de comando usando curl , funciona. Estoy usando solicitudes de la versión 0.6.1 que instalé usando, pip install python-requests .

No estoy seguro de cómo decirle que replique el problema porque estoy usando la biblioteca python-sendgrid para agregar un boletín a mi cuenta de sendgrid y no quiero publicar mi nombre de usuario y contraseña de API en el ticket de emisión. :)

Para probar desde la línea de comando usando curl, creé dos archivos que contenían texto sin formato y texto html que fue codificado en urlencoder usando un urlencoder . Luego ejecuté el siguiente comando.

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

Comentario más útil

¡Acción dulce! ¡Cambiar de requests.get(url, params=kwargs) a requests.post(url, data=kwargs) solucionó! ¡Perdón por molestarte con esto y gracias por la ayuda!

Todos 19 comentarios

Mmm interesante. Si ese es el error que se está produciendo, tengo pocas razones para creer que el servidor _no_ realmente está restableciendo la conexión.

¿Tiene un proxy HTTP como Charles disponible? Podría ayudar a arrojar algo de luz sobre lo que realmente está sucediendo.

Lo siento, olvidé proporcionar el rastreo completo. Aquí está el rastreo que obtengo cuando obtengo el error. Además, no entiendo cómo usar el proxy HTTP y por qué eso marcaría la diferencia cuando funciona desde la línea de comando con 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 respuesta que recibo de github es ...

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

Lo cual es extraño porque, como mencioné antes, funciona con curl .

Si se toma el tiempo de echar un vistazo a las dos solicitudes a través de Charles (o similar), estoy seguro de que verá el problema con bastante rapidez.


Como dice el error, el Request-URI es demasiado grande para que el servidor lo procese, por lo que está interrumpiendo la conexión.

Con Requests, está enviando todos los datos como una cadena de consulta masiva en el URI de solicitud, conocido como parámetro GET. Cuando usa curl, está cargando datos codificados en formulario al cuerpo de la solicitud, conocido como datos POST.

Intenté usar requests.get(url, params=kwargs) y requests.post(url, params=kwargs) y ambos devuelven el mismo error. Por alguna razón, Charles no captura solicitudes de curl y solo captura solicitudes de mi navegador y mi script de líneas de comando de Python que usa solicitudes de Python.

No hay problema.

params es para cadenas de consulta, data es para datos POST.

¡Acción dulce! ¡Cambiar de requests.get(url, params=kwargs) a requests.post(url, data=kwargs) solucionó! ¡Perdón por molestarte con esto y gracias por la ayuda!

Sin preocupaciones :)

Es extraño que me salga el mismo error con datos similares, la única diferencia es que en mi caso no tengo una gran lista o tamaño de parámetros. La misma solicitud realizada a través de CURL funciona bien, pero a través de solicitudes me da este error.

request.exceptions.ConnectionError: HTTPSConnectionPool (host = 'sbarnea.com', port = 443): Se excedió el número máximo de reintentos con url: / jira / rest / api / 2 / group? groupname = jira-administrator & expand = users (Causado por: [Errno 54] Conexión restablecida por par)

Aún más interesante, parece que la solicitud ni siquiera llega al servidor web.

¿Alguna idea de cuál podría ser la causa?

@ssbarnea Este problema tiene más de dos años: no tiene nada que ver con el problema que está experimentando actualmente. =) ¿Puede abrir una nueva edición para realizar un seguimiento de su problema, por favor?

Aún mejor, no abra un problema, vaya a hablar con StackOverflow, está haciendo una pregunta y no tiene ninguna razón para creer que es un problema con el comportamiento de las solicitudes. Elimina los detalles en StackOverflow y luego podemos presentar un informe de error (si es necesario).

Es un comportamiento muy extraño y tengo razones para creer que no es un error en las solicitudes, por eso abrí un nuevo error. Todavía estoy investigando qué podría causar esto, sucede solo desde mi máquina, pero la parte más interesante es que CURL funciona (y los navegadores también). Gracias.

Lamento mantener esto aquí, pero encontré la causa de esto:

#  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;

Al deshabilitar estos ajustes en el servidor nginx, comenzó a trabajar con solicitudes, claramente uno de ellos está causando el mal funcionamiento.

@ssbarnea
Lo más probable es que sea un servidor con errores que hace cosas incorrectas cuando se le habla en versiones específicas de SSL / TLS como se describe en el n. ° 1567 (y varias más).
Intente forzar una versión diferente como se explica aquí (algunas felicitaciones más a @Lukasa)

Y el ganador (perdedor) es ssl_protocols TLSv1.2 TLSv1.1;
Parece que eliminar TLSv1 de los protocolos admitidos en el servidor evita que las solicitudes funcionen.

Ahora, ¿puedo llamar a esto un error en las solicitudes o una biblioteca subyacente?

Nota: se recomienda la eliminación de TLSv1 debido a problemas de seguridad, hay vulnerabilidades con él.

@ssbarnea Verá que la limitación no está en Solicitudes sino en Python. Actualmente, ninguna versión enviada de Python es compatible con ninguna versión de TLS más reciente que la V1.0, como puede ver en la tabla aquí .

Python 3.4 (aún no enviado, no hay garantías de que Requests sea compatible con él) permite la compatibilidad con TLS1.2 y TLS1.1, por lo que puede probar con eso. De lo contrario, tendrá que permitir que TLSv1 permita el paso de las solicitudes.

Todavía hay algo extraño: en ambos casos usé Python, cuando lo probé desde OS X falló, cuando lo probé desde Ubuntu funcionó.

Normalmente no tocaría la configuración predeterminada para SSL, pero ejecuté un informe SSL e intenté resolver la mayoría de las advertencias:

FIPS requiere: SSL v2 y SSL v3 están deshabilitados (solo se utilizan los protocolos de la versión TLS)
Lea también sobre los ataques BEAST.

Compruébalo aquí:
https://sslcheck.globalsign.com/en_US/sslcheck/?host=sbarnea.com

Entonces, me pregunto si es posible solucionar esto, claramente si funciona con Python en Ubuntu, no puede ser específico para todas las versiones de Python.

Mm, lamentablemente puede. Las características relativas del soporte ssl que obtiene dependen de la versión de OpenSSL que haya instalado. Compare las dos versiones. =)

Solo para cerrar un poco el tema. Si su servidor web no permite TLSv1, obtendrá TLSv1.1 y 1.2 con python 2.7.9 (que saldrá en diciembre de 2014). Sin embargo, también puede instalar PYOpenSSL e inyectarlo en urrlib3 (http://urllib3.readthedocs.org/en/latest/security.html#openssl-pyopenssl) que parece permitir el uso de solicitudes para un servidor web que ha deshabilitado TLSv1 con python 2.7.6 (y probablemente otros).

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

Pero, en realidad, el servidor web probablemente no debería estar desaprobando algo que obliga a la gente a superar tantos obstáculos extraños.

¿Fue útil esta página
0 / 5 - 0 calificaciones