diff options
Diffstat (limited to 'paste/wareweb/dispatch.py')
| -rw-r--r-- | paste/wareweb/dispatch.py | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/paste/wareweb/dispatch.py b/paste/wareweb/dispatch.py new file mode 100644 index 0000000..8cfc6ec --- /dev/null +++ b/paste/wareweb/dispatch.py @@ -0,0 +1,91 @@ +from paste import httpexceptions +import event + +__all__ = ['public', 'ActionDispatch', 'PathDispatch'] + +def public(func): + func.public = True + return func + +class MethodDispatch(object): + + prefix = None + + def __addtoclass__(self, attr, cls): + cls.listeners.append(self.respond_event) + + def respond_event(self, name, servlet, *args, **kw): + if name == 'end_awake': + return self.find_method(servlet, *args, **kw) + return event.Continue + + def get_method(self, servlet, action): + try: + return action, getattr(servlet, action) + except AttributeError: + pass + if self.prefix: + try: + return (self.prefix + action, + getattr(servlet, self.prefix + action)) + except AttributeError: + pass + return None, None + + def valid_method(self, name, method): + if getattr(method, 'public', False): + return True + if self.prefix and name.startswith(self.prefix): + return True + return False + +class ActionDispatch(MethodDispatch): + + prefix = 'action_' + + def __init__(self, action_name='_action_'): + self.action_name = action_name + + def find_method(self, servlet, ret_value): + possible_actions = [] + for name, value in servlet.fields.items(): + if name == self.action_name: + possible_actions.append(value) + elif name.startswith(self.action_name): + possible_actions.append(name[len(self.action_name):]) + if not possible_actions: + return event.Continue + if len(possible_actions) > 1: + raise httpexceptions.HTTPBadRequest( + "More than one action received: %s" + % ', '.join(map(repr, possible_actions))) + action = possible_actions[0] + name, method = self.get_method(servlet, action) + if name is None: + raise httpexceptions.Forbidden( + "Action method not found: %r" % action) + if not self.valid_method(name, method): + raise httpexceptions.Forbidden( + "Method not allowed: %r" % action) + return method() + +class PathDispatch(MethodDispatch): + + prefix = 'path_' + + def find_method(self, servlet, ret_value): + parts = servlet.path_parts + if not parts: + action == 'index' + else: + action == parts[0] + servlet.path_parts = parts[1:] + name, method = self.get_method(servlet, action) + if name is None: + raise httpexceptions.Forbidden( + "Method not found: %r" % action) + if not self.valid_method(name, method): + raise httpexceptions.Forbidden( + "Method not allowed: %r" % action) + return method() + |
