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

Propagate errors sensibly from proxied IS requests #2147

Merged
merged 12 commits into from
May 3, 2017
11 changes: 11 additions & 0 deletions synapse/api/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ def error_dict(self):
return cs_error(self.msg)


class MatrixCodeMessageException(CodeMessageException):
"""An error from a general matrix endpoint, eg. from a proxied Matrix API call.
Attributes:
errcode (str): Matrix error code e.g 'M_FORBIDDEN'
"""
def __init__(self, code, msg, errcode=Codes.UNKNOWN):
super(MatrixCodeMessageException, self).__init__(code, msg)
self.errcode = errcode


class SynapseError(CodeMessageException):
"""A base exception type for matrix errors which have an errcode and error
message (as well as an HTTP status code).
Expand Down
11 changes: 10 additions & 1 deletion synapse/handlers/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from twisted.internet import defer

from synapse.api.errors import (
CodeMessageException
MatrixCodeMessageException, CodeMessageException
)
from ._base import BaseHandler
from synapse.util.async import run_on_reactor
Expand Down Expand Up @@ -90,6 +90,9 @@ def threepid_from_creds(self, creds):
),
{'sid': creds['sid'], 'client_secret': client_secret}
)
except MatrixCodeMessageException as e:
logger.info("getValidated3pid failed with Matrix error: %r", e)
raise SynapseError(e.code, e.msg, e.errcode)
except CodeMessageException as e:
data = json.loads(e.msg)

Expand Down Expand Up @@ -159,6 +162,9 @@ def requestEmailToken(self, id_server, email, client_secret, send_attempt, **kwa
params
)
defer.returnValue(data)
except MatrixCodeMessageException as e:
logger.info("Proxied requestToken failed with Matrix error: %r", e)
raise SynapseError(e.code, e.msg, e.errcode)
except CodeMessageException as e:
logger.info("Proxied requestToken failed: %r", e)
raise e
Expand Down Expand Up @@ -193,6 +199,9 @@ def requestMsisdnToken(
params
)
defer.returnValue(data)
except MatrixCodeMessageException as e:
logger.info("Proxied requestToken failed with Matrix error: %r", e)
raise SynapseError(e.code, e.msg, e.errcode)
except CodeMessageException as e:
logger.info("Proxied requestToken failed: %r", e)
raise e
23 changes: 20 additions & 3 deletions synapse/http/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from OpenSSL.SSL import VERIFY_NONE

from synapse.api.errors import (
CodeMessageException, SynapseError, Codes,
CodeMessageException, MatrixCodeMessageException, SynapseError, Codes,
)
from synapse.util.logcontext import preserve_context_over_fn
import synapse.metrics
Expand Down Expand Up @@ -145,6 +145,11 @@ def post_json_get_json(self, uri, post_json):

body = yield preserve_context_over_fn(readBody, response)

if 200 <= response.code < 300:
defer.returnValue(json.loads(body))
else:
raise self._exceptionFromFailedRequest(response, body)

defer.returnValue(json.loads(body))

@defer.inlineCallbacks
Expand All @@ -164,8 +169,11 @@ def get_json(self, uri, args={}):
On a non-2xx HTTP response. The response body will be used as the
error message.
"""
body = yield self.get_raw(uri, args)
defer.returnValue(json.loads(body))
try:
body = yield self.get_raw(uri, args)
defer.returnValue(json.loads(body))
except CodeMessageException as e:
raise self._exceptionFromFailedRequest(e.code, e.msg)

@defer.inlineCallbacks
def put_json(self, uri, json_body, args={}):
Expand Down Expand Up @@ -246,6 +254,15 @@ def get_raw(self, uri, args={}):
else:
raise CodeMessageException(response.code, body)

def _exceptionFromFailedRequest(self, response, body):
try:
jsonBody = json.loads(body)
errcode = jsonBody['errcode']
error = jsonBody['error']
return MatrixCodeMessageException(response.code, error, errcode)
except:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally we prefer to list the types of exceptions, as otherwise its too easy to catch a typo or something. Its probably fine for me.

return CodeMessageException(response.code, body)

# XXX: FIXME: This is horribly copy-pasted from matrixfederationclient.
# The two should be factored out.

Expand Down