1import traceback
2
3from bottle import HTTPResponse
4
5from conans.errors import ConanException
6from conans.util.log import logger
7
8
9class ReturnHandlerPlugin(object):
10    """ The ReturnHandlerPlugin plugin unify REST return and exception management """
11
12    name = 'ReturnHandlerPlugin'
13    api = 2
14
15    def __init__(self, exception_mapping):
16        self.exception_mapping = exception_mapping
17
18    def setup(self, app):
19        """ Make sure that other installed plugins don't affect the same
20            keyword argument. """
21        for other in app.plugins:
22            if not isinstance(other, ReturnHandlerPlugin):
23                continue
24
25    def apply(self, callback, _):
26        """ Apply plugin """
27        def wrapper(*args, **kwargs):
28            """ Capture possible exceptions to manage the return """
29            try:
30                # The encoding from browsers is utf-8, so we assume it
31                for key, value in kwargs.items():
32                    if isinstance(value, str):
33                        kwargs[key] = value
34                return callback(*args, **kwargs)  # kwargs has :xxx variables from url
35            except HTTPResponse:
36                raise
37            except ConanException as excep:
38                return get_response_from_exception(excep, self.exception_mapping)
39            except Exception as e:
40                logger.error(e)
41                logger.error(traceback.print_exc())
42                return get_response_from_exception(e, self.exception_mapping)
43
44        return wrapper
45
46
47def get_response_from_exception(excep, exception_mapping):
48    status = exception_mapping.get(excep.__class__, None)
49    if status is None:
50        status = 500
51    ret = HTTPResponse(status=status, body=str(excep))
52    ret.add_header("Content-Type", "text/plain")
53    return ret
54