示例#1
0
文件: brick.py 项目: zruibin/bottle
class Brick(object):
    def __init__(self, catchall=True, autojson=True, config=None):
        self.routes = Router()
        self._logger = None
        self.mounts = {}
        self.error_handler = {}
        self.catchall = catchall
        self.config = config or {}
        self.serve = True
        self.castfilter = []
        if autojson and dumps:
            self.add_filter(dict, dumps)

    def optimize(self, *a, **ka):
        depr("Brick.optimize() is obsolete.")

    def mount(self, app, script_path):
        if not isinstance(app, Brick):
            raise TypeError('Only Brick instances are supported for now.')
        script_path = '/'.join(filter(None, script_path.split('/')))
        path_depth = script_path.count('/') + 1
        if not script_path:
            raise TypeError('Empty script_path. Perhaps you want a merge()?')
        for other in self.mounts:
            if other.startswith(script_path):
                raise TypeError('Conflict with existing mount: %s' % other)

        @self.route('/%s/:#.*#' % script_path, method="ANY")
        def mountpoint():
            request.path_shift(path_depth)
            return app.handle(request.path, request.method)

        self.mounts[script_path] = app

    def add_filter(self, ftype, func):
        if not isinstance(ftype, type):
            raise TypeError("Expected type object, got %s" % type(ftype))
        self.castfilter = [(t, f) for (t, f) in self.castfilter if t != ftype]
        self.castfilter.append((ftype, func))
        self.castfilter.sort()

    def match_url(self, path, method='GET'):
        path, method = path.strip().lstrip('/'), method.upper()
        callbacks, args = self.routes.match(path)
        if not callbacks:
            raise HTTPError(404, "Not found: " + path)
        if method in callbacks:
            return callbacks[method], args
        if method == 'HEAD' and 'GET' in callbacks:
            return callbacks['GET'], args
        if 'ANY' in callbacks:
            return callbacks['ANY'], args
        allow = [m for m in callbacks if m != 'ANY']
        if 'GET' in allow and 'HEAD' not in allow:
            allow.append('HEAD')
        raise HTTPError(405,
                        "Method not allowed.",
                        header=[('Allow', ",".join(allow))])

    def get_url(self, routename, **kargs):
        scriptname = request.environ.get('SCRIPT_NAME', '').strip('/') + '/'
        location = self.routes.build(routename, **kargs).lstrip('/')
        return urljoin(urljoin('/', scriptname), location)

    def route(self, path=None, method='GET', **kargs):
        def wrapper(callback):
            routes = [path] if path else yieldroutes(callback)
            methods = method.split(';') if isinstance(method, str) else method
            for r in routes:
                for m in methods:
                    r, m = r.strip().lstrip('/'), m.strip().upper()
                    old = self.routes.get_route(r, **kargs)
                    if old:
                        old.target[m] = callback
                    else:
                        self.routes.add(r, {m: callback}, **kargs)
                        self.routes.compile()
            return callback

        return wrapper

    def get(self, path=None, method='GET', **kargs):
        return self.route(path, method, **kargs)

    def post(self, path=None, method='POST', **kargs):
        return self.route(path, method, **kargs)

    def put(self, path=None, method='PUT', **kargs):
        return self.route(path, method, **kargs)

    def delete(self, path=None, method='DELETE', **kargs):
        return self.route(path, method, **kargs)

    def error(self, code=500):
        def wrapper(handler):
            self.error_handler[int(code)] = handler
            return handler

        return wrapper

    def handle(self, url, method):
        if not self.serve:
            return HTTPError(503, "Server stopped")
        try:
            handler, args = self.match_url(url, method)
            return handler(**args)
        except HTTPResponse, e:
            return e
        except Exception, e:
            if isinstance(e, (KeyboardInterrupt, SystemExit, MemoryError))\
            or not self.catchall:
                raise
            print e
            return HTTPError(500, 'Unhandled exception', e, format_exc(10))
