From d7b185208d25378ec9735ca30d9d3cf02a0f9f7f Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Fri, 20 Oct 2017 21:49:41 +1300 Subject: [PATCH] Handlers to construct response objects --- mopidy_iris/core.py | 114 ++++++++++++++++++---------------------- mopidy_iris/handlers.py | 106 +++++++++++++++++++++---------------- 2 files changed, 112 insertions(+), 108 deletions(-) diff --git a/mopidy_iris/core.py b/mopidy_iris/core.py index 345fa67f..fce2b2a8 100755 --- a/mopidy_iris/core.py +++ b/mopidy_iris/core.py @@ -105,11 +105,10 @@ class IrisCore(object): connection['connection'].write_message( json_encode(data) ) response = { - 'status': 1, 'message': 'Broadcast to '+str(len(self.connections))+' connections' } if (callback): - callback(response) + callback(response, False) else: return response @@ -129,11 +128,10 @@ class IrisCore(object): connections.append(connection['client']) response = { - 'status': 1, 'connections': connections } if (callback): - callback(response) + callback(response, False) else: return response @@ -193,12 +191,11 @@ class IrisCore(object): } ) response = { - 'status': 1, 'connection_id': connection_id, 'username': data['username'] } if (callback): - callback(response) + callback(response, False) else: return response @@ -206,14 +203,14 @@ class IrisCore(object): error = 'Connection "'+data['connection_id']+'" not found' self.raven_client.captureMessage(error) logger.error(error) - response = { - 'status': 0, + + error = { 'message': error } if (callback): - callback(response) + callback(False, error) else: - return response + return error def deliver_message(self, *args, **kwargs): callback = kwargs.get('callback', False) @@ -222,11 +219,10 @@ class IrisCore(object): if data['connection_id'] in self.connections: self.send_message(connection_id=data['connection_id'], data=data['message']) response = { - 'status': 1, 'message': 'Sent message to '+data['connection_id'] } if (callback): - callback(response) + callback(response, False) else: return response @@ -234,14 +230,14 @@ class IrisCore(object): error = 'Connection "'+data['connection_id']+'" not found' self.raven_client.captureMessage(error) logger.error(error) - response = { - 'status': 0, + + error = { 'message': error } if (callback): - callback(response) + callback(False, error) else: - return response + return error @@ -272,7 +268,7 @@ class IrisCore(object): } if (callback): - callback(response) + callback(response, False) else: return response @@ -296,7 +292,6 @@ class IrisCore(object): upgrade_available = False response = { - 'status': 1, 'version': { 'current': self.version, 'latest': latest_version, @@ -305,7 +300,7 @@ class IrisCore(object): } } if (callback): - callback(response) + callback(response, False) else: return response @@ -315,24 +310,22 @@ class IrisCore(object): try: subprocess.check_call(["pip", "install", "--upgrade", "Mopidy-Iris"]) response = { - 'status': 1, 'message': "Upgrade started" } if (callback): - callback(response) + callback(response, False) else: return response except subprocess.CalledProcessError as e: self.raven_client.captureException(e) - response = { - 'status': 0, + error = { 'message': "Could not start upgrade" } if (callback): - callback(response) + callback(False, error) else: - return response + return error def restart(self, *args, **kwargs): os.execl(sys.executable, *([sys.executable]+sys.argv)) @@ -350,11 +343,10 @@ class IrisCore(object): callback = kwargs.get('callback', False) response = { - 'status': 1, 'radio': self.radio } if (callback): - callback(response) + callback(response, False) else: return response @@ -405,20 +397,19 @@ class IrisCore(object): } ) - return self.get_radio(callback=callback) + self.get_radio(callback=callback) + return # failed fetching/adding tracks, so no-go self.radio['enabled'] = 0; - response = { - 'status': 0, + error = { 'message': 'Could not start radio', 'radio': self.radio } - if (callback): - callback(response) + callback(False, error) else: - return response + return error def stop_radio(self, *args, **kwargs): @@ -444,11 +435,10 @@ class IrisCore(object): ) response = { - 'status': 1, 'message': 'Stopped radio' } if (callback): - callback(response) + callback(response, False) else: return response @@ -525,11 +515,10 @@ class IrisCore(object): callback = kwargs.get('callback', False) response = { - 'status': 1, 'queue_metadata': self.queue_metadata } if (callback): - callback(response) + callback(response, False) else: return response @@ -553,11 +542,10 @@ class IrisCore(object): ) response = { - 'status': 1, 'message': 'Added queue metadata' } if (callback): - callback(response) + callback(response, False) else: return response @@ -581,11 +569,10 @@ class IrisCore(object): ) response = { - 'status': 1, 'message': 'Cleaned queue metadata' } if (callback): - callback(response) + callback(response, False) else: return response @@ -605,7 +592,7 @@ class IrisCore(object): } if (callback): - callback(response) + callback(response, False) else: return response @@ -635,28 +622,24 @@ class IrisCore(object): token = json.loads(response.body) self.spotify_token = token + response = { + 'spotify_token': token + } if (callback): - callback({ - 'status': 1, - 'spotify_token': token - }) + callback(response, False) else: - return token + return response except urllib2.HTTPError as e: self.raven_client.captureException() error = json.loads(e.read()) - response = { - 'status': 0, - 'message': 'Could not refresh token: '+error['error_description'], - 'source': 'refresh_spotify_token' - } + error = {'message': 'Could not refresh token: '+error['error_description']} if (callback): - callback(response) + callback(False, error) else: - return response + return error ## @@ -675,22 +658,21 @@ class IrisCore(object): data = kwargs.get('data', {}) except: self.raven_client.captureException() - callback({ - 'status': 0, + callback(False, { 'message': 'Malformed data', 'source': 'proxy_request' }) - + return # Our request includes data, so make sure we POST the data if 'url' not in data: self.raven_client.captureException() - callback({ - 'status': 0, + callback(False, { 'message': 'Malformed data (missing URL)', 'source': 'proxy_request', 'original_request': data }) + return # Construct request headers # If we have an original request, pass through it's headers @@ -741,8 +723,12 @@ class IrisCore(object): ## def test(self, *args, **kwargs): callback = kwargs.get('callback', None) - time.sleep(1) - callback({ - 'status': 1, - 'message': "Slept for one second" - }) + data = kwargs.get('data', {}) + + if data and 'force_error' in data: + callback(False, {'message': "Could not sleep, forced error"}) + return + else: + time.sleep(1) + callback({'message': "Slept for one second"}, False) + return diff --git a/mopidy_iris/handlers.py b/mopidy_iris/handlers.py index 248dccba..2ad2d1db 100755 --- a/mopidy_iris/handlers.py +++ b/mopidy_iris/handlers.py @@ -85,22 +85,14 @@ class WebsocketHandler(tornado.websocket.WebSocketHandler): # make sure the method exists if hasattr(mem.iris, message['method']): - getattr(mem.iris, message['method'])(data=data, callback=lambda response: self.handle_response(response=response, request_id=request_id)) + getattr(mem.iris, message['method'])(data=data, callback=lambda response, error: self.handle_response(response=response, error=error, request_id=request_id)) else: - mem.iris.raven_client.captureMessage("Method "+message['method']+" does not exist") - self.handle_response({ - 'status': 0, - 'message': 'Method "'+message['method']+'" does not exist', - 'request_id': request_id - }) + self.handle_response(error={'message': 'Method "'+message['method']+'" does not exist'}) + return else: - mem.iris.raven_client.captureMessage("Method key missing from request") - self.handle_response({ - 'status': 0, - 'message': 'Method key missing from request', - 'request_id': request_id - }) + self.handle_response(error={'message': 'Method key missing from request'}) + return def on_close(self): @@ -112,12 +104,23 @@ class WebsocketHandler(tornado.websocket.WebSocketHandler): ## def handle_response(self, *args, **kwargs): response = kwargs.get('response', None) + error = kwargs.get('error', None) request_id = kwargs.get('request_id', False) + # We've been given an error + if error: + data = error + data['status'] = 0 + data['request_id'] = request_id + + # Log error with Sentry + mem.iris.raven_client.captureMessage(error.message) + # We've been handed an AsyncHTTPClient callback. This is the case # when our request calls subsequent external requests (eg Spotify, Genius) - if isinstance(response, tornado.httpclient.HTTPResponse): - response = { + elif isinstance(response, tornado.httpclient.HTTPResponse): + data = { + 'status': 1, 'response_code': response.code, 'response_reason': response.reason, 'response': response.body, @@ -126,10 +129,12 @@ class WebsocketHandler(tornado.websocket.WebSocketHandler): # Just a regular json object, so not an external request else: - response['request_id'] = request_id - mem.iris.send_message(connection_id=self.connection_id, data=response) + data = response + data['status'] = 1 + data['request_id'] = request_id - mem.iris.send_message(connection_id=self.connection_id, data=response) + # Respond to the original request + mem.iris.send_message(connection_id=self.connection_id, data=data) @@ -157,15 +162,11 @@ class HttpHandler(tornado.web.RequestHandler): # make sure the method exists if hasattr(mem.iris, slug): - getattr(mem.iris, slug)(request=self.request, callback=self.handle_response) + getattr(mem.iris, slug)(request=self.request, callback=lambda response, error: self.handle_response(response=response, error=error)) else: - mem.iris.raven_client.captureMessage("Method "+slug+" does not exist") - self.write({ - 'status': 0, - 'message': 'Method "'+slug+'" does not exist' - }) - self.finish() + self.handle_response(error={'message': "Method "+slug+" does not exist"}) + return @tornado.web.asynchronous def post(self, slug=None): @@ -174,48 +175,65 @@ class HttpHandler(tornado.web.RequestHandler): if hasattr(mem.iris, slug): try: data = json.loads(self.request.body.decode('utf-8')) - getattr(mem.iris, slug)(data=data, request=self.request, callback=self.handle_response) + getattr(mem.iris, slug)(data=data, request=self.request, callback=lambda response, error: self.handle_response(response=response, error=error)) except urllib2.HTTPError as e: - self.write({ - 'status': 0, - 'message': 'Invalid JSON payload' - }) - self.finish() + self.handle_response(error={'message': "Invalid JSON payload"}) + return else: - mem.iris.raven_client.captureMessage("Method "+slug+" does not exist") - self.write({ - 'status': 0, - 'message': 'Method "'+slug+'" does not exist' - }) - self.finish() + self.handle_response(error={'message': "Method "+slug+" does not exist"}) + return ## # Handle a response from our core # This is just our callback from an Async request ## - def handle_response(self, response): + def handle_response(self, *args, **kwargs): + response = kwargs.get('response', None) + error = kwargs.get('error', None) + data = {} + + print response + print error + print "------------" + + if error: + data = error + data['status'] = 0 + + # Log error with Sentry + mem.iris.raven_client.captureMessage(data.message) + # We've been handed an AsyncHTTPClient callback. This is the case # when our request calls subsequent external requests (eg Spotify, Genius). # We don't need to wrap non-HTTPResponse responses as these are dicts - if isinstance(response, tornado.httpclient.HTTPResponse): + elif isinstance(response, tornado.httpclient.HTTPResponse): - # Digest JSON resposes into JSON + # Digest JSON responses into JSON content_type = response.headers.get('Content-Type') if content_type.startswith('application/json') or content_type.startswith('text/json'): body = json.loads(response.body) + + # Non-JSON so just copy as-is else: body = response.body - response = { - 'response_code': response.code, - 'response_message': response.reason, + data = { + 'status': response.code, + 'message': response.reason, 'response': body } - self.write(response) + # Regular ol successful response + else: + data = response + data['status'] = 1 + + + # Write our response + self.write(data) self.finish()