Requests: socket.error: [Errno 54] 对等方重置连接

创建于 2011-09-22  ·  19评论  ·  资料来源: psf/requests

我目前收到错误socket.error: [Errno 54] Connection reset by peer当我使用requests.get(url, params=kwargs)并且params包含大量文本时。 如果我将两个大文本主体截断为每个小于 2,900 个字符,它就可以工作。 如果我使用curl从命令行运行相同的 get 请求,它会起作用。 我正在使用我使用pip install python-requests安装的请求版本 0.6.1。

我不确定如何告诉您复制该问题,因为我正在使用python-sendgrid库向我的 sendgrid 帐户添加时事通讯,并且我不想在问题票证中发布我的 api 用户名和密码。 :)

为了使用 curl 从命令行进行测试,我创建了两个文件,每个文件都包含使用urlencoder进行 urlencoded 的纯文本和 html 文本。 然后我运行了以下命令。

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

最有用的评论

甜蜜的动作! 从requests.get(url, params=kwargs)切换到requests.post(url, data=kwargs)修复了它! 很抱歉打扰您,感谢您的帮助!

所有19条评论

嗯,有意思。 如果这是引发的错误,我就没有理由相信服务器 _is't_ 实际上正在重置连接。

你有像 Charles 这样的 HTTP 代理吗? 它可能有助于阐明实际发生的情况。

抱歉,我忘了提供完整的回溯。 这是我收到错误时得到的回溯。 另外,我不明白如何使用 HTTP 代理以及为什么当它从命令行使用 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

我从 github 得到的回应是......

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

这很奇怪,因为就像我之前提到的,它适用于curl

如果您花时间通过 Charles(或类似方式)查看这两个请求,我相信您会很快发现问题。


正如错误所说,请求 URI 太大,服务器无法处理,因此它正在断开连接。

使用请求,您将所有数据作为请求 URI 中的大量查询字符串发送,称为 GET 参数。 当您使用 curl 时,您将表单编码的数据上传到请求正文,称为 POST 数据。

我试过同时使用requests.get(url, params=kwargs)requests.post(url, params=kwargs)并且都返回相同的错误。 出于某种原因,Charles 没有从 curl 捕获请求,它只是从我的浏览器和使用 python-requests 的 python 命令行脚本捕获请求。

不用担心。

params用于查询字符串, data用于 POST 数据。

甜蜜的动作! 从requests.get(url, params=kwargs)切换到requests.post(url, data=kwargs)修复了它! 很抱歉打扰您,感谢您的帮助!

完全不用担心:)

奇怪的是,我用类似的数据得到了同样的错误,唯一的区别是,在我的情况下,我没有大的参数列表或大小。 通过 CURL 发出的相同请求工作正常,但通过请求给了我这个错误。

requests.exceptions.ConnectionError: HTTPSConnectionPool(host='sbarnea.com', port=443): Max retries exceeded with url: /jira/rest/api/2/group?groupname=jira-administrators&expand=users(由: [Errno 54] 对等方重置连接)

更有趣的是,请求似乎甚至没有到达 Web 服务器。

知道这可能是什么原因吗?

@ssbarnea这个问题已经两年多了:它与您目前遇到的问题无关。 =) 你能打开一个新问题来跟踪你的问题吗?

更好的是,不要打开一个问题,去和 StackOverflow 谈谈,你在问一个问题,你没有理由相信这是请求行为的问题。 在 StackOverflow 上散列详细信息,然后我们可以提交错误报告(如有必要)。

这是一种非常奇怪的行为,我有理由相信这不是请求中的错误,这就是我确实打开了一个新错误的原因。 我仍在调查可能导致这种情况的原因,它只发生在我的机器上,但最有趣的部分是 CURL 工作(和浏览器也是如此)。 谢谢你。

很抱歉把它放在这里,但我找到了原因:

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

通过在 nginx 服务器上禁用这些调整,它开始处理请求,显然其中之一导致了故障。

@ssbarnea
它很可能是一个有问题的服务器,当在特定的 SSL/TLS 版本中说话时做错了事情,如 #1567(以及更多)中描述的那样。
尝试强制使用不同的版本,就像这里解释的那样(对@Lukasa 有更多的赞誉)

赢家(输家)是ssl_protocols TLSv1.2 TLSv1.1;
从服务器上支持的协议中删除TLSv1似乎会阻止请求工作。

现在,我可以将其称为请求或底层库中的错误吗?

注意:出于安全考虑,建议删除 TLSv1,它存在漏洞。

@ssbarnea您会发现限制不在请求中,而是在 Python 中。 目前没有已发布的 Python 版本支持比 V1.0 更新的任何 TLS 版本,如您在此处的表中所见。

Python 3.4(尚未发布,不保证 Requests 与其兼容)允许支持 TLS1.2 和 TLS1.1,因此您可以尝试一下。 否则,您必须允许 TLSv1 允许请求通过。

还有一些奇怪的地方:在这两种情况下,我都使用了 Python,在 OS X 上测试时它失败了,当在 Ubuntu 上测试时它可以工作。

通常我不会触及 SSL 的默认设置,但我运行 SSL 报告并尝试解决大多数警告:

FIPS 要求:禁用 SSL v2 和 SSL v3(仅使用 TLS 版本协议)
另请阅读有关 BEAST 攻击的信息。

在这里检查:
https://sslcheck.globalsign.com/en_US/sslcheck/?host=sbarnea.com

所以,我想知道是否有可能解决这个问题,很明显,如果它适用于 Ubuntu 上的 Python,它不能特定于所有 Python 版本。

嗯,可惜可以。 您获得的ssl支持的相关功能取决于您安装的 OpenSSL 版本。 比较两个版本。 =)

只是想对这个主题做一点总结。 如果您的网络服务器不允许使用 TLSv1,那么您将使用 python 2.7.9 获得 TLSv1.1 和 1.2(将于 2014 年 12 月发布)。 但是,您也可以安装 PYOpenSSL 并将其注入 urrlib3 (http://urllib3.readthedocs.org/en/latest/security.html#openssl-pyopenssl),这似乎允许使用对使用 python 禁用 TLSv1 的网络服务器的请求2.7.6(可能还有其他)。

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

但实际上,网络服务器可能不应该弃用迫使人们跳过这么多奇怪圈子的东西。

此页面是否有帮助?
0 / 5 - 0 等级