summary refs log tree commit diff
path: root/synapse/rest/client/v1
diff options
context:
space:
mode:
authorMark Haines <mark.haines@matrix.org>2015-12-01 19:15:27 +0000
committerMark Haines <mark.haines@matrix.org>2015-12-01 19:15:27 +0000
commitf73ea0bda26a51794abedb65cbf4d0a717dee26c (patch)
tree64fd41675594a7c71a7f119fb68b5b476f9173fd /synapse/rest/client/v1
parentOnly fire user_joined_room on the distributor if the user has actually joined... (diff)
parentMerge pull request #392 from matrix-org/markjh/client_config (diff)
downloadsynapse-f73ea0bda26a51794abedb65cbf4d0a717dee26c.tar.xz
Merge branch 'develop' into markjh/edu_frequency
Diffstat (limited to 'synapse/rest/client/v1')
-rw-r--r--synapse/rest/client/v1/admin.py4
-rw-r--r--synapse/rest/client/v1/base.py10
-rw-r--r--synapse/rest/client/v1/directory.py4
-rw-r--r--synapse/rest/client/v1/events.py6
-rw-r--r--synapse/rest/client/v1/initial_sync.py4
-rw-r--r--synapse/rest/client/v1/login.py12
-rw-r--r--synapse/rest/client/v1/presence.py8
-rw-r--r--synapse/rest/client/v1/profile.py8
-rw-r--r--synapse/rest/client/v1/push_rule.py4
-rw-r--r--synapse/rest/client/v1/pusher.py4
-rw-r--r--synapse/rest/client/v1/register.py4
-rw-r--r--synapse/rest/client/v1/room.py90
-rw-r--r--synapse/rest/client/v1/voip.py4
13 files changed, 84 insertions, 78 deletions
diff --git a/synapse/rest/client/v1/admin.py b/synapse/rest/client/v1/admin.py
index bdde43864c..0103697889 100644
--- a/synapse/rest/client/v1/admin.py
+++ b/synapse/rest/client/v1/admin.py
@@ -18,7 +18,7 @@ from twisted.internet import defer
 from synapse.api.errors import AuthError, SynapseError
 from synapse.types import UserID
 
-from base import ClientV1RestServlet, client_path_pattern
+from base import ClientV1RestServlet, client_path_patterns
 
 import logging
 
@@ -26,7 +26,7 @@ logger = logging.getLogger(__name__)
 
 
 class WhoisRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/admin/whois/(?P<user_id>[^/]*)")
+    PATTERNS = client_path_patterns("/admin/whois/(?P<user_id>[^/]*)", releases=())
 
     @defer.inlineCallbacks
     def on_GET(self, request, user_id):
diff --git a/synapse/rest/client/v1/base.py b/synapse/rest/client/v1/base.py
index 504a5e432f..7ae3839a19 100644
--- a/synapse/rest/client/v1/base.py
+++ b/synapse/rest/client/v1/base.py
@@ -27,7 +27,7 @@ import logging
 logger = logging.getLogger(__name__)
 
 
-def client_path_pattern(path_regex):
+def client_path_patterns(path_regex, releases=(0,)):
     """Creates a regex compiled client path with the correct client path
     prefix.
 
@@ -37,7 +37,13 @@ def client_path_pattern(path_regex):
     Returns:
         SRE_Pattern
     """
-    return re.compile("^" + CLIENT_PREFIX + path_regex)
+    patterns = [re.compile("^" + CLIENT_PREFIX + path_regex)]
+    unstable_prefix = CLIENT_PREFIX.replace("/api/v1", "/unstable")
+    patterns.append(re.compile("^" + unstable_prefix + path_regex))
+    for release in releases:
+        new_prefix = CLIENT_PREFIX.replace("/api/v1", "/r%d" % release)
+        patterns.append(re.compile("^" + new_prefix + path_regex))
+    return patterns
 
 
 class ClientV1RestServlet(RestServlet):
diff --git a/synapse/rest/client/v1/directory.py b/synapse/rest/client/v1/directory.py
index 240eedac75..f488e2dd41 100644
--- a/synapse/rest/client/v1/directory.py
+++ b/synapse/rest/client/v1/directory.py
@@ -18,7 +18,7 @@ from twisted.internet import defer
 
 from synapse.api.errors import AuthError, SynapseError, Codes
 from synapse.types import RoomAlias
-from .base import ClientV1RestServlet, client_path_pattern
+from .base import ClientV1RestServlet, client_path_patterns
 
 import simplejson as json
 import logging
@@ -32,7 +32,7 @@ def register_servlets(hs, http_server):
 
 
 class ClientDirectoryServer(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/directory/room/(?P<room_alias>[^/]*)$")
+    PATTERNS = client_path_patterns("/directory/room/(?P<room_alias>[^/]*)$")
 
     @defer.inlineCallbacks
     def on_GET(self, request, room_alias):
diff --git a/synapse/rest/client/v1/events.py b/synapse/rest/client/v1/events.py
index 3e1750d1a1..41b97e7d15 100644
--- a/synapse/rest/client/v1/events.py
+++ b/synapse/rest/client/v1/events.py
@@ -18,7 +18,7 @@ from twisted.internet import defer
 
 from synapse.api.errors import SynapseError
 from synapse.streams.config import PaginationConfig
-from .base import ClientV1RestServlet, client_path_pattern
+from .base import ClientV1RestServlet, client_path_patterns
 from synapse.events.utils import serialize_event
 
 import logging
@@ -28,7 +28,7 @@ logger = logging.getLogger(__name__)
 
 
 class EventStreamRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/events$")
+    PATTERNS = client_path_patterns("/events$")
 
     DEFAULT_LONGPOLL_TIME_MS = 30000
 
@@ -72,7 +72,7 @@ class EventStreamRestServlet(ClientV1RestServlet):
 
 # TODO: Unit test gets, with and without auth, with different kinds of events.
 class EventRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/events/(?P<event_id>[^/]*)$")
+    PATTERNS = client_path_patterns("/events/(?P<event_id>[^/]*)$")
 
     def __init__(self, hs):
         super(EventRestServlet, self).__init__(hs)
diff --git a/synapse/rest/client/v1/initial_sync.py b/synapse/rest/client/v1/initial_sync.py
index 856a70f297..9ad3df8a9f 100644
--- a/synapse/rest/client/v1/initial_sync.py
+++ b/synapse/rest/client/v1/initial_sync.py
@@ -16,12 +16,12 @@
 from twisted.internet import defer
 
 from synapse.streams.config import PaginationConfig
-from base import ClientV1RestServlet, client_path_pattern
+from base import ClientV1RestServlet, client_path_patterns
 
 
 # TODO: Needs unit testing
 class InitialSyncRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/initialSync$")
+    PATTERNS = client_path_patterns("/initialSync$")
 
     @defer.inlineCallbacks
     def on_GET(self, request):
diff --git a/synapse/rest/client/v1/login.py b/synapse/rest/client/v1/login.py
index 720d6358e7..b0b641e430 100644
--- a/synapse/rest/client/v1/login.py
+++ b/synapse/rest/client/v1/login.py
@@ -18,7 +18,7 @@ from twisted.internet import defer
 from synapse.api.errors import SynapseError, LoginError, Codes
 from synapse.http.client import SimpleHttpClient
 from synapse.types import UserID
-from base import ClientV1RestServlet, client_path_pattern
+from base import ClientV1RestServlet, client_path_patterns
 
 import simplejson as json
 import urllib
@@ -36,7 +36,7 @@ logger = logging.getLogger(__name__)
 
 
 class LoginRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/login$")
+    PATTERNS = client_path_patterns("/login$", releases=())
     PASS_TYPE = "m.login.password"
     SAML2_TYPE = "m.login.saml2"
     CAS_TYPE = "m.login.cas"
@@ -238,7 +238,7 @@ class LoginRestServlet(ClientV1RestServlet):
 
 
 class SAML2RestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/login/saml2")
+    PATTERNS = client_path_patterns("/login/saml2", releases=())
 
     def __init__(self, hs):
         super(SAML2RestServlet, self).__init__(hs)
@@ -282,7 +282,7 @@ class SAML2RestServlet(ClientV1RestServlet):
 
 # TODO Delete this after all CAS clients switch to token login instead
 class CasRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/login/cas")
+    PATTERNS = client_path_patterns("/login/cas", releases=())
 
     def __init__(self, hs):
         super(CasRestServlet, self).__init__(hs)
@@ -293,7 +293,7 @@ class CasRestServlet(ClientV1RestServlet):
 
 
 class CasRedirectServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/login/cas/redirect")
+    PATTERNS = client_path_patterns("/login/cas/redirect", releases=())
 
     def __init__(self, hs):
         super(CasRedirectServlet, self).__init__(hs)
@@ -316,7 +316,7 @@ class CasRedirectServlet(ClientV1RestServlet):
 
 
 class CasTicketServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/login/cas/ticket")
+    PATTERNS = client_path_patterns("/login/cas/ticket", releases=())
 
     def __init__(self, hs):
         super(CasTicketServlet, self).__init__(hs)
diff --git a/synapse/rest/client/v1/presence.py b/synapse/rest/client/v1/presence.py
index 6fe5d19a22..e0949fe4bb 100644
--- a/synapse/rest/client/v1/presence.py
+++ b/synapse/rest/client/v1/presence.py
@@ -19,7 +19,7 @@ from twisted.internet import defer
 
 from synapse.api.errors import SynapseError
 from synapse.types import UserID
-from .base import ClientV1RestServlet, client_path_pattern
+from .base import ClientV1RestServlet, client_path_patterns
 
 import simplejson as json
 import logging
@@ -28,7 +28,7 @@ logger = logging.getLogger(__name__)
 
 
 class PresenceStatusRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/presence/(?P<user_id>[^/]*)/status")
+    PATTERNS = client_path_patterns("/presence/(?P<user_id>[^/]*)/status")
 
     @defer.inlineCallbacks
     def on_GET(self, request, user_id):
@@ -73,7 +73,7 @@ class PresenceStatusRestServlet(ClientV1RestServlet):
 
 
 class PresenceListRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/presence/list/(?P<user_id>[^/]*)")
+    PATTERNS = client_path_patterns("/presence/list/(?P<user_id>[^/]*)")
 
     @defer.inlineCallbacks
     def on_GET(self, request, user_id):
@@ -120,7 +120,7 @@ class PresenceListRestServlet(ClientV1RestServlet):
                 if len(u) == 0:
                     continue
                 invited_user = UserID.from_string(u)
-                yield self.handlers.presence_handler.send_invite(
+                yield self.handlers.presence_handler.send_presence_invite(
                     observer_user=user, observed_user=invited_user
                 )
 
diff --git a/synapse/rest/client/v1/profile.py b/synapse/rest/client/v1/profile.py
index 3218e47025..e6c6e5d024 100644
--- a/synapse/rest/client/v1/profile.py
+++ b/synapse/rest/client/v1/profile.py
@@ -16,14 +16,14 @@
 """ This module contains REST servlets to do with profile: /profile/<paths> """
 from twisted.internet import defer
 
-from .base import ClientV1RestServlet, client_path_pattern
+from .base import ClientV1RestServlet, client_path_patterns
 from synapse.types import UserID
 
 import simplejson as json
 
 
 class ProfileDisplaynameRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/profile/(?P<user_id>[^/]*)/displayname")
+    PATTERNS = client_path_patterns("/profile/(?P<user_id>[^/]*)/displayname")
 
     @defer.inlineCallbacks
     def on_GET(self, request, user_id):
@@ -56,7 +56,7 @@ class ProfileDisplaynameRestServlet(ClientV1RestServlet):
 
 
 class ProfileAvatarURLRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/profile/(?P<user_id>[^/]*)/avatar_url")
+    PATTERNS = client_path_patterns("/profile/(?P<user_id>[^/]*)/avatar_url")
 
     @defer.inlineCallbacks
     def on_GET(self, request, user_id):
@@ -89,7 +89,7 @@ class ProfileAvatarURLRestServlet(ClientV1RestServlet):
 
 
 class ProfileRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/profile/(?P<user_id>[^/]*)")
+    PATTERNS = client_path_patterns("/profile/(?P<user_id>[^/]*)")
 
     @defer.inlineCallbacks
     def on_GET(self, request, user_id):
diff --git a/synapse/rest/client/v1/push_rule.py b/synapse/rest/client/v1/push_rule.py
index b0870db1ac..edf5b0ca41 100644
--- a/synapse/rest/client/v1/push_rule.py
+++ b/synapse/rest/client/v1/push_rule.py
@@ -18,7 +18,7 @@ from twisted.internet import defer
 from synapse.api.errors import (
     SynapseError, Codes, UnrecognizedRequestError, NotFoundError, StoreError
 )
-from .base import ClientV1RestServlet, client_path_pattern
+from .base import ClientV1RestServlet, client_path_patterns
 from synapse.storage.push_rule import (
     InconsistentRuleException, RuleNotFoundException
 )
@@ -31,7 +31,7 @@ import simplejson as json
 
 
 class PushRuleRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/pushrules/.*$")
+    PATTERNS = client_path_patterns("/pushrules/.*$")
     SLIGHTLY_PEDANTIC_TRAILING_SLASH_ERROR = (
         "Unrecognised request: You probably wanted a trailing slash")
 
diff --git a/synapse/rest/client/v1/pusher.py b/synapse/rest/client/v1/pusher.py
index a110c0a4f0..6f465035b4 100644
--- a/synapse/rest/client/v1/pusher.py
+++ b/synapse/rest/client/v1/pusher.py
@@ -17,13 +17,13 @@ from twisted.internet import defer
 
 from synapse.api.errors import SynapseError, Codes
 from synapse.push import PusherConfigException
-from .base import ClientV1RestServlet, client_path_pattern
+from .base import ClientV1RestServlet, client_path_patterns
 
 import simplejson as json
 
 
 class PusherRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/pushers/set$")
+    PATTERNS = client_path_patterns("/pushers/set$")
 
     @defer.inlineCallbacks
     def on_POST(self, request):
diff --git a/synapse/rest/client/v1/register.py b/synapse/rest/client/v1/register.py
index a56834e365..5b95d63e25 100644
--- a/synapse/rest/client/v1/register.py
+++ b/synapse/rest/client/v1/register.py
@@ -18,7 +18,7 @@ from twisted.internet import defer
 
 from synapse.api.errors import SynapseError, Codes
 from synapse.api.constants import LoginType
-from base import ClientV1RestServlet, client_path_pattern
+from base import ClientV1RestServlet, client_path_patterns
 import synapse.util.stringutils as stringutils
 
 from synapse.util.async import run_on_reactor
@@ -48,7 +48,7 @@ class RegisterRestServlet(ClientV1RestServlet):
     handler doesn't have a concept of multi-stages or sessions.
     """
 
-    PATTERN = client_path_pattern("/register$")
+    PATTERNS = client_path_patterns("/register$", releases=())
 
     def __init__(self, hs):
         super(RegisterRestServlet, self).__init__(hs)
diff --git a/synapse/rest/client/v1/room.py b/synapse/rest/client/v1/room.py
index 6952d269ec..d86d266465 100644
--- a/synapse/rest/client/v1/room.py
+++ b/synapse/rest/client/v1/room.py
@@ -16,7 +16,7 @@
 """ This module contains REST servlets to do with rooms: /rooms/<paths> """
 from twisted.internet import defer
 
-from base import ClientV1RestServlet, client_path_pattern
+from base import ClientV1RestServlet, client_path_patterns
 from synapse.api.errors import SynapseError, Codes, AuthError
 from synapse.streams.config import PaginationConfig
 from synapse.api.constants import EventTypes, Membership
@@ -34,16 +34,16 @@ class RoomCreateRestServlet(ClientV1RestServlet):
     # No PATTERN; we have custom dispatch rules here
 
     def register(self, http_server):
-        PATTERN = "/createRoom"
-        register_txn_path(self, PATTERN, http_server)
+        PATTERNS = "/createRoom"
+        register_txn_path(self, PATTERNS, http_server)
         # define CORS for all of /rooms in RoomCreateRestServlet for simplicity
-        http_server.register_path("OPTIONS",
-                                  client_path_pattern("/rooms(?:/.*)?$"),
-                                  self.on_OPTIONS)
+        http_server.register_paths("OPTIONS",
+                                   client_path_patterns("/rooms(?:/.*)?$"),
+                                   self.on_OPTIONS)
         # define CORS for /createRoom[/txnid]
-        http_server.register_path("OPTIONS",
-                                  client_path_pattern("/createRoom(?:/.*)?$"),
-                                  self.on_OPTIONS)
+        http_server.register_paths("OPTIONS",
+                                   client_path_patterns("/createRoom(?:/.*)?$"),
+                                   self.on_OPTIONS)
 
     @defer.inlineCallbacks
     def on_PUT(self, request, txn_id):
@@ -103,18 +103,18 @@ class RoomStateEventRestServlet(ClientV1RestServlet):
         state_key = ("/rooms/(?P<room_id>[^/]*)/state/"
                      "(?P<event_type>[^/]*)/(?P<state_key>[^/]*)$")
 
-        http_server.register_path("GET",
-                                  client_path_pattern(state_key),
-                                  self.on_GET)
-        http_server.register_path("PUT",
-                                  client_path_pattern(state_key),
-                                  self.on_PUT)
-        http_server.register_path("GET",
-                                  client_path_pattern(no_state_key),
-                                  self.on_GET_no_state_key)
-        http_server.register_path("PUT",
-                                  client_path_pattern(no_state_key),
-                                  self.on_PUT_no_state_key)
+        http_server.register_paths("GET",
+                                   client_path_patterns(state_key),
+                                   self.on_GET)
+        http_server.register_paths("PUT",
+                                   client_path_patterns(state_key),
+                                   self.on_PUT)
+        http_server.register_paths("GET",
+                                   client_path_patterns(no_state_key, releases=()),
+                                   self.on_GET_no_state_key)
+        http_server.register_paths("PUT",
+                                   client_path_patterns(no_state_key, releases=()),
+                                   self.on_PUT_no_state_key)
 
     def on_GET_no_state_key(self, request, room_id, event_type):
         return self.on_GET(request, room_id, event_type, "")
@@ -170,8 +170,8 @@ class RoomSendEventRestServlet(ClientV1RestServlet):
 
     def register(self, http_server):
         # /rooms/$roomid/send/$event_type[/$txn_id]
-        PATTERN = ("/rooms/(?P<room_id>[^/]*)/send/(?P<event_type>[^/]*)")
-        register_txn_path(self, PATTERN, http_server, with_get=True)
+        PATTERNS = ("/rooms/(?P<room_id>[^/]*)/send/(?P<event_type>[^/]*)")
+        register_txn_path(self, PATTERNS, http_server, with_get=True)
 
     @defer.inlineCallbacks
     def on_POST(self, request, room_id, event_type, txn_id=None):
@@ -215,8 +215,8 @@ class JoinRoomAliasServlet(ClientV1RestServlet):
 
     def register(self, http_server):
         # /join/$room_identifier[/$txn_id]
-        PATTERN = ("/join/(?P<room_identifier>[^/]*)")
-        register_txn_path(self, PATTERN, http_server)
+        PATTERNS = ("/join/(?P<room_identifier>[^/]*)")
+        register_txn_path(self, PATTERNS, http_server)
 
     @defer.inlineCallbacks
     def on_POST(self, request, room_identifier, txn_id=None):
@@ -280,7 +280,7 @@ class JoinRoomAliasServlet(ClientV1RestServlet):
 
 # TODO: Needs unit testing
 class PublicRoomListRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/publicRooms$")
+    PATTERNS = client_path_patterns("/publicRooms$")
 
     @defer.inlineCallbacks
     def on_GET(self, request):
@@ -291,7 +291,7 @@ class PublicRoomListRestServlet(ClientV1RestServlet):
 
 # TODO: Needs unit testing
 class RoomMemberListRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/members$")
+    PATTERNS = client_path_patterns("/rooms/(?P<room_id>[^/]*)/members$")
 
     @defer.inlineCallbacks
     def on_GET(self, request, room_id):
@@ -328,7 +328,7 @@ class RoomMemberListRestServlet(ClientV1RestServlet):
 
 # TODO: Needs better unit testing
 class RoomMessageListRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/messages$")
+    PATTERNS = client_path_patterns("/rooms/(?P<room_id>[^/]*)/messages$")
 
     @defer.inlineCallbacks
     def on_GET(self, request, room_id):
@@ -351,7 +351,7 @@ class RoomMessageListRestServlet(ClientV1RestServlet):
 
 # TODO: Needs unit testing
 class RoomStateRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/state$")
+    PATTERNS = client_path_patterns("/rooms/(?P<room_id>[^/]*)/state$")
 
     @defer.inlineCallbacks
     def on_GET(self, request, room_id):
@@ -368,7 +368,7 @@ class RoomStateRestServlet(ClientV1RestServlet):
 
 # TODO: Needs unit testing
 class RoomInitialSyncRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/initialSync$")
+    PATTERNS = client_path_patterns("/rooms/(?P<room_id>[^/]*)/initialSync$")
 
     @defer.inlineCallbacks
     def on_GET(self, request, room_id):
@@ -384,7 +384,7 @@ class RoomInitialSyncRestServlet(ClientV1RestServlet):
 
 
 class RoomTriggerBackfill(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/rooms/(?P<room_id>[^/]*)/backfill$")
+    PATTERNS = client_path_patterns("/rooms/(?P<room_id>[^/]*)/backfill$", releases=())
 
     def __init__(self, hs):
         super(RoomTriggerBackfill, self).__init__(hs)
@@ -408,7 +408,7 @@ class RoomTriggerBackfill(ClientV1RestServlet):
 
 
 class RoomEventContext(ClientV1RestServlet):
-    PATTERN = client_path_pattern(
+    PATTERNS = client_path_patterns(
         "/rooms/(?P<room_id>[^/]*)/context/(?P<event_id>[^/]*)$"
     )
 
@@ -447,9 +447,9 @@ class RoomMembershipRestServlet(ClientV1RestServlet):
 
     def register(self, http_server):
         # /rooms/$roomid/[invite|join|leave]
-        PATTERN = ("/rooms/(?P<room_id>[^/]*)/"
-                   "(?P<membership_action>join|invite|leave|ban|kick|forget)")
-        register_txn_path(self, PATTERN, http_server)
+        PATTERNS = ("/rooms/(?P<room_id>[^/]*)/"
+                    "(?P<membership_action>join|invite|leave|ban|kick|forget)")
+        register_txn_path(self, PATTERNS, http_server)
 
     @defer.inlineCallbacks
     def on_POST(self, request, room_id, membership_action, txn_id=None):
@@ -543,8 +543,8 @@ class RoomMembershipRestServlet(ClientV1RestServlet):
 
 class RoomRedactEventRestServlet(ClientV1RestServlet):
     def register(self, http_server):
-        PATTERN = ("/rooms/(?P<room_id>[^/]*)/redact/(?P<event_id>[^/]*)")
-        register_txn_path(self, PATTERN, http_server)
+        PATTERNS = ("/rooms/(?P<room_id>[^/]*)/redact/(?P<event_id>[^/]*)")
+        register_txn_path(self, PATTERNS, http_server)
 
     @defer.inlineCallbacks
     def on_POST(self, request, room_id, event_id, txn_id=None):
@@ -582,7 +582,7 @@ class RoomRedactEventRestServlet(ClientV1RestServlet):
 
 
 class RoomTypingRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern(
+    PATTERNS = client_path_patterns(
         "/rooms/(?P<room_id>[^/]*)/typing/(?P<user_id>[^/]*)$"
     )
 
@@ -615,7 +615,7 @@ class RoomTypingRestServlet(ClientV1RestServlet):
 
 
 class SearchRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern(
+    PATTERNS = client_path_patterns(
         "/search$"
     )
 
@@ -655,20 +655,20 @@ def register_txn_path(servlet, regex_string, http_server, with_get=False):
         http_server : The http_server to register paths with.
         with_get: True to also register respective GET paths for the PUTs.
     """
-    http_server.register_path(
+    http_server.register_paths(
         "POST",
-        client_path_pattern(regex_string + "$"),
+        client_path_patterns(regex_string + "$"),
         servlet.on_POST
     )
-    http_server.register_path(
+    http_server.register_paths(
         "PUT",
-        client_path_pattern(regex_string + "/(?P<txn_id>[^/]*)$"),
+        client_path_patterns(regex_string + "/(?P<txn_id>[^/]*)$"),
         servlet.on_PUT
     )
     if with_get:
-        http_server.register_path(
+        http_server.register_paths(
             "GET",
-            client_path_pattern(regex_string + "/(?P<txn_id>[^/]*)$"),
+            client_path_patterns(regex_string + "/(?P<txn_id>[^/]*)$"),
             servlet.on_GET
         )
 
diff --git a/synapse/rest/client/v1/voip.py b/synapse/rest/client/v1/voip.py
index eb7c57cade..1567a03c89 100644
--- a/synapse/rest/client/v1/voip.py
+++ b/synapse/rest/client/v1/voip.py
@@ -15,7 +15,7 @@
 
 from twisted.internet import defer
 
-from base import ClientV1RestServlet, client_path_pattern
+from base import ClientV1RestServlet, client_path_patterns
 
 
 import hmac
@@ -24,7 +24,7 @@ import base64
 
 
 class VoipRestServlet(ClientV1RestServlet):
-    PATTERN = client_path_pattern("/voip/turnServer$")
+    PATTERNS = client_path_patterns("/voip/turnServer$")
 
     @defer.inlineCallbacks
     def on_GET(self, request):