我正在尝试运行一个 python 脚本,该脚本在一定的时间间隔内调用外部 API(我只有读取访问权限),该 API 使用基于 cookie 的身份验证:调用 /auth
端点最初设置 session cookie,然后将其用于进一步请求中的身份验证。
至于我的问题:因为身份验证基于事件 session ,所以一旦连接断开,cookie 就无效,因此必须重新启动。据我所知,requests
基于urllib3
,它默认保持连接处于事件状态。然而,经过几次测试,我发现在某些情况下,连接无论如何都会被断开。
我使用了 requests
模块中的 Session
对象,并测试了断开连接所需的时间,如下所示:
from requests import session
import logging
import time import time, sleep
logging.basicConfig(level=logging.DEBUG)
def tt(interval):
credentials = {"username":"user","password":"pass"}
s = Session()
r = s.post("https://<host>:<port>/auth", json=credentials)
ts = time()
while r.status_code is 200:
r = s.get("https://<host>:<port>/some/other/endpoint")
sleep(interval)
return time() - ts # Seconds until connection drop
可能不是找出这个问题的最佳方法,但我让该函数运行两次,一次间隔 1 秒,然后间隔 1 分钟。两者都运行了大约一个小时,直到我不得不手动停止执行。
但是,当我在 while
循环中交换两行时,这意味着在初始 POST/auth
请求之后有 1 分钟的延迟,以下 GET
请求失败,并出现 401 Unauthorized
,并且此消息已预先记录:
DEBUG:urllib3.connectionpool:Resetting dropped connection: <host>
由于我的产品脚本中的请求间隔可能从几分钟到几个小时不等,因此我必须事先知道这些 session 保持事件状态的时间以及该规则是否有一些异常(exception)(例如,如果没有,则断开连接)在初始 POST/auth
发出一段时间后发出请求)。
那么,requests
或者更确切地说 urllib3
使连接保持事件状态多长时间,是否可以无限期地延长该时间?
或者是服务器而不是请求
断开了连接?
最佳答案
通过使用requests.Session
,keep-alive is handled for you automatically .
在调用 /auth
后连续轮询服务器的循环的第一个版本中,服务器不会由于后续的 GET
而断开连接发生。在第二个版本中, sleep 间隔很可能超过服务器配置为保持连接打开的时间。
根据 API 的服务器配置,响应 header 可能包含一个 Keep-Alive
header ,其中包含有关连接至少保持打开状态的时间的信息。 HTTP/1.0
指定此信息包含在 Keep-Alive
header 的 timeout
参数中。您可以使用此信息来确定服务器断开连接之前还有多长时间。
在 HTTP/1.1
中,默认情况下使用持久连接,并且不使用 Keep-Alive
header ,除非服务器明确实现它以实现向后兼容性。由于这种差异,客户端无法立即确定连接的确切超时时间,因为它可能仅作为服务器端配置存在。
保持连接打开的关键是继续定期轮询。您使用的时间间隔必须小于服务器配置的连接超时。
另一件事需要指出的是,以这种方式人为地无限期地延长 session 长度会使人更容易受到 session fixation attacks 的攻击。 。您可能需要考虑添加偶尔重新建立 session 的逻辑,以最大限度地降低此类攻击的风险。
关于python请求无限期地保持连接事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59162353/