示例#2
0
文件: brick.py 项目: ListFranz/bottle
class Brick(object):

    def __init__(self, catchall=True, autojson=True, config=None):
        self.routes = Router()
        self._logger=None
        self.mounts = {}
        self.error_handler = {}
        self.catchall = catchall
        self.config = config or {}
        self.serve = True
        self.castfilter = []
        if autojson and dumps:
            self.add_filter(dict, dumps)

    def optimize(self, *a, **ka):
        depr("Brick.optimize() is obsolete.")

    def mount(self, app, script_path):
        if not isinstance(app, Brick):
            raise TypeError('Only Brick instances are supported for now.')
        script_path = '/'.join(filter(None, script_path.split('/')))
        path_depth = script_path.count('/') + 1
        if not script_path:
            raise TypeError('Empty script_path. Perhaps you want a merge()?')
        for other in self.mounts:
            if other.startswith(script_path):
                raise TypeError('Conflict with existing mount: %s' % other)
        @self.route('/%s/:#.*#' % script_path, method="ANY")
        def mountpoint():
            request.path_shift(path_depth)
            return app.handle(request.path, request.method)
        self.mounts[script_path] = app

    def add_filter(self, ftype, func):
        if not isinstance(ftype, type):
            raise TypeError("Expected type object, got %s" % type(ftype))
        self.castfilter = [(t, f) for (t, f) in self.castfilter if t != ftype]
        self.castfilter.append((ftype, func))
        self.castfilter.sort()

    def match_url(self, path, method='GET'):
        path, method = path.strip().lstrip('/'), method.upper()
        callbacks, args = self.routes.match(path)
        if not callbacks:
            raise HTTPError(404, "Not found: " + path)
        if method in callbacks:
            return callbacks[method], args
        if method == 'HEAD' and 'GET' in callbacks:
            return callbacks['GET'], args
        if 'ANY' in callbacks:
            return callbacks['ANY'], args
        allow = [m for m in callbacks if m != 'ANY']
        if 'GET' in allow and 'HEAD' not in allow:
            allow.append('HEAD')
        raise HTTPError(405, "Method not allowed.",
                        header=[('Allow',",".join(allow))])

    def get_url(self, routename, **kargs):
        scriptname = request.environ.get('SCRIPT_NAME', '').strip('/') + '/'
        location = self.routes.build(routename, **kargs).lstrip('/')
        return urljoin(urljoin('/', scriptname), location)

    def route(self, path=None, method='GET', **kargs):
        def wrapper(callback):
            routes = [path] if path else yieldroutes(callback)
            methods = method.split(';') if isinstance(method, str) else method
            for r in routes:
                for m in methods:
                    r, m = r.strip().lstrip('/'), m.strip().upper()
                    old = self.routes.get_route(r, **kargs)
                    if old:
                        old.target[m] = callback
                    else:
                        self.routes.add(r, {m: callback}, **kargs)
                        self.routes.compile()
            return callback
        return wrapper

    def get(self, path=None, method='GET', **kargs):
        return self.route(path, method, **kargs)

    def post(self, path=None, method='POST', **kargs):
        return self.route(path, method, **kargs)

    def put(self, path=None, method='PUT', **kargs):
        return self.route(path, method, **kargs)

    def delete(self, path=None, method='DELETE', **kargs):
        return self.route(path, method, **kargs)

    def error(self, code=500):
        def wrapper(handler):
            self.error_handler[int(code)] = handler
            return handler
        return wrapper

    def handle(self, url, method):
        if not self.serve:
            return HTTPError(503, "Server stopped")
        try:
            handler, args = self.match_url(url, method)
            return handler(**args)
        except HTTPResponse, e:
            return e
        except Exception, e:
            if isinstance(e, (KeyboardInterrupt, SystemExit, MemoryError))\
            or not self.catchall:
                raise
            print e
            return HTTPError(500, 'Unhandled exception', e, format_exc(10))