Repository: matrix-org/synapse

Issue:
Synapse responds with a 404 with HTML content for unknown URL prefixes
See https://github.com/vector-im/element-web/issues/19738#issuecomment-996804209 for some background, but if you request an endpoint for Synapse that doesn't have a prefix registered (see [here](https://github.com/matrix-org/synapse/blob/71f9966f2790c6b24281bb9f109bff28ff05d962/synapse/app/homeserver.py#L185-L196)) then Synapse responds with a 404 including HTML content (the default Twisted 404 handler).

This wasn't an issue when adding new `/unstable` or `/r0` endpoints since the prefix was registered, but the `/hierarchy` endpoint is the first `/v1` endpoint we had. This will also bite us once we need to rev an endpoint to `/v2` (or `/v4`) since neither of those are registered right now.


Discussion:
> then Synapse responds with a 404 including HTML content (the default Twisted 404 handler).

and without an ACAO header so browser-based clients can't even read that its a 404 as the browser just gives them a generic failure due to CORS.

Resolving patch:
diff --git a/synapse/app/homeserver.py b/synapse/app/homeserver.py
--- a/synapse/app/homeserver.py
+++ b/synapse/app/homeserver.py
@@ -27,6 +27,7 @@
 import synapse.config.logger
 from synapse import events
 from synapse.api.urls import (
+    CLIENT_API_PREFIX,
     FEDERATION_PREFIX,
     LEGACY_MEDIA_PREFIX,
     MEDIA_R0_PREFIX,
@@ -192,13 +193,7 @@ def _configure_named_resource(
 
             resources.update(
                 {
-                    "/_matrix/client/api/v1": client_resource,
-                    "/_matrix/client/r0": client_resource,
-                    "/_matrix/client/v1": client_resource,
-                    "/_matrix/client/v3": client_resource,
-                    "/_matrix/client/unstable": client_resource,
-                    "/_matrix/client/v2_alpha": client_resource,
-                    "/_matrix/client/versions": client_resource,
+                    CLIENT_API_PREFIX: client_resource,
                     "/.well-known": well_known_resource(self),
                     "/_synapse/admin": AdminRestResource(self),
                     **build_synapse_client_resource_tree(self),
diff --git a/synapse/http/server.py b/synapse/http/server.py
--- a/synapse/http/server.py
+++ b/synapse/http/server.py
@@ -530,7 +530,7 @@ class RootRedirect(resource.Resource):
     """Redirects the root '/' path to another path."""
 
     def __init__(self, path: str):
-        resource.Resource.__init__(self)
+        super().__init__()
         self.url = path
 
     def render_GET(self, request: Request) -> bytes:
@@ -539,7 +539,7 @@ def render_GET(self, request: Request) -> bytes:
     def getChild(self, name: str, request: Request) -> resource.Resource:
         if len(name) == 0:
             return self  # select ourselves as the child to render
-        return resource.Resource.getChild(self, name, request)
+        return super().getChild(name, request)
 
 
 class OptionsResource(resource.Resource):
@@ -556,7 +556,7 @@ def render_OPTIONS(self, request: Request) -> bytes:
     def getChildWithDefault(self, path: str, request: Request) -> resource.Resource:
         if request.method == b"OPTIONS":
             return self  # select ourselves as the child to render
-        return resource.Resource.getChildWithDefault(self, path, request)
+        return super().getChildWithDefault(path, request)
 
 
 class RootOptionsRedirectResource(OptionsResource, RootRedirect):


Test patch: