mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-07-25 08:45:25 -04:00
Remove trailing slashes from outbound federation requests and retry on 400 (#4840)
As per #3622, we remove trailing slashes from outbound federation requests. However, to ensure that we remain backwards compatible with previous versions of Synapse, if we receive a HTTP 400 with `M_UNRECOGNIZED`, then we are likely talking to an older version of Synapse in which case we retry with a trailing slash appended to the request path.
This commit is contained in:
commit
7bef97dfb7
5 changed files with 191 additions and 17 deletions
|
@ -51,9 +51,10 @@ class TransportLayerClient(object):
|
|||
logger.debug("get_room_state dest=%s, room=%s",
|
||||
destination, room_id)
|
||||
|
||||
path = _create_v1_path("/state/%s/", room_id)
|
||||
path = _create_v1_path("/state/%s", room_id)
|
||||
return self.client.get_json(
|
||||
destination, path=path, args={"event_id": event_id},
|
||||
try_trailing_slash_on_400=True,
|
||||
)
|
||||
|
||||
@log_function
|
||||
|
@ -73,9 +74,10 @@ class TransportLayerClient(object):
|
|||
logger.debug("get_room_state_ids dest=%s, room=%s",
|
||||
destination, room_id)
|
||||
|
||||
path = _create_v1_path("/state_ids/%s/", room_id)
|
||||
path = _create_v1_path("/state_ids/%s", room_id)
|
||||
return self.client.get_json(
|
||||
destination, path=path, args={"event_id": event_id},
|
||||
try_trailing_slash_on_400=True,
|
||||
)
|
||||
|
||||
@log_function
|
||||
|
@ -95,8 +97,11 @@ class TransportLayerClient(object):
|
|||
logger.debug("get_pdu dest=%s, event_id=%s",
|
||||
destination, event_id)
|
||||
|
||||
path = _create_v1_path("/event/%s/", event_id)
|
||||
return self.client.get_json(destination, path=path, timeout=timeout)
|
||||
path = _create_v1_path("/event/%s", event_id)
|
||||
return self.client.get_json(
|
||||
destination, path=path, timeout=timeout,
|
||||
try_trailing_slash_on_400=True,
|
||||
)
|
||||
|
||||
@log_function
|
||||
def backfill(self, destination, room_id, event_tuples, limit):
|
||||
|
@ -121,7 +126,7 @@ class TransportLayerClient(object):
|
|||
# TODO: raise?
|
||||
return
|
||||
|
||||
path = _create_v1_path("/backfill/%s/", room_id)
|
||||
path = _create_v1_path("/backfill/%s", room_id)
|
||||
|
||||
args = {
|
||||
"v": event_tuples,
|
||||
|
@ -132,6 +137,7 @@ class TransportLayerClient(object):
|
|||
destination,
|
||||
path=path,
|
||||
args=args,
|
||||
try_trailing_slash_on_400=True,
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
|
@ -176,6 +182,7 @@ class TransportLayerClient(object):
|
|||
json_data_callback=json_data_callback,
|
||||
long_retries=True,
|
||||
backoff_on_404=True, # If we get a 404 the other side has gone
|
||||
try_trailing_slash_on_400=True,
|
||||
)
|
||||
|
||||
defer.returnValue(response)
|
||||
|
@ -959,7 +966,7 @@ def _create_v1_path(path, *args):
|
|||
|
||||
Example:
|
||||
|
||||
_create_v1_path("/event/%s/", event_id)
|
||||
_create_v1_path("/event/%s", event_id)
|
||||
|
||||
Args:
|
||||
path (str): String template for the path
|
||||
|
@ -980,7 +987,7 @@ def _create_v2_path(path, *args):
|
|||
|
||||
Example:
|
||||
|
||||
_create_v2_path("/event/%s/", event_id)
|
||||
_create_v2_path("/event/%s", event_id)
|
||||
|
||||
Args:
|
||||
path (str): String template for the path
|
||||
|
|
|
@ -188,6 +188,57 @@ class MatrixFederationHttpClient(object):
|
|||
|
||||
self._cooperator = Cooperator(scheduler=schedule)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _send_request_with_optional_trailing_slash(
|
||||
self,
|
||||
request,
|
||||
try_trailing_slash_on_400=False,
|
||||
**send_request_args
|
||||
):
|
||||
"""Wrapper for _send_request which can optionally retry the request
|
||||
upon receiving a combination of a 400 HTTP response code and a
|
||||
'M_UNRECOGNIZED' errcode. This is a workaround for Synapse <= v0.99.3
|
||||
due to #3622.
|
||||
|
||||
Args:
|
||||
request (MatrixFederationRequest): details of request to be sent
|
||||
try_trailing_slash_on_400 (bool): Whether on receiving a 400
|
||||
'M_UNRECOGNIZED' from the server to retry the request with a
|
||||
trailing slash appended to the request path.
|
||||
send_request_args (Dict): A dictionary of arguments to pass to
|
||||
`_send_request()`.
|
||||
|
||||
Raises:
|
||||
HttpResponseException: If we get an HTTP response code >= 300
|
||||
(except 429).
|
||||
|
||||
Returns:
|
||||
Deferred[Dict]: Parsed JSON response body.
|
||||
"""
|
||||
try:
|
||||
response = yield self._send_request(
|
||||
request, **send_request_args
|
||||
)
|
||||
except HttpResponseException as e:
|
||||
# Received an HTTP error > 300. Check if it meets the requirements
|
||||
# to retry with a trailing slash
|
||||
if not try_trailing_slash_on_400:
|
||||
raise
|
||||
|
||||
if e.code != 400 or e.to_synapse_error().errcode != "M_UNRECOGNIZED":
|
||||
raise
|
||||
|
||||
# Retry with a trailing slash if we received a 400 with
|
||||
# 'M_UNRECOGNIZED' which some endpoints can return when omitting a
|
||||
# trailing slash on Synapse <= v0.99.3.
|
||||
request.path += "/"
|
||||
|
||||
response = yield self._send_request(
|
||||
request, **send_request_args
|
||||
)
|
||||
|
||||
defer.returnValue(response)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _send_request(
|
||||
self,
|
||||
|
@ -196,7 +247,7 @@ class MatrixFederationHttpClient(object):
|
|||
timeout=None,
|
||||
long_retries=False,
|
||||
ignore_backoff=False,
|
||||
backoff_on_404=False
|
||||
backoff_on_404=False,
|
||||
):
|
||||
"""
|
||||
Sends a request to the given server.
|
||||
|
@ -473,7 +524,8 @@ class MatrixFederationHttpClient(object):
|
|||
json_data_callback=None,
|
||||
long_retries=False, timeout=None,
|
||||
ignore_backoff=False,
|
||||
backoff_on_404=False):
|
||||
backoff_on_404=False,
|
||||
try_trailing_slash_on_400=False):
|
||||
""" Sends the specifed json data using PUT
|
||||
|
||||
Args:
|
||||
|
@ -493,7 +545,12 @@ class MatrixFederationHttpClient(object):
|
|||
and try the request anyway.
|
||||
backoff_on_404 (bool): True if we should count a 404 response as
|
||||
a failure of the server (and should therefore back off future
|
||||
requests)
|
||||
requests).
|
||||
try_trailing_slash_on_400 (bool): True if on a 400 M_UNRECOGNIZED
|
||||
response we should try appending a trailing slash to the end
|
||||
of the request. Workaround for #3622 in Synapse <= v0.99.3. This
|
||||
will be attempted before backing off if backing off has been
|
||||
enabled.
|
||||
|
||||
Returns:
|
||||
Deferred[dict|list]: Succeeds when we get a 2xx HTTP response. The
|
||||
|
@ -509,7 +566,6 @@ class MatrixFederationHttpClient(object):
|
|||
RequestSendFailed: If there were problems connecting to the
|
||||
remote, due to e.g. DNS failures, connection timeouts etc.
|
||||
"""
|
||||
|
||||
request = MatrixFederationRequest(
|
||||
method="PUT",
|
||||
destination=destination,
|
||||
|
@ -519,17 +575,19 @@ class MatrixFederationHttpClient(object):
|
|||
json=data,
|
||||
)
|
||||
|
||||
response = yield self._send_request(
|
||||
response = yield self._send_request_with_optional_trailing_slash(
|
||||
request,
|
||||
try_trailing_slash_on_400,
|
||||
backoff_on_404=backoff_on_404,
|
||||
ignore_backoff=ignore_backoff,
|
||||
long_retries=long_retries,
|
||||
timeout=timeout,
|
||||
ignore_backoff=ignore_backoff,
|
||||
backoff_on_404=backoff_on_404,
|
||||
)
|
||||
|
||||
body = yield _handle_json_response(
|
||||
self.hs.get_reactor(), self.default_timeout, request, response,
|
||||
)
|
||||
|
||||
defer.returnValue(body)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
|
@ -592,7 +650,8 @@ class MatrixFederationHttpClient(object):
|
|||
|
||||
@defer.inlineCallbacks
|
||||
def get_json(self, destination, path, args=None, retry_on_dns_fail=True,
|
||||
timeout=None, ignore_backoff=False):
|
||||
timeout=None, ignore_backoff=False,
|
||||
try_trailing_slash_on_400=False):
|
||||
""" GETs some json from the given host homeserver and path
|
||||
|
||||
Args:
|
||||
|
@ -606,6 +665,9 @@ class MatrixFederationHttpClient(object):
|
|||
be retried.
|
||||
ignore_backoff (bool): true to ignore the historical backoff data
|
||||
and try the request anyway.
|
||||
try_trailing_slash_on_400 (bool): True if on a 400 M_UNRECOGNIZED
|
||||
response we should try appending a trailing slash to the end of
|
||||
the request. Workaround for #3622 in Synapse <= v0.99.3.
|
||||
Returns:
|
||||
Deferred[dict|list]: Succeeds when we get a 2xx HTTP response. The
|
||||
result will be the decoded JSON body.
|
||||
|
@ -631,16 +693,19 @@ class MatrixFederationHttpClient(object):
|
|||
query=args,
|
||||
)
|
||||
|
||||
response = yield self._send_request(
|
||||
response = yield self._send_request_with_optional_trailing_slash(
|
||||
request,
|
||||
try_trailing_slash_on_400,
|
||||
backoff_on_404=False,
|
||||
ignore_backoff=ignore_backoff,
|
||||
retry_on_dns_fail=retry_on_dns_fail,
|
||||
timeout=timeout,
|
||||
ignore_backoff=ignore_backoff,
|
||||
)
|
||||
|
||||
body = yield _handle_json_response(
|
||||
self.hs.get_reactor(), self.default_timeout, request, response,
|
||||
)
|
||||
|
||||
defer.returnValue(body)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue