##language:zh ''' Finger演化:使用单一factory支持多种协议 The Evolution of Finger: using a single factory for multiple protocols ''' -- dreamingk [<>] <> == 介绍(Introduction) == 这是Twisted教程《Twisted入门 - Finger演化》的第八部分。 This is the eighth part of the Twisted tutorial Twisted from Scratch, or The Evolution of Finger. 在这部分中,我们向web前端增加 HTTPS 支持,用于展示如何让单一factory在多个端口上监听(listen)。 In this part, we add HTTPS support to our web frontend, showing how to have a single factory listen on multiple ports. == HTTPS支持(Support HTTPS) == 编写一个 HTTPS 站点我们只需要编写一个上下文(context) factory(在本例中,它会从一个特定的文件中装入证书),接着使用twisted.application.internet.SSLServer方法。请注意一个facotry(在本例中是一个站点)可以使用多种协议在多个端口上进行监听。 All we need to do to code an HTTPS site is just write a context factory (in this case, which loads the certificate from a certain file) and then use the twisted.application.internet.SSLServer method. Note that one factory (in this case, a site) can listen on multiple ports with multiple protocols. {{{ #!python # Do everything properly, and componentize from twisted.application import internet, service from twisted.internet import protocol, reactor, defer from twisted.protocols import basic, irc from twisted.python import components from twisted.web import resource, server, static, xmlrpc, microdom from twisted.web.woven import page, model, interfaces from twisted.spread import pb from OpenSSL import SSL import cgi class IFingerService(components.Interface): def getUser(self, user): """Return a deferred returning a string""" def getUsers(self): """Return a deferred returning a list of strings""" class IFingerSetterService(components.Interface): def setUser(self, user, status): """Set the user's status to something""" def catchError(err): return "Internal error in server" class FingerProtocol(basic.LineReceiver): def lineReceived(self, user): d = self.factory.getUser(user) d.addErrback(catchError) def writeValue(value): self.transport.write(value+'\n') self.transport.loseConnection() d.addCallback(writeValue) class IFingerFactory(components.Interface): def getUser(self, user): """Return a deferred returning a string""" def buildProtocol(self, addr): """Return a protocol returning a string""" class FingerFactoryFromService(protocol.ServerFactory): __implements__ = IFingerFactory, protocol = FingerProtocol def __init__(self, service): self.service = service def getUser(self, user): return self.service.getUser(user) components.registerAdapter(FingerFactoryFromService, IFingerService, IFingerFactory) class FingerSetterProtocol(basic.LineReceiver): def connectionMade(self): self.lines = [] def lineReceived(self, line): self.lines.append(line) def connectionLost(self, reason): if len(self.lines) == 2: self.factory.setUser(*self.lines) class IFingerSetterFactory(components.Interface): def setUser(self, user, status): """Return a deferred returning a string""" def buildProtocol(self, addr): """Return a protocol returning a string""" class FingerSetterFactoryFromService(protocol.ServerFactory): __implements__ = IFingerSetterFactory, protocol = FingerSetterProtocol def __init__(self, service): self.service = service def setUser(self, user, status): self.service.setUser(user, status) components.registerAdapter(FingerSetterFactoryFromService, IFingerSetterService, IFingerSetterFactory) class IRCReplyBot(irc.IRCClient): def connectionMade(self): self.nickname = self.factory.nickname irc.IRCClient.connectionMade(self) def privmsg(self, user, channel, msg): user = user.split('!')[0] if self.nickname.lower() == channel.lower(): d = self.factory.getUser(msg) d.addErrback(catchError) d.addCallback(lambda m: "Status of %s: %s" % (msg, m)) d.addCallback(lambda m: self.msg(user, m)) class IIRCClientFactory(components.Interface): """ @ivar nickname """ def getUser(self, user): """Return a deferred returning a string""" def buildProtocol(self, addr): """Return a protocol""" class IRCClientFactoryFromService(protocol.ClientFactory): __implements__ = IIRCClientFactory, protocol = IRCReplyBot nickname = None def __init__(self, service): self.service = service def getUser(self, user): return self.service.getUser(user) components.registerAdapter(IRCClientFactoryFromService, IFingerService, IIRCClientFactory) class UsersModel(model.MethodModel): def initialize(self, *args, **kwargs): self.service=args[0] def wmfactory_users(self, request): return self.service.getUsers() components.registerAdapter(UsersModel, IFingerService, interfaces.IModel) class UserStatusTree(page.Page): template = """Users

Users

""" def initialize(self, *args, **kwargs): self.service=args[0] def getDynamicChild(self, path, request): return UserStatus(user=path, service=self.service) def wchild_RPC2 (self, request): return UserStatusXR(self.service) components.registerAdapter(UserStatusTree, IFingerService, resource.IResource) class UserStatus(page.Page): template='''</head> <body><h1 view="Text" model="user"/> <p model="status" view="Text" /> </body></html>''' def initialize(self, **kwargs): self.user = kwargs['user'] self.service = kwargs['service'] def wmfactory_user(self, request): return self.user def wmfactory_status(self, request): return self.service.getUser(self.user) class UserStatusXR(xmlrpc.XMLRPC): def __init__(self, service): xmlrpc.XMLRPC.__init__(self) self.service = service def xmlrpc_getUser(self, user): return self.service.getUser(user) def xmlrpc_getUsers(self): return self.service.getUsers() class IPerspectiveFinger(components.Interface): def remote_getUser(self, username): """return a user's status""" def remote_getUsers(self): """return a user's status""" class PerspectiveFingerFromService(pb.Root): __implements__ = pb.Root.__implements__, IPerspectiveFinger def __init__(self, service): self.service = service def remote_getUser(self, username): return self.service.getUser(username) def remote_getUsers(self): return self.service.getUsers() components.registerAdapter(PerspectiveFingerFromService, IFingerService, IPerspectiveFinger) class FingerService(service.Service): __implements__ = IFingerService, def __init__(self, filename): self.filename = filename self._read() def _read(self): self.users = {} for line in file(self.filename): user, status = line.split(':', 1) user = user.strip() status = status.strip() self.users[user] = status self.call = reactor.callLater(30, self._read) def getUser(self, user): return defer.succeed(self.users.get(user, "No such user")) def getUsers(self): return defer.succeed(self.users.keys()) class ServerContextFactory: def getContext(self): """Create an SSL context. This is a sample implementation that loads a certificate from a file called 'server.pem'.""" ctx = SSL.Context(SSL.SSLv23_METHOD) ctx.use_certificate_file('server.pem') ctx.use_privatekey_file('server.pem') return ctx application = service.Application('finger', uid=1, gid=1) f = FingerService('/etc/users') serviceCollection = service.IServiceCollection(application) internet.TCPServer(79, IFingerFactory(f) ).setServiceParent(serviceCollection) site = server.Site(resource.IResource(f)) internet.TCPServer(8000, site ).setServiceParent(serviceCollection) internet.SSLServer(443, site, ServerContextFactory() ).setServiceParent(serviceCollection) i = IIRCClientFactory(f) i.nickname = 'fingerbot' internet.TCPClient('irc.freenode.org', 6667, i ).setServiceParent(serviceCollection) internet.TCPServer(8889, pb.PBServerFactory(IPerspectiveFinger(f)) ).setServiceParent(serviceCollection) }}} Source listing - listings/finger/finger22.py return index-->[[TwistedTUT]] Version: 1.3.0