diff --git a/wsme/protocols/__init__.py b/wsme/protocols/__init__.py index b0846b3..465932a 100644 --- a/wsme/protocols/__init__.py +++ b/wsme/protocols/__init__.py @@ -11,6 +11,26 @@ __all__ = [ registered_protocols = {} +def _cfg(f): + cfg = getattr(f, '_cfg', None) + if cfg is None: + f._cfg = cfg = {} + return cfg + + +class expose(object): + def __init__(self, path, content_type): + self.path = path + self.content_type = content_type + + def __call__(self, func): + func.exposed = True + cfg = _cfg(func) + cfg['content-type'] = self.content_type + cfg['path'] = self.path + return func + + class CallContext(object): def __init__(self, request): self._request = weakref.ref(request) @@ -30,6 +50,12 @@ class Protocol(object): dataformat = None content_types = [] + def iter_routes(self): + for attrname in dir(self): + attr = getattr(self, attrname) + if getattr(attr, 'exposed', False): + yield _cfg(attr)['path'], attr + def accept(self, request): if request.path.endswith('.' + self.dataformat): return True diff --git a/wsme/root.py b/wsme/root.py index f91e2cc..fb8258d 100644 --- a/wsme/root.py +++ b/wsme/root.py @@ -199,10 +199,30 @@ class WSRoot(object): request.server_errorcount += 1 return protocol.encode_error(context, infos) + def find_route(self, path): + for p in self.protocols: + for routepath, func in p.iter_routes(): + if path.startswith(routepath): + return routepath, func + return None, None + def _handle_request(self, request): res = webob.Response() res_content_type = None + path = request.path + if path.startswith(self._webpath): + path = path[len(self._webpath):] + routepath, func = self.find_route(path) + if routepath: + content = func() + if isinstance(content, six.text_type): + res.text = content + elif isinstance(content, six.binary_type): + res.body = content + res.content_type = func._cfg['content-type'] + return res + if request.path == self._webpath + '/api.spore': res.body = spore.getdesc(self, request.host_url) res.content_type = 'application/json'