fix api error responses

This commit is contained in:
Jack Robison 2017-12-06 13:25:58 -05:00
parent ecdba8dc38
commit 8fdd8d8c43
No known key found for this signature in database
GPG key ID: 284699E7404E3CFF
2 changed files with 18 additions and 15 deletions

View file

@ -17,6 +17,7 @@ at anytime.
* Merged two separate dht test folders into one * Merged two separate dht test folders into one
* Fixed value error due to a race condition when saving to the claim cache (https://github.com/lbryio/lbry/issues/1013) * Fixed value error due to a race condition when saving to the claim cache (https://github.com/lbryio/lbry/issues/1013)
* Fixed being unable to re-download updated content (#951) * Fixed being unable to re-download updated content (#951)
* Fixed sending error messages for failed api requests
### Deprecated ### Deprecated
* `channel_list_mine`, replaced with `channel_list` * `channel_list_mine`, replaced with `channel_list`
@ -28,6 +29,8 @@ at anytime.
* Changed `channel_list` to include channels where the certificate info has been imported but the claim is not in the wallet * Changed `channel_list` to include channels where the certificate info has been imported but the claim is not in the wallet
* Changed `file_list`, `file_delete`, `file_set_status`, and `file_reflect` to no longer return claim related information. * Changed `file_list`, `file_delete`, `file_set_status`, and `file_reflect` to no longer return claim related information.
* Increased assumption for time it takes to announce single hash from 1 second to 5 seconds * Increased assumption for time it takes to announce single hash from 1 second to 5 seconds
* Don't set HTTP error codes for failed api requests, conform to http://www.jsonrpc.org/specification#error_object
* Return less verbose tracebacks for api requests resulting in errors
### Added ### Added
* Added `channel_import` and `channel_export` commands * Added `channel_import` and `channel_export` commands

View file

@ -58,20 +58,24 @@ class JSONRPCError(object):
assert (data is None or isinstance(data, dict)), "'data' must be None or a dict" assert (data is None or isinstance(data, dict)), "'data' must be None or a dict"
self.code = code self.code = code
if message is None: if message is None:
message = self.MESSAGES[code] if code in self.MESSAGES else "Error" message = self.MESSAGES[code] if code in self.MESSAGES else "API Error"
self.message = message self.message = message
self.data = {} if data is None else data self.data = {} if data is None else data
self.traceback = []
if traceback is not None: if traceback is not None:
self.data['traceback'] = traceback.split("\n") trace_lines = traceback.split("\n")
for i, t in enumerate(trace_lines):
if "--- <exception caught here> ---" in t:
if len(trace_lines) > i + 1:
self.traceback = [j for j in trace_lines[i+1:] if j]
break
def to_dict(self): def to_dict(self):
ret = { return {
'code': self.code, 'code': self.code,
'message': self.message, 'message': self.message,
'data': self.traceback
} }
if len(self.data):
ret['data'] = self.data
return ret
@classmethod @classmethod
def create_from_exception(cls, exception, code=CODE_APPLICATION_ERROR, traceback=None): def create_from_exception(cls, exception, code=CODE_APPLICATION_ERROR, traceback=None):
@ -215,18 +219,15 @@ class AuthJSONRPCServer(AuthorizedBase):
error = failure.check(JSONRPCError) error = failure.check(JSONRPCError)
if error is None: if error is None:
# maybe its a twisted Failure with another type of error # maybe its a twisted Failure with another type of error
error = JSONRPCError(failure.getErrorMessage(), traceback=failure.getTraceback()) error = JSONRPCError(failure.getErrorMessage() or failure.type.__name__,
traceback=failure.getTraceback())
else: else:
# last resort, just cast it as a string # last resort, just cast it as a string
error = JSONRPCError(str(failure)) error = JSONRPCError(str(failure))
log.warning("error processing api request: %s", error.message)
response_content = jsonrpc_dumps_pretty(error, id=id_) response_content = jsonrpc_dumps_pretty(error, id=id_)
self._set_headers(request, response_content) self._set_headers(request, response_content)
try: request.setResponseCode(200)
request.setResponseCode(JSONRPCError.HTTP_CODES[error.code])
except KeyError:
request.setResponseCode(JSONRPCError.HTTP_CODES[JSONRPCError.CODE_INTERNAL_ERROR])
self._render_message(request, response_content) self._render_message(request, response_content)
@staticmethod @staticmethod
@ -365,8 +366,7 @@ class AuthJSONRPCServer(AuthorizedBase):
# handle deferredLists that won't peacefully cancel, namely # handle deferredLists that won't peacefully cancel, namely
# get_lbry_files # get_lbry_files
d.addErrback(trap, ConnectionDone, ConnectionLost, defer.CancelledError, RuntimeError) d.addErrback(trap, ConnectionDone, ConnectionLost, defer.CancelledError, RuntimeError)
d.addErrback(log.fail(self._render_error, request, id_), d.addErrback(self._render_error, request, id_)
'Failed to process %s', function_name)
d.addBoth(lambda _: log.debug("%s took %f", d.addBoth(lambda _: log.debug("%s took %f",
function_name, function_name,
(utils.now() - time_in).total_seconds())) (utils.now() - time_in).total_seconds()))