diff --git a/synapse/handlers/directory.py b/synapse/handlers/directory.py index 7c89150d99..2e9c6b688b 100644 --- a/synapse/handlers/directory.py +++ b/synapse/handlers/directory.py @@ -18,6 +18,7 @@ from twisted.internet import defer from ._base import BaseHandler from synapse.api.errors import SynapseError +from synapse.http.client import HttpClient import logging @@ -68,7 +69,10 @@ class DirectoryHandler(BaseHandler): result = yield self.federation.make_query( destination=room_alias.domain, query_type="directory", - args={"room_alias": room_alias.to_string()}, + args={ + "room_alias": room_alias.to_string(), + HttpClient.RETRY_DNS_LOOKUP_FAILURES: False + } ) if result and "room_id" in result and "servers" in result: diff --git a/synapse/http/client.py b/synapse/http/client.py index 709c952226..f74e3eca73 100644 --- a/synapse/http/client.py +++ b/synapse/http/client.py @@ -44,6 +44,7 @@ _destination_mappings = { class HttpClient(object): """ Interface for talking json over http """ + RETRY_DNS_LOOKUP_FAILURES = "__retry_dns" def put_json(self, destination, path, data): """ Sends the specifed json data using PUT @@ -143,13 +144,23 @@ class TwistedHttpClient(HttpClient): destination = _destination_mappings[destination] logger.debug("get_json args: %s", args) + + retry_on_dns_fail = True + if HttpClient.RETRY_DNS_LOOKUP_FAILURES in args: + # FIXME: This isn't ideal, but the interface exposed in get_json + # isn't comprehensive enough to give caller's any control over + # their connection mechanics. + retry_on_dns_fail = args.pop(HttpClient.RETRY_DNS_LOOKUP_FAILURES) + query_bytes = urllib.urlencode(args, True) + logger.debug("Query bytes: %s Retry DNS: %s", args, retry_on_dns_fail) response = yield self._create_request( destination.encode("ascii"), "GET", path.encode("ascii"), - query_bytes=query_bytes + query_bytes=query_bytes, + retry_on_dns_fail=retry_on_dns_fail ) body = yield readBody(response) @@ -158,7 +169,8 @@ class TwistedHttpClient(HttpClient): @defer.inlineCallbacks def _create_request(self, destination, method, path_bytes, param_bytes=b"", - query_bytes=b"", producer=None, headers_dict={}): + query_bytes=b"", producer=None, headers_dict={}, + retry_on_dns_fail=True): """ Creates and sends a request to the given url """ headers_dict[b"User-Agent"] = [b"Synapse"] @@ -199,11 +211,12 @@ class TwistedHttpClient(HttpClient): logger.debug("Got response to %s", method) break - except DNSLookupError as dns: - logger.warn("DNS Lookup failed to %s with %s", destination, - dns) - raise SynapseError(400, "Domain specified not found.") except Exception as e: + if not retry_on_dns_fail and isinstance(e, DNSLookupError): + logger.warn("DNS Lookup failed to %s with %s", destination, + e) + raise SynapseError(400, "Domain specified not found.") + logger.exception("Got error in _create_request") _print_ex(e) diff --git a/tests/handlers/test_directory.py b/tests/handlers/test_directory.py index 88ac8933f8..e509c1b629 100644 --- a/tests/handlers/test_directory.py +++ b/tests/handlers/test_directory.py @@ -21,6 +21,7 @@ from mock import Mock import logging from synapse.server import HomeServer +from synapse.http.client import HttpClient from synapse.handlers.directory import DirectoryHandler from synapse.storage.directory import RoomAliasMapping @@ -92,7 +93,10 @@ class DirectoryTestCase(unittest.TestCase): self.mock_federation.make_query.assert_called_with( destination="remote", query_type="directory", - args={"room_alias": "#another:remote"} + args={ + "room_alias": "#another:remote", + HttpClient.RETRY_DNS_LOOKUP_FAILURES: False + } ) @defer.inlineCallbacks