mirror of
https://mau.dev/maunium/synapse.git
synced 2024-12-15 14:03:53 +01:00
Merge pull request #747 from matrix-org/markjh/http_resource_tree
Split out create_resource_tree to a separate file
This commit is contained in:
commit
e57df8fa86
2 changed files with 105 additions and 82 deletions
|
@ -66,6 +66,7 @@ from synapse.federation.transport.server import TransportLayerServer
|
||||||
|
|
||||||
from synapse.util.rlimit import change_resource_limit
|
from synapse.util.rlimit import change_resource_limit
|
||||||
from synapse.util.versionstring import get_version_string
|
from synapse.util.versionstring import get_version_string
|
||||||
|
from synapse.util.httpresourcetree import create_resource_tree
|
||||||
|
|
||||||
from synapse import events
|
from synapse import events
|
||||||
|
|
||||||
|
@ -174,7 +175,12 @@ class SynapseHomeServer(HomeServer):
|
||||||
if name == "replication":
|
if name == "replication":
|
||||||
resources[REPLICATION_PREFIX] = ReplicationResource(self)
|
resources[REPLICATION_PREFIX] = ReplicationResource(self)
|
||||||
|
|
||||||
root_resource = create_resource_tree(resources)
|
if WEB_CLIENT_PREFIX in resources:
|
||||||
|
root_resource = RootRedirect(WEB_CLIENT_PREFIX)
|
||||||
|
else:
|
||||||
|
root_resource = Resource()
|
||||||
|
|
||||||
|
root_resource = create_resource_tree(resources, root_resource)
|
||||||
if tls:
|
if tls:
|
||||||
reactor.listenSSL(
|
reactor.listenSSL(
|
||||||
port,
|
port,
|
||||||
|
@ -494,87 +500,6 @@ class SynapseSite(Site):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def create_resource_tree(desired_tree, redirect_root_to_web_client=True):
|
|
||||||
"""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.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
web_client (bool): True to enable the web client.
|
|
||||||
redirect_root_to_web_client (bool): True to redirect '/' to the
|
|
||||||
location of the web client. This does nothing if web_client is not
|
|
||||||
True.
|
|
||||||
"""
|
|
||||||
if redirect_root_to_web_client and WEB_CLIENT_PREFIX in desired_tree:
|
|
||||||
root_resource = RootRedirect(WEB_CLIENT_PREFIX)
|
|
||||||
else:
|
|
||||||
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, res in desired_tree.items():
|
|
||||||
logger.info("Attaching %s to path %s", res, full_path)
|
|
||||||
last_resource = root_resource
|
|
||||||
for path_seg in full_path.split('/')[1:-1]:
|
|
||||||
if path_seg not in last_resource.listNames():
|
|
||||||
# resource doesn't exist, so make a "dummy resource"
|
|
||||||
child_resource = Resource()
|
|
||||||
last_resource.putChild(path_seg, child_resource)
|
|
||||||
res_id = _resource_id(last_resource, path_seg)
|
|
||||||
resource_mappings[res_id] = child_resource
|
|
||||||
last_resource = child_resource
|
|
||||||
else:
|
|
||||||
# we have an existing Resource, use that instead.
|
|
||||||
res_id = _resource_id(last_resource, path_seg)
|
|
||||||
last_resource = resource_mappings[res_id]
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# now attach the actual desired resource
|
|
||||||
last_path_seg = full_path.split('/')[-1]
|
|
||||||
|
|
||||||
# if there is already a resource here, thieve its children and
|
|
||||||
# replace it
|
|
||||||
res_id = _resource_id(last_resource, last_path_seg)
|
|
||||||
if res_id in resource_mappings:
|
|
||||||
# there is a dummy resource at this path already, which needs
|
|
||||||
# to be replaced with the desired resource.
|
|
||||||
existing_dummy_resource = resource_mappings[res_id]
|
|
||||||
for child_name in existing_dummy_resource.listNames():
|
|
||||||
child_res_id = _resource_id(
|
|
||||||
existing_dummy_resource, child_name
|
|
||||||
)
|
|
||||||
child_resource = resource_mappings[child_res_id]
|
|
||||||
# steal the children
|
|
||||||
res.putChild(child_name, child_resource)
|
|
||||||
|
|
||||||
# finally, insert the desired resource in the right place
|
|
||||||
last_resource.putChild(last_path_seg, res)
|
|
||||||
res_id = _resource_id(last_resource, last_path_seg)
|
|
||||||
resource_mappings[res_id] = res
|
|
||||||
|
|
||||||
return root_resource
|
|
||||||
|
|
||||||
|
|
||||||
def _resource_id(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* Resourceb
|
|
||||||
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 run(hs):
|
def run(hs):
|
||||||
PROFILE_SYNAPSE = False
|
PROFILE_SYNAPSE = False
|
||||||
if PROFILE_SYNAPSE:
|
if PROFILE_SYNAPSE:
|
||||||
|
|
98
synapse/util/httpresourcetree.py
Normal file
98
synapse/util/httpresourcetree.py
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
# Copyright 2016 OpenMarket Ltd
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from twisted.web.resource import Resource
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def create_resource_tree(desired_tree, root_resource):
|
||||||
|
"""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.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
web_client (bool): True to enable the web client.
|
||||||
|
root_resource (twisted.web.resource.Resource): The root
|
||||||
|
resource to add the tree to.
|
||||||
|
Returns:
|
||||||
|
twisted.web.resource.Resource: the ``root_resource`` with a tree of
|
||||||
|
child resources added to it.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 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, res in desired_tree.items():
|
||||||
|
logger.info("Attaching %s to path %s", res, full_path)
|
||||||
|
last_resource = root_resource
|
||||||
|
for path_seg in full_path.split('/')[1:-1]:
|
||||||
|
if path_seg not in last_resource.listNames():
|
||||||
|
# resource doesn't exist, so make a "dummy resource"
|
||||||
|
child_resource = Resource()
|
||||||
|
last_resource.putChild(path_seg, child_resource)
|
||||||
|
res_id = _resource_id(last_resource, path_seg)
|
||||||
|
resource_mappings[res_id] = child_resource
|
||||||
|
last_resource = child_resource
|
||||||
|
else:
|
||||||
|
# we have an existing Resource, use that instead.
|
||||||
|
res_id = _resource_id(last_resource, path_seg)
|
||||||
|
last_resource = resource_mappings[res_id]
|
||||||
|
|
||||||
|
# ===========================
|
||||||
|
# now attach the actual desired resource
|
||||||
|
last_path_seg = full_path.split('/')[-1]
|
||||||
|
|
||||||
|
# if there is already a resource here, thieve its children and
|
||||||
|
# replace it
|
||||||
|
res_id = _resource_id(last_resource, last_path_seg)
|
||||||
|
if res_id in resource_mappings:
|
||||||
|
# there is a dummy resource at this path already, which needs
|
||||||
|
# to be replaced with the desired resource.
|
||||||
|
existing_dummy_resource = resource_mappings[res_id]
|
||||||
|
for child_name in existing_dummy_resource.listNames():
|
||||||
|
child_res_id = _resource_id(
|
||||||
|
existing_dummy_resource, child_name
|
||||||
|
)
|
||||||
|
child_resource = resource_mappings[child_res_id]
|
||||||
|
# steal the children
|
||||||
|
res.putChild(child_name, child_resource)
|
||||||
|
|
||||||
|
# finally, insert the desired resource in the right place
|
||||||
|
last_resource.putChild(last_path_seg, res)
|
||||||
|
res_id = _resource_id(last_resource, last_path_seg)
|
||||||
|
resource_mappings[res_id] = res
|
||||||
|
|
||||||
|
return root_resource
|
||||||
|
|
||||||
|
|
||||||
|
def _resource_id(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* Resourceb
|
||||||
|
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)
|
Loading…
Reference in a new issue