forked from MirrorHub/synapse
Refactor code for turning HttpResponseException into SynapseError
This commit replaces SynapseError.from_http_response_exception with HttpResponseException.to_synapse_error. The new method actually returns a ProxiedRequestError, which allows us to pass through additional metadata from the API call.
This commit is contained in:
parent
fa7dc889f1
commit
018d75a148
3 changed files with 56 additions and 34 deletions
|
@ -105,38 +105,28 @@ class SynapseError(CodeMessageException):
|
||||||
self.errcode,
|
self.errcode,
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_http_response_exception(cls, err):
|
|
||||||
"""Make a SynapseError based on an HTTPResponseException
|
|
||||||
|
|
||||||
This is useful when a proxied request has failed, and we need to
|
class ProxiedRequestError(SynapseError):
|
||||||
decide how to map the failure onto a matrix error to send back to the
|
"""An error from a general matrix endpoint, eg. from a proxied Matrix API call.
|
||||||
client.
|
|
||||||
|
|
||||||
An attempt is made to parse the body of the http response as a matrix
|
Attributes:
|
||||||
error. If that succeeds, the errcode and error message from the body
|
errcode (str): Matrix error code e.g 'M_FORBIDDEN'
|
||||||
are used as the errcode and error message in the new synapse error.
|
|
||||||
|
|
||||||
Otherwise, the errcode is set to M_UNKNOWN, and the error message is
|
|
||||||
set to the reason code from the HTTP response.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
err (HttpResponseException):
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
SynapseError:
|
|
||||||
"""
|
"""
|
||||||
# try to parse the body as json, to get better errcode/msg, but
|
def __init__(self, code, msg, errcode=Codes.UNKNOWN, additional_fields=None):
|
||||||
# default to M_UNKNOWN with the HTTP status as the error text
|
super(ProxiedRequestError, self).__init__(
|
||||||
try:
|
code, msg, errcode
|
||||||
j = json.loads(err.response)
|
)
|
||||||
except ValueError:
|
if additional_fields is None:
|
||||||
j = {}
|
self._additional_fields = {}
|
||||||
errcode = j.get('errcode', Codes.UNKNOWN)
|
else:
|
||||||
errmsg = j.get('error', err.msg)
|
self._additional_fields = dict(additional_fields)
|
||||||
|
|
||||||
res = SynapseError(err.code, errmsg, errcode)
|
def error_dict(self):
|
||||||
return res
|
return cs_error(
|
||||||
|
self.msg,
|
||||||
|
self.errcode,
|
||||||
|
**self._additional_fields
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ConsentNotGivenError(SynapseError):
|
class ConsentNotGivenError(SynapseError):
|
||||||
|
@ -361,7 +351,7 @@ class HttpResponseException(CodeMessageException):
|
||||||
Represents an HTTP-level failure of an outbound request
|
Represents an HTTP-level failure of an outbound request
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
response (str): body of response
|
response (bytes): body of response
|
||||||
"""
|
"""
|
||||||
def __init__(self, code, msg, response):
|
def __init__(self, code, msg, response):
|
||||||
"""
|
"""
|
||||||
|
@ -369,7 +359,39 @@ class HttpResponseException(CodeMessageException):
|
||||||
Args:
|
Args:
|
||||||
code (int): HTTP status code
|
code (int): HTTP status code
|
||||||
msg (str): reason phrase from HTTP response status line
|
msg (str): reason phrase from HTTP response status line
|
||||||
response (str): body of response
|
response (bytes): body of response
|
||||||
"""
|
"""
|
||||||
super(HttpResponseException, self).__init__(code, msg)
|
super(HttpResponseException, self).__init__(code, msg)
|
||||||
self.response = response
|
self.response = response
|
||||||
|
|
||||||
|
def to_synapse_error(self):
|
||||||
|
"""Make a SynapseError based on an HTTPResponseException
|
||||||
|
|
||||||
|
This is useful when a proxied request has failed, and we need to
|
||||||
|
decide how to map the failure onto a matrix error to send back to the
|
||||||
|
client.
|
||||||
|
|
||||||
|
An attempt is made to parse the body of the http response as a matrix
|
||||||
|
error. If that succeeds, the errcode and error message from the body
|
||||||
|
are used as the errcode and error message in the new synapse error.
|
||||||
|
|
||||||
|
Otherwise, the errcode is set to M_UNKNOWN, and the error message is
|
||||||
|
set to the reason code from the HTTP response.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
SynapseError:
|
||||||
|
"""
|
||||||
|
# try to parse the body as json, to get better errcode/msg, but
|
||||||
|
# default to M_UNKNOWN with the HTTP status as the error text
|
||||||
|
try:
|
||||||
|
j = json.loads(self.response)
|
||||||
|
except ValueError:
|
||||||
|
j = {}
|
||||||
|
|
||||||
|
if not isinstance(j, dict):
|
||||||
|
j = {}
|
||||||
|
|
||||||
|
errcode = j.pop('errcode', Codes.UNKNOWN)
|
||||||
|
errmsg = j.pop('error', self.msg)
|
||||||
|
|
||||||
|
return ProxiedRequestError(self.code, errmsg, errcode, j)
|
||||||
|
|
|
@ -506,7 +506,7 @@ class FederationClient(FederationBase):
|
||||||
)
|
)
|
||||||
except HttpResponseException as e:
|
except HttpResponseException as e:
|
||||||
if not 500 <= e.code < 600:
|
if not 500 <= e.code < 600:
|
||||||
raise SynapseError.from_http_response_exception(e)
|
raise e.to_synapse_error()
|
||||||
else:
|
else:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"Failed to %s via %s: %i %s",
|
"Failed to %s via %s: %i %s",
|
||||||
|
@ -682,7 +682,7 @@ class FederationClient(FederationBase):
|
||||||
)
|
)
|
||||||
except HttpResponseException as e:
|
except HttpResponseException as e:
|
||||||
if e.code == 403:
|
if e.code == 403:
|
||||||
raise SynapseError.from_http_response_exception(e)
|
raise e.to_synapse_error()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
pdu_dict = content["event"]
|
pdu_dict = content["event"]
|
||||||
|
|
|
@ -379,7 +379,7 @@ class MediaRepository(object):
|
||||||
logger.warn("HTTP error fetching remote media %s/%s: %s",
|
logger.warn("HTTP error fetching remote media %s/%s: %s",
|
||||||
server_name, media_id, e.response)
|
server_name, media_id, e.response)
|
||||||
if e.code == twisted.web.http.NOT_FOUND:
|
if e.code == twisted.web.http.NOT_FOUND:
|
||||||
raise SynapseError.from_http_response_exception(e)
|
raise e.to_synapse_error()
|
||||||
raise SynapseError(502, "Failed to fetch remote media")
|
raise SynapseError(502, "Failed to fetch remote media")
|
||||||
|
|
||||||
except SynapseError:
|
except SynapseError:
|
||||||
|
|
Loading…
Reference in a new issue