Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Fix exceptions in logs when failing to get remote room list (#10541)
Browse files Browse the repository at this point in the history
  • Loading branch information
erikjohnston authored Aug 6, 2021
1 parent 1bebc0b commit 60f0534
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 38 deletions.
1 change: 1 addition & 0 deletions changelog.d/10541.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix exceptions in logs when failing to get remote room list.
3 changes: 2 additions & 1 deletion synapse/federation/federation_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1108,7 +1108,8 @@ async def get_public_rooms(
The response from the remote server.
Raises:
HttpResponseException: There was an exception returned from the remote server
HttpResponseException / RequestSendFailed: There was an exception
returned from the remote server
SynapseException: M_FORBIDDEN when the remote server has disallowed publicRoom
requests over federation
Expand Down
46 changes: 28 additions & 18 deletions synapse/handlers/room_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,12 @@ async def get_remote_public_room_list(
include_all_networks: bool = False,
third_party_instance_id: Optional[str] = None,
) -> JsonDict:
"""Get the public room list from remote server
Raises:
SynapseError
"""

if not self.enable_room_list_search:
return {"chunk": [], "total_room_count_estimate": 0}

Expand Down Expand Up @@ -395,13 +401,16 @@ async def get_remote_public_room_list(
limit = None
since_token = None

res = await self._get_remote_list_cached(
server_name,
limit=limit,
since_token=since_token,
include_all_networks=include_all_networks,
third_party_instance_id=third_party_instance_id,
)
try:
res = await self._get_remote_list_cached(
server_name,
limit=limit,
since_token=since_token,
include_all_networks=include_all_networks,
third_party_instance_id=third_party_instance_id,
)
except (RequestSendFailed, HttpResponseException):
raise SynapseError(502, "Failed to fetch room list")

if search_filter:
res = {
Expand All @@ -423,20 +432,21 @@ async def _get_remote_list_cached(
include_all_networks: bool = False,
third_party_instance_id: Optional[str] = None,
) -> JsonDict:
"""Wrapper around FederationClient.get_public_rooms that caches the
result.
"""

repl_layer = self.hs.get_federation_client()
if search_filter:
# We can't cache when asking for search
try:
return await repl_layer.get_public_rooms(
server_name,
limit=limit,
since_token=since_token,
search_filter=search_filter,
include_all_networks=include_all_networks,
third_party_instance_id=third_party_instance_id,
)
except (RequestSendFailed, HttpResponseException):
raise SynapseError(502, "Failed to fetch room list")
return await repl_layer.get_public_rooms(
server_name,
limit=limit,
since_token=since_token,
search_filter=search_filter,
include_all_networks=include_all_networks,
third_party_instance_id=third_party_instance_id,
)

key = (
server_name,
Expand Down
30 changes: 12 additions & 18 deletions synapse/rest/client/v1/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
from synapse.api.errors import (
AuthError,
Codes,
HttpResponseException,
InvalidClientCredentialsError,
ShadowBanError,
SynapseError,
Expand Down Expand Up @@ -783,12 +782,9 @@ async def on_GET(self, request):
Codes.INVALID_PARAM,
)

try:
data = await handler.get_remote_public_room_list(
server, limit=limit, since_token=since_token
)
except HttpResponseException as e:
raise e.to_synapse_error()
data = await handler.get_remote_public_room_list(
server, limit=limit, since_token=since_token
)
else:
data = await handler.get_local_public_room_list(
limit=limit, since_token=since_token
Expand Down Expand Up @@ -836,17 +832,15 @@ async def on_POST(self, request):
Codes.INVALID_PARAM,
)

try:
data = await handler.get_remote_public_room_list(
server,
limit=limit,
since_token=since_token,
search_filter=search_filter,
include_all_networks=include_all_networks,
third_party_instance_id=third_party_instance_id,
)
except HttpResponseException as e:
raise e.to_synapse_error()
data = await handler.get_remote_public_room_list(
server,
limit=limit,
since_token=since_token,
search_filter=search_filter,
include_all_networks=include_all_networks,
third_party_instance_id=third_party_instance_id,
)

else:
data = await handler.get_local_public_room_list(
limit=limit,
Expand Down
92 changes: 91 additions & 1 deletion tests/rest/client/v1/test_rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@

import json
from typing import Iterable
from unittest.mock import Mock
from unittest.mock import Mock, call
from urllib import parse as urlparse

from twisted.internet import defer

import synapse.rest.admin
from synapse.api.constants import EventContentFields, EventTypes, Membership
from synapse.api.errors import HttpResponseException
from synapse.handlers.pagination import PurgeStatus
from synapse.rest import admin
from synapse.rest.client.v1 import directory, login, profile, room
Expand Down Expand Up @@ -1124,6 +1127,93 @@ def test_restricted_auth(self):
self.assertEqual(channel.code, 200, channel.result)


class PublicRoomsTestRemoteSearchFallbackTestCase(unittest.HomeserverTestCase):
"""Test that we correctly fallback to local filtering if a remote server
doesn't support search.
"""

servlets = [
synapse.rest.admin.register_servlets_for_client_rest_resource,
room.register_servlets,
login.register_servlets,
]

def make_homeserver(self, reactor, clock):
return self.setup_test_homeserver(federation_client=Mock())

def prepare(self, reactor, clock, hs):
self.register_user("user", "pass")
self.token = self.login("user", "pass")

self.federation_client = hs.get_federation_client()

def test_simple(self):
"Simple test for searching rooms over federation"
self.federation_client.get_public_rooms.side_effect = (
lambda *a, **k: defer.succeed({})
)

search_filter = {"generic_search_term": "foobar"}

channel = self.make_request(
"POST",
b"/_matrix/client/r0/publicRooms?server=testserv",
content={"filter": search_filter},
access_token=self.token,
)
self.assertEqual(channel.code, 200, channel.result)

self.federation_client.get_public_rooms.assert_called_once_with(
"testserv",
limit=100,
since_token=None,
search_filter=search_filter,
include_all_networks=False,
third_party_instance_id=None,
)

def test_fallback(self):
"Test that searching public rooms over federation falls back if it gets a 404"

# The `get_public_rooms` should be called again if the first call fails
# with a 404, when using search filters.
self.federation_client.get_public_rooms.side_effect = (
HttpResponseException(404, "Not Found", b""),
defer.succeed({}),
)

search_filter = {"generic_search_term": "foobar"}

channel = self.make_request(
"POST",
b"/_matrix/client/r0/publicRooms?server=testserv",
content={"filter": search_filter},
access_token=self.token,
)
self.assertEqual(channel.code, 200, channel.result)

self.federation_client.get_public_rooms.assert_has_calls(
[
call(
"testserv",
limit=100,
since_token=None,
search_filter=search_filter,
include_all_networks=False,
third_party_instance_id=None,
),
call(
"testserv",
limit=None,
since_token=None,
search_filter=None,
include_all_networks=False,
third_party_instance_id=None,
),
]
)


class PerRoomProfilesForbiddenTestCase(unittest.HomeserverTestCase):

servlets = [
Expand Down

0 comments on commit 60f0534

Please sign in to comment.