会话结束

前两个示例介绍了 Twisted Web 的会话 API。这包括访问会话对象、在其上存储状态以及稍后检索它,以及 Session 对象具有与它表示的虚拟会话相关的生命周期的概念。本示例演示了如何对该生命周期进行一些控制,以及在会话过期时如何做出反应。

会话的生命周期由 sessionTimeout 属性控制 Session 类。此属性指定会话在过期之前可以不访问的最长时间(以秒为单位)。默认值为 15 分钟。在本示例中,我们将更改该值。

覆盖该值的一种方法是使用子类

from twisted.web.server import Session

class ShortSession(Session):
    sessionTimeout = 60

为了让 Twisted Web 实际使用此会话类,而不是默认类,还需要覆盖 sessionFactory 属性 Site 。我们可以使用另一个子类来做到这一点,但我们也可以对 Site 的单个实例执行此操作

from twisted.web.server import Site

factory = Site(rootResource)
factory.sessionFactory = ShortSession

为由此 Site 提供服务的请求发出的会话将使用 ShortSession,并且在没有活动的情况下只持续一分钟。

您也可以在会话过期时运行任意函数。这对于清理与会话关联的外部资源、跟踪使用统计信息等很有用。此功能通过 Session.notifyOnExpire 提供。它接受一个参数:一个在会话过期时调用的函数。这是一个简单的示例,它在会话过期时打印一条消息

from twisted.web.resource import Resource

class ExpirationLogger(Resource):
    sessions = set()

    def render_GET(self, request):
        session = request.getSession()
        if session.uid not in self.sessions:
            self.sessions.add(session.uid)
            session.notifyOnExpire(lambda: self._expired(session.uid))
        return ""

    def _expired(self, uid):
        print("Session", uid, "has expired.")
        self.sessions.remove(uid)

请记住,使用方法作为回调将使实例(在本例中为 ExpirationLogger 资源)保留在内存中,直到会话过期。

有了这些部分,这里有一个示例,它在会话过期时打印一条消息,并使用持续 5 秒的会话

from twisted.web.server import Site, Session
from twisted.web.resource import Resource
from twisted.internet import reactor, endpoints

class ShortSession(Session):
    sessionTimeout = 5

class ExpirationLogger(Resource):
    sessions = set()

    def render_GET(self, request):
        session = request.getSession()
        if session.uid not in self.sessions:
            self.sessions.add(session.uid)
            session.notifyOnExpire(lambda: self._expired(session.uid))
        return ""

    def _expired(self, uid):
        print("Session", uid, "has expired.")
        self.sessions.remove(uid)

rootResource = Resource()
rootResource.putChild(b"logme", ExpirationLogger())
factory = Site(rootResource)
factory.sessionFactory = ShortSession

endpoint = endpoints.TCP4ServerEndpoint(reactor, 8080)
endpoint.listen(factory)
reactor.run()

由于需要 Site 自定义,因此此示例不能基于 rpy,因此它恢复了手动 endpoints.TCP4ServerEndpointreactor.run 调用。运行它并访问 /logme 以查看它的运行情况。继续访问它以保持会话处于活动状态。停止访问它 5 秒以查看会话过期消息。