Use CodeMessageException subclass instead

Parse json errors from get_json client methods and throw special
errors.
This commit is contained in:
David Baker 2017-04-25 19:30:55 +01:00
parent a46982cee9
commit 1a9255c12e
4 changed files with 51 additions and 61 deletions

View File

@ -66,6 +66,17 @@ class CodeMessageException(RuntimeError):
return cs_error(self.msg) 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): class SynapseError(CodeMessageException):
"""A base exception type for matrix errors which have an errcode and error """A base exception type for matrix errors which have an errcode and error
message (as well as an HTTP status code). message (as well as an HTTP status code).

View File

@ -18,7 +18,7 @@
from twisted.internet import defer from twisted.internet import defer
from synapse.api.errors import ( from synapse.api.errors import (
CodeMessageException MatrixCodeMessageException, CodeMessageException
) )
from ._base import BaseHandler from ._base import BaseHandler
from synapse.util.async import run_on_reactor from synapse.util.async import run_on_reactor
@ -35,7 +35,7 @@ class IdentityHandler(BaseHandler):
def __init__(self, hs): def __init__(self, hs):
super(IdentityHandler, self).__init__(hs) super(IdentityHandler, self).__init__(hs)
self.proxy_client = hs.get_matrix_proxy_client() self.http_client = hs.get_simple_http_client()
self.trusted_id_servers = set(hs.config.trusted_third_party_id_servers) self.trusted_id_servers = set(hs.config.trusted_third_party_id_servers)
self.trust_any_id_server_just_for_testing_do_not_use = ( self.trust_any_id_server_just_for_testing_do_not_use = (
@ -83,13 +83,16 @@ class IdentityHandler(BaseHandler):
data = {} data = {}
try: try:
data = yield self.proxy_client.get_json( data = yield self.http_client.get_json(
"https://%s%s" % ( "http://%s%s" % (
id_server, id_server,
"/_matrix/identity/api/v1/3pid/getValidated3pid" "/_matrix/identity/api/v1/3pid/getValidated3pid"
), ),
{'sid': creds['sid'], 'client_secret': client_secret} {'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: except CodeMessageException as e:
data = json.loads(e.msg) data = json.loads(e.msg)
@ -118,8 +121,8 @@ class IdentityHandler(BaseHandler):
raise SynapseError(400, "No client_secret in creds") raise SynapseError(400, "No client_secret in creds")
try: try:
data = yield self.proxy_client.post_urlencoded_get_json( data = yield self.http_client.post_urlencoded_get_json(
"https://%s%s" % ( "http://%s%s" % (
id_server, "/_matrix/identity/api/v1/3pid/bind" id_server, "/_matrix/identity/api/v1/3pid/bind"
), ),
{ {
@ -151,14 +154,17 @@ class IdentityHandler(BaseHandler):
params.update(kwargs) params.update(kwargs)
try: try:
data = yield self.proxy_client.post_json_get_json( data = yield self.http_client.post_json_get_json(
"https://%s%s" % ( "http://%s%s" % (
id_server, id_server,
"/_matrix/identity/api/v1/validate/email/requestToken" "/_matrix/identity/api/v1/validate/email/requestToken"
), ),
params params
) )
defer.returnValue(data) 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: except CodeMessageException as e:
logger.info("Proxied requestToken failed: %r", e) logger.info("Proxied requestToken failed: %r", e)
raise e raise e
@ -185,14 +191,17 @@ class IdentityHandler(BaseHandler):
params.update(kwargs) params.update(kwargs)
try: try:
data = yield self.proxy_client.post_json_get_json( data = yield self.http_client.post_json_get_json(
"https://%s%s" % ( "http://%s%s" % (
id_server, id_server,
"/_matrix/identity/api/v1/validate/msisdn/requestToken" "/_matrix/identity/api/v1/validate/msisdn/requestToken"
), ),
params params
) )
defer.returnValue(data) 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: except CodeMessageException as e:
logger.info("Proxied requestToken failed: %r", e) logger.info("Proxied requestToken failed: %r", e)
raise e raise e

View File

@ -16,7 +16,7 @@ from OpenSSL import SSL
from OpenSSL.SSL import VERIFY_NONE from OpenSSL.SSL import VERIFY_NONE
from synapse.api.errors import ( from synapse.api.errors import (
CodeMessageException, SynapseError, Codes, CodeMessageException, MatrixCodeMessageException, SynapseError, Codes,
) )
from synapse.util.logcontext import preserve_context_over_fn from synapse.util.logcontext import preserve_context_over_fn
import synapse.metrics import synapse.metrics
@ -145,8 +145,10 @@ class SimpleHttpClient(object):
body = yield preserve_context_over_fn(readBody, response) body = yield preserve_context_over_fn(readBody, response)
if response.code / 100 >= 4: if 200 <= response.code < 300:
raise CodeMessageException(response.code, body) defer.returnValue(json.loads(body))
else:
raise self._exceptionFromFailedRequest(response, body)
defer.returnValue(json.loads(body)) defer.returnValue(json.loads(body))
@ -168,7 +170,11 @@ class SimpleHttpClient(object):
error message. error message.
""" """
body = yield self.get_raw(uri, args) body = yield self.get_raw(uri, args)
if 200 <= response.code < 300:
defer.returnValue(json.loads(body)) defer.returnValue(json.loads(body))
else:
raise self._exceptionFromFailedRequest(response, body)
@defer.inlineCallbacks @defer.inlineCallbacks
def put_json(self, uri, json_body, args={}): def put_json(self, uri, json_body, args={}):
@ -249,6 +255,16 @@ class SimpleHttpClient(object):
else: else:
raise CodeMessageException(response.code, body) 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 e:
print e
return CodeMessageException(response.code, body)
# XXX: FIXME: This is horribly copy-pasted from matrixfederationclient. # XXX: FIXME: This is horribly copy-pasted from matrixfederationclient.
# The two should be factored out. # The two should be factored out.
@ -309,46 +325,6 @@ class SimpleHttpClient(object):
defer.returnValue((length, headers, response.request.absoluteURI, response.code)) defer.returnValue((length, headers, response.request.absoluteURI, response.code))
class MatrixProxyClient(object):
"""
An HTTP client that proxies other Matrix endpoints, ie. if the remote endpoint
returns Matrix-style error response, this will raise the appropriate SynapseError
"""
def __init__(self, hs):
self.simpleHttpClient = SimpleHttpClient(hs)
@defer.inlineCallbacks
def post_json_get_json(self, uri, post_json):
try:
result = yield self.simpleHttpClient.post_json_get_json(uri, post_json)
defer.returnValue(result)
except CodeMessageException as cme:
ex = self._tryGetMatrixError(cme)
if ex is not None:
raise ex
raise cme
@defer.inlineCallbacks
def get_json(self, uri, args={}):
try:
result = yield self.simpleHttpClient.get_json(uri, args)
defer.returnValue(result)
except CodeMessageException as cme:
ex = self._tryGetMatrixError(cme)
if ex is not None:
raise ex
raise cme
def _tryGetMatrixError(self, codeMessageException):
try:
errbody = json.loads(codeMessageException.msg)
errcode = errbody['errcode']
errtext = errbody['error']
return SynapseError(codeMessageException.code, errtext, errcode)
except:
return None
# XXX: FIXME: This is horribly copy-pasted from matrixfederationclient. # XXX: FIXME: This is horribly copy-pasted from matrixfederationclient.
# The two should be factored out. # The two should be factored out.

View File

@ -49,9 +49,7 @@ from synapse.handlers.events import EventHandler, EventStreamHandler
from synapse.handlers.initial_sync import InitialSyncHandler from synapse.handlers.initial_sync import InitialSyncHandler
from synapse.handlers.receipts import ReceiptsHandler from synapse.handlers.receipts import ReceiptsHandler
from synapse.handlers.read_marker import ReadMarkerHandler from synapse.handlers.read_marker import ReadMarkerHandler
from synapse.http.client import ( from synapse.http.client import SimpleHttpClient, InsecureInterceptableContextFactory
SimpleHttpClient, InsecureInterceptableContextFactory, MatrixProxyClient
)
from synapse.http.matrixfederationclient import MatrixFederationHttpClient from synapse.http.matrixfederationclient import MatrixFederationHttpClient
from synapse.notifier import Notifier from synapse.notifier import Notifier
from synapse.push.pusherpool import PusherPool from synapse.push.pusherpool import PusherPool
@ -130,7 +128,6 @@ class HomeServer(object):
'filtering', 'filtering',
'http_client_context_factory', 'http_client_context_factory',
'simple_http_client', 'simple_http_client',
'matrix_proxy_client',
'media_repository', 'media_repository',
'federation_transport_client', 'federation_transport_client',
'federation_sender', 'federation_sender',
@ -193,9 +190,6 @@ class HomeServer(object):
def build_simple_http_client(self): def build_simple_http_client(self):
return SimpleHttpClient(self) return SimpleHttpClient(self)
def build_matrix_proxy_client(self):
return MatrixProxyClient(self)
def build_v1auth(self): def build_v1auth(self):
orf = Auth(self) orf = Auth(self)
# Matrix spec makes no reference to what HTTP status code is returned, # Matrix spec makes no reference to what HTTP status code is returned,