Twisted.web.server 如果连接被客户端取消则不通知

Twisted.web.server does not notify if a connection is cancelled by client

documentation 意味着如果连接因任何原因断开,应通知 request.notifyFinish()Deferred。我在下面加载了类似的代码:

from twisted.web.resource import Resource
from twisted.web.server import NOT_DONE_YET
from twisted.internet import reactor
from twisted.logger import Logger

log = Logger()

class DelayedResource(Resource):
    isLeaf = 1

    def _delayedRender(self, request):
        log.info("Rendered!")
        request.write("<html><body>Sorry to keep you waiting.</body></html>")
        request.finish()

    def _responseFailed(self, err, call):
        call.cancel()
        log.info("No. Wait. Stop")

    def render_GET(self, request):
        log.info("Lets try this!")
        call = reactor.callLater(5, self._delayedRender, request)
        request.notifyFinish().addErrback(self._responseFailed, call)
        return NOT_DONE_YET

如果我从客户端取消连接,_responseFailed 不会被调用。永远不会打印日志语句 "No. Wait. Stop",而打印 "Rendered!" 语句

这很重要,因为在我的实际用例中,我正在分配连接断开时需要释放的资源。升级到 twisted 17.1.0 后,这些不再被清理。

我做错了吗?或者这是扭曲的错误?

这是由于 http://tm.tl/8320 but recently fixed by http://tm.tl/8692 引入的错误(或意外引入的功能 - 你来判断!)。因此,Twisted 16.3 到 Twisted 17.5 不会触发 notifyFinish()Failure(尽管它似乎仍然在 success 案例)。由于 HTTP 实现的复杂性和 TCP 的底层特性,在 HTTP 客户端观察到某种错误的情况下,即使是超出该范围的 Twisted 版本也可能不会总是触发 notifyFinish()Failure。请记住这一点,并确保必须在请求结束时发生的任何处理不依赖于此 Deferred 上的 errback(即附加 回调 或确保处理作为响应生成代码的一部分运行)。