From 709d74b458a8bef43134c3c526cbeb77fd7e0ac0 Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Thu, 26 Mar 2015 20:00:16 +0200 Subject: [PATCH] prettier http errors; curl http client is now used instead of the simple default one --- motioneye.py | 9 ++++++++ src/handlers.py | 2 +- src/motionctl.py | 2 +- src/remote.py | 60 ++++++++++++++++++++++++------------------------ src/utils.py | 25 ++++++++++++++++++-- 5 files changed, 64 insertions(+), 34 deletions(-) diff --git a/motioneye.py b/motioneye.py index 14144e6..9ddf27f 100755 --- a/motioneye.py +++ b/motioneye.py @@ -25,6 +25,8 @@ import re import signal import sys +from tornado.httpclient import AsyncHTTPClient + import settings sys.path.append(os.path.join(getattr(settings, 'PROJECT_PATH', os.path.dirname(sys.argv[0])), 'src')) @@ -238,6 +240,12 @@ def _configure_signals(): def _configure_logging(): logging.basicConfig(filename=None, level=settings.LOG_LEVEL, format='%(asctime)s: %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S') + + logging.getLogger('tornado').setLevel(logging.WARN) + + +def _configure_tornado(): + AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient") def _print_help(): @@ -355,6 +363,7 @@ if __name__ == '__main__': _configure_signals() _configure_logging() + _configure_tornado() if settings.SMB_SHARES: stop, start = smbctl.update_mounts() diff --git a/src/handlers.py b/src/handlers.py index 5fa23b1..3d7ee0d 100644 --- a/src/handlers.py +++ b/src/handlers.py @@ -489,7 +489,7 @@ class ConfigHandler(BaseHandler): else: cameras = [c for c in cameras if c.get('enabled')] self.finish_json({'cameras': cameras}) - + remote.list_cameras(self.get_data(), on_response) elif type == 'netcam': diff --git a/src/motionctl.py b/src/motionctl.py index 93eb44a..b656dc0 100644 --- a/src/motionctl.py +++ b/src/motionctl.py @@ -253,7 +253,7 @@ def set_motion_detection(camera_id, enabled): logging.error('failed to %(what)s motion detection for camera with id %(id)s: %(msg)s' % { 'what': ['disable', 'enable'][enabled], 'id': camera_id, - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) else: logging.debug('successfully %(what)s motion detection for camera with id %(id)s' % { diff --git a/src/remote.py b/src/remote.py index 5c0aa63..92b91f6 100644 --- a/src/remote.py +++ b/src/remote.py @@ -109,9 +109,9 @@ def list_cameras(local_config, callback): if response.error: logging.error('failed to list remote cameras on %(url)s: %(msg)s' % { 'url': make_camera_url(local_config, camera=False), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) try: response = json.loads(response.body) @@ -148,9 +148,9 @@ def get_config(local_config, callback): logging.error('failed to get config for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) try: response = json.loads(response.body) @@ -201,9 +201,9 @@ def set_config(local_config, ui_config, callback): logging.error('failed to set config for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) callback() @@ -232,9 +232,9 @@ def set_preview(local_config, controls, callback): logging.error('failed to set preview for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) callback() @@ -278,9 +278,9 @@ def get_current_picture(local_config, width, height, callback): logging.error('failed to get current picture for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) callback(motion_detected, response.body) @@ -313,9 +313,9 @@ def list_media(local_config, media_type, prefix, callback): logging.error('failed to get media list for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) try: response = json.loads(response.body) @@ -360,9 +360,9 @@ def get_media_content(local_config, filename, media_type, callback): 'filename': filename, 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) return callback(response.body) @@ -397,9 +397,9 @@ def make_zipped_content(local_config, media_type, group, callback): 'group': group, 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) try: key = json.loads(response.body)['key'] @@ -441,9 +441,9 @@ def get_zipped_content(local_config, media_type, key, group, callback): logging.error('failed to download zip file for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) callback({ 'data': response.body, @@ -486,9 +486,9 @@ def make_timelapse_movie(local_config, framerate, interval, group, callback): 'url': make_camera_url(local_config), 'int': interval, 'framerate': framerate, - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) try: response = json.loads(response.body) @@ -527,9 +527,9 @@ def check_timelapse_movie(local_config, group, callback): logging.error('failed to check timelapse movie status for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) try: response = json.loads(response.body) @@ -570,9 +570,9 @@ def get_timelapse_movie(local_config, key, group, callback): logging.error('failed to download timelapse movie for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) callback({ 'data': response.body, @@ -618,9 +618,9 @@ def get_media_preview(local_config, filename, media_type, width, height, callbac 'filename': filename, 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) callback(response.body) @@ -654,9 +654,9 @@ def del_media_content(local_config, filename, media_type, callback): 'filename': filename, 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) callback() @@ -690,9 +690,9 @@ def del_media_group(local_config, group, media_type, callback): 'group': group, 'id': camera_id, 'url': make_camera_url(local_config), - 'msg': unicode(response.error)}) + 'msg': utils.pretty_http_error(response.error)}) - return callback(error=unicode(response.error)) + return callback(error=utils.pretty_http_error(response.error)) callback() diff --git a/src/utils.py b/src/utils.py index db32598..9e5bcfe 100644 --- a/src/utils.py +++ b/src/utils.py @@ -19,6 +19,7 @@ import datetime import hashlib import logging import os +import re import time import urllib import urlparse @@ -206,7 +207,18 @@ def pretty_size(size): size, unit = size / 1024.0 / 1024 / 1024, 'GB' return '%.1f %s' % (size, unit) - + + +def pretty_http_error(http_error): + msg = unicode(http_error) + if msg.startswith('HTTP '): + msg = msg.split(':', 1)[-1].strip() + + if msg.startswith('[Errno '): + msg = msg.split(']', 1)[-1].strip() + + return msg + def get_disk_usage(path): logging.debug('getting disk usage for path %(path)s...' % { @@ -267,8 +279,12 @@ def test_netcam_url(data, callback): http_client = AsyncHTTPClient() called = [False] + not_2xx = [False] def on_header(header): + if not_2xx[0]: + return # ignore headers unless the status is 2xx + header = header.lower() if header.startswith('content-type'): content_type = header.split(':')[1].strip() @@ -283,10 +299,15 @@ def test_netcam_url(data, callback): called[0] = True + else: + m = re.match('^http/1.\d (\d+) ', header) + if m and int(m.group(1)) / 100 != 2: + not_2xx[0] = True + def on_response(response): if not called[0]: called[0] = True - callback(error=unicode(response.error) if response.error else 'not a network camera') + callback(error=pretty_http_error(response.error) if response.error else 'not a network camera') username = data['username'] or None password = data['password'] or None -- 2.39.5