summaryrefslogtreecommitdiff
path: root/src/mailman/rest/wsgiapp.py
diff options
context:
space:
mode:
authorBarry Warsaw2014-08-12 16:42:12 -0400
committerBarry Warsaw2014-08-12 16:42:12 -0400
commit826261effa9d74b8ecdf1247e9ebba75fa3b2baa (patch)
treef6e609e56db4fe202a3b85361651832433cb514b /src/mailman/rest/wsgiapp.py
parentd4d71f71f08d6d440b17482eecc5472dcfe6cbae (diff)
downloadmailman-826261effa9d74b8ecdf1247e9ebba75fa3b2baa.tar.gz
mailman-826261effa9d74b8ecdf1247e9ebba75fa3b2baa.tar.zst
mailman-826261effa9d74b8ecdf1247e9ebba75fa3b2baa.zip
Diffstat (limited to 'src/mailman/rest/wsgiapp.py')
-rw-r--r--src/mailman/rest/wsgiapp.py66
1 files changed, 61 insertions, 5 deletions
diff --git a/src/mailman/rest/wsgiapp.py b/src/mailman/rest/wsgiapp.py
index b7ad3d698..8c2ee1758 100644
--- a/src/mailman/rest/wsgiapp.py
+++ b/src/mailman/rest/wsgiapp.py
@@ -28,7 +28,10 @@ __all__ = [
import logging
-from restish.app import RestishApp
+from falcon import API
+from falcon.api_helpers import create_http_method_map
+from falcon.status_codes import HTTP_404
+
from wsgiref.simple_server import WSGIRequestHandler
from wsgiref.simple_server import make_server as wsgi_server
@@ -40,6 +43,12 @@ from mailman.rest.root import Root
log = logging.getLogger('mailman.http')
+def path_not_found(request, response, **kws):
+ # Like falcon.responders.path_not_found() but sets the body.
+ response.status = HTTP_404
+ response.body = b'404 Not Found'
+
+
class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler):
"""Handler class which just logs output to the right place."""
@@ -49,15 +58,62 @@ class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler):
log.info('%s - - %s', self.address_string(), format % args)
-class AdminWebServiceApplication(RestishApp):
- """Connect the restish WSGI application to Mailman's database."""
+class RootedAPI(API):
+ def __init__(self, root, *args, **kws):
+ self._root = root
+ super(RootedAPI, self).__init__(*args, **kws)
@transactional
def __call__(self, environ, start_response):
"""See `RestishApp`."""
- return super(AdminWebServiceApplication, self).__call__(
+ return super(RootedAPI, self).__call__(
environ, start_response)
+ def _get_responder(self, req):
+ path = req.path
+ method = req.method
+ path_segments = path.split('/')
+ # Since the path is always rooted at /, skip the first segment, which
+ # will always be the empty string.
+ path_segments.pop(0)
+ if len(path_segments) == 0:
+ # We're at the end of the path, so the root must be the responder.
+ method_map = create_http_method_map(self._root, None, None, None)
+ responder = method_map[method]
+ return responder, {}, self._root
+ this_segment = path_segments.pop(0)
+ resource = self._root
+ while True:
+ # See if there's a child matching the current segment.
+ # See if any of the resource's child links match the next segment.
+ for name in dir(resource):
+ if name.startswith('__') and name.endswith('__'):
+ continue
+ attribute = getattr(resource, name)
+ assert attribute is not None, name
+ matcher = getattr(attribute, '__matcher__', None)
+ if matcher is None:
+ continue
+ if matcher == this_segment:
+ resource, path_segments = attribute(req, path_segments)
+ # The method could have truncated the remaining segments,
+ # meaning, it's consumed all the path segments, or this is
+ # the last path segment. In that case the resource we're
+ # left at is the responder.
+ if len(path_segments) == 0:
+ # We're at the end of the path, so the root must be the
+ # responder.
+ method_map = create_http_method_map(
+ resource, None, None, None)
+ responder = method_map[method]
+ return responder, {}, resource
+ this_segment = path_segments.pop(0)
+ break
+ else:
+ # None of the attributes matched this path component, so the
+ # response is a 404.
+ return path_not_found, {}, None
+
def make_application():
@@ -66,7 +122,7 @@ def make_application():
Use this if you want to integrate Mailman's REST server with your own WSGI
server.
"""
- return AdminWebServiceApplication(Root())
+ return RootedAPI(Root())
def make_server():