From 9f863d34663a4d58cf59cd15e0b0aa4a8e8581a5 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 14 Aug 2014 09:52:20 +0100 Subject: Start phasing out HttpServer: we should be using Resources instead. Added resource_for_client/federation/web_client to the HomeServer and hooked the C-S servlets to operate on resource_for_client. Dynamically construct the Resource tree. --- synapse/app/homeserver.py | 77 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) (limited to 'synapse/app') diff --git a/synapse/app/homeserver.py b/synapse/app/homeserver.py index 82afb04c7d..1acc87e99c 100644 --- a/synapse/app/homeserver.py +++ b/synapse/app/homeserver.py @@ -21,8 +21,12 @@ from synapse.server import HomeServer from twisted.internet import reactor from twisted.enterprise import adbapi from twisted.python.log import PythonLoggingObserver -from synapse.http.server import TwistedHttpServer +from twisted.web.resource import Resource +from twisted.web.static import File +from twisted.web.server import Site +from synapse.http.server import TwistedHttpServer, JsonResource from synapse.http.client import TwistedHttpClient +from synapse.rest.base import CLIENT_PREFIX from daemonize import Daemonize @@ -41,6 +45,15 @@ class SynapseHomeServer(HomeServer): def build_http_client(self): return TwistedHttpClient() + def build_resource_for_client(self): + return JsonResource() + + def build_resource_for_federation(self): + return JsonResource() + + def build_resource_for_web_client(self): + return File("webclient") + def build_db_pool(self): """ Set up all the dbs. Since all the *.sql have IF NOT EXISTS, so we don't have to worry about overwriting existing content. @@ -73,6 +86,65 @@ class SynapseHomeServer(HomeServer): return pool + def create_resource_tree(self): + """Create the resource tree for this Home Server. + + This in unduly complicated because Twisted does not support putting + child resources more than 1 level deep at a time. + """ + desired_tree = ( # list of tuples containing (path_str, Resource) + ("/matrix/client", self.get_resource_for_web_client()), + (CLIENT_PREFIX, self.get_resource_for_client()) + ) + + self.root_resource = Resource() + # ideally we'd just use getChild and putChild but getChild doesn't work + # unless you give it a Request object IN ADDITION to the name :/ So + # instead, we'll store a copy of this mapping so we can actually add + # extra resources to existing nodes. See self._resource_id for the key. + resource_mappings = {} + for (full_path, resource) in desired_tree: + logging.info("Attaching %s to path %s", resource, full_path) + last_resource = self.root_resource + for path_seg in full_path.split('/')[1:-1]: + if not path_seg in last_resource.listNames(): + # resource doesn't exist + child_resource = Resource() + last_resource.putChild(path_seg, child_resource) + res_id = self._resource_id(last_resource, path_seg) + resource_mappings[res_id] = child_resource + last_resource = child_resource + else: + # we have an existing Resource, pull it out. + res_id = self._resource_id(last_resource, path_seg) + last_resource = resource_mappings[res_id] + + # now attach the actual resource + last_path_seg = full_path.split('/')[-1] + last_resource.putChild(last_path_seg, resource) + res_id = self._resource_id(last_resource, last_path_seg) + resource_mappings[res_id] = resource + + return self.root_resource + + def _resource_id(self, resource, path_seg): + """Construct an arbitrary resource ID so you can retrieve the mapping + later. + + If you want to represent resource A putChild resource B with path C, + the mapping should looks like _resource_id(A,C) = B. + + Args: + resource (Resource): The *parent* Resource + path_seg (str): The name of the child Resource to be attached. + Returns: + str: A unique string which can be a key to the child Resource. + """ + return "%s-%s" % (resource, path_seg) + + def start_listening(self, port): + reactor.listenTCP(port, Site(self.root_resource)) + def setup_logging(verbosity=0, filename=None, config_path=None): """ Sets up logging with verbosity levels. @@ -150,7 +222,8 @@ def setup(): hs.register_servlets() - hs.get_http_server().start_listening(args.port) + hs.create_resource_tree() + hs.start_listening(args.port) hs.build_db_pool() -- cgit 1.4.1