Merge pull request #2147 from matrix-org/dbkr/http_request_propagate_error
Propagate errors sensibly from proxied IS requestspull/2185/head
						commit
						60833c8978
					
				|  | @ -66,6 +66,17 @@ class CodeMessageException(RuntimeError): | |||
|         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). | ||||
|  |  | |||
|  | @ -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 | ||||
|  | @ -90,6 +90,9 @@ class IdentityHandler(BaseHandler): | |||
|                 ), | ||||
|                 {'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) | ||||
| 
 | ||||
|  | @ -159,6 +162,9 @@ class IdentityHandler(BaseHandler): | |||
|                 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 | ||||
|  | @ -193,6 +199,9 @@ class IdentityHandler(BaseHandler): | |||
|                 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 | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ from OpenSSL import SSL | |||
| 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 | ||||
|  | @ -145,6 +145,11 @@ class SimpleHttpClient(object): | |||
| 
 | ||||
|         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 | ||||
|  | @ -164,8 +169,11 @@ class SimpleHttpClient(object): | |||
|             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={}): | ||||
|  | @ -246,6 +254,15 @@ class SimpleHttpClient(object): | |||
|         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 (ValueError, KeyError): | ||||
|             return CodeMessageException(response.code, body) | ||||
| 
 | ||||
|     # XXX: FIXME: This is horribly copy-pasted from matrixfederationclient. | ||||
|     # The two should be factored out. | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 David Baker
						David Baker