+# -*- coding: utf-8 -*-
+import logging
+from functools import wraps
+
+import bottle
+import yaml
+
+Bad_Request = 400
+Unauthorized = 401
+Not_Found = 404
+Forbidden = 403
+Method_Not_Allowed = 405
+Not_Acceptable = 406
+Request_Timeout = 408
+Conflict = 409
+Service_Unavailable = 503
+Internal_Server_Error = 500
+
+
+class HttpMappedError(Exception):
+ """Base class for a new hierarchy that translate HTTP error codes
+ to python exceptions
+
+ This class accepts an extra argument ``http_code`` (integer
+ representing HTTP error codes).
+ """
+
+ def __init__(self, message, http_code=Internal_Server_Error):
+ Exception.__init__(self, message)
+ self.http_code = http_code
+
+
+class ErrorHandler(object):
+ """Defines a default strategy for handling HttpMappedError.
+
+ This class implements a wrapper (can also be used as decorator), that
+ watches out for different exceptions and log them accordingly.
+
+ Arguments:
+ logger(logging.Logger): logger object to be used to report errors
+ """
+ def __init__(self, logger=None):
+ self.logger = logger or logging.getLogger('openmano.http')
+
+ def __call__(self, function):
+ @wraps(function)
+ def _wraped(*args, **kwargs):
+ try:
+ return function(*args, **kwargs)
+ except bottle.HTTPError:
+ raise
+ except HttpMappedError as ex:
+ self.logger.error(
+ "%s error %s",
+ function.__name__, ex.http_code, exc_info=True)
+ bottle.abort(ex.http_code, str(ex))
+ except yaml.YAMLError as ex:
+ self.logger.error(
+ "YAML error while trying to serialize/unserialize fields",
+ exc_info=True)
+ bottle.abort(Bad_Request, type(ex).__name__ + ": " + str(ex))
+ except Exception as ex:
+ self.logger.error("Unexpected exception: ", exc_info=True)
+ bottle.abort(Internal_Server_Error,
+ type(ex).__name__ + ": " + str(ex))
+
+ return _wraped