summaryrefslogtreecommitdiff
path: root/paste/wareweb/dispatch.py
diff options
context:
space:
mode:
Diffstat (limited to 'paste/wareweb/dispatch.py')
-rw-r--r--paste/wareweb/dispatch.py91
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()
+