summaryrefslogtreecommitdiff
path: root/src/mailman/rest
diff options
context:
space:
mode:
authorBarry Warsaw2009-05-04 11:05:51 -0400
committerBarry Warsaw2009-05-04 11:05:51 -0400
commit70e6738197f225d486a555bfe7fca81073f38347 (patch)
tree8e72b893df67d990ad888fc46964589321ab53a5 /src/mailman/rest
parente920c98c72fc9674316ae32c26a81fe571964ea5 (diff)
downloadmailman-70e6738197f225d486a555bfe7fca81073f38347.tar.gz
mailman-70e6738197f225d486a555bfe7fca81073f38347.tar.zst
mailman-70e6738197f225d486a555bfe7fca81073f38347.zip
A working test of the REST server. http://localhost:8001/3.0/sys returns
useful information. It's GET only atm.
Diffstat (limited to 'src/mailman/rest')
-rw-r--r--src/mailman/rest/docs/basic.txt30
-rw-r--r--src/mailman/rest/testing/__init__.py0
-rw-r--r--src/mailman/rest/testing/server.py63
-rw-r--r--src/mailman/rest/webservice.py28
4 files changed, 115 insertions, 6 deletions
diff --git a/src/mailman/rest/docs/basic.txt b/src/mailman/rest/docs/basic.txt
new file mode 100644
index 000000000..7afa7a120
--- /dev/null
+++ b/src/mailman/rest/docs/basic.txt
@@ -0,0 +1,30 @@
+REST server
+===========
+
+Mailman exposes a REST HTTP server for administrative control.
+
+ >>> from mailman.rest.testing.server import TestableServer
+ >>> server = TestableServer()
+ >>> server.start()
+
+The server listens for connections on a configurable host name and port.
+Because the REST server has full administrative access, it should always be
+run only on localhost, unless you really know what you're doing. The Mailman
+major and minor version numbers are in the URL.
+
+System information can be retrieved from the server. By default JSON is
+returned.
+
+ >>> dump_json('http://localhost:8001/3.0/sys')
+ http_etag: "b49c76fb07102f7d56884268c46091367fef180d"
+ mailman_version: GNU Mailman 3.0.0a3 (Working Man)
+ python_version: 2.6.2+ (release26-maint:71636:71637, Apr 15 2009, 20:51:2)
+ [GCC 4.0.1 (Apple Inc. build 5490)]
+ resource_type_link: https://localhost:8001/3.0/#system
+ self_link: https://localhost:8001/3.0/sys
+
+
+Cleanup
+-------
+
+ >>> server.stop()
diff --git a/src/mailman/rest/testing/__init__.py b/src/mailman/rest/testing/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/mailman/rest/testing/__init__.py
diff --git a/src/mailman/rest/testing/server.py b/src/mailman/rest/testing/server.py
new file mode 100644
index 000000000..d4b9df256
--- /dev/null
+++ b/src/mailman/rest/testing/server.py
@@ -0,0 +1,63 @@
+# Copyright (C) 2009 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""A testable REST server."""
+
+from __future__ import absolute_import, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'TestableServer',
+ ]
+
+
+import logging
+import threading
+
+from urllib2 import urlopen
+
+from mailman.rest.webservice import make_server
+
+
+log = logging.getLogger('mailman.http')
+
+
+
+class TestableServer:
+ """A REST server which polls for the stop action."""
+
+ def __init__(self):
+ self.server = make_server()
+ self.event = threading.Event()
+ self.thread = threading.Thread(target=self.loop)
+
+ def start(self):
+ """Start the server."""
+ self.thread.start()
+
+ def stop(self):
+ """Stop the server by firing the event."""
+ self.event.set()
+ # Fire off one more request so the handle_request() will exit. XXX
+ # Should we set a .timeout on the server instead?
+ fp = urlopen('http://localhost:8001/3.0/sys')
+ fp.close()
+ self.thread.join()
+
+ def loop(self):
+ while not self.event.is_set():
+ self.server.handle_request()
diff --git a/src/mailman/rest/webservice.py b/src/mailman/rest/webservice.py
index fe14513b9..fc8bdfcf4 100644
--- a/src/mailman/rest/webservice.py
+++ b/src/mailman/rest/webservice.py
@@ -23,11 +23,16 @@ __metaclass__ = type
__all__ = [
'AdminWebServiceApplication',
'AdminWebServiceRequest',
- 'start',
+ 'make_server',
]
-from wsgiref.simple_server import make_server
+import logging
+
+# Don't use wsgiref.simple_server.make_server() because we need to override
+# BaseHTTPRequestHandler.log_message() so that logging output will go to the
+# proper Mailman logger instead of stderr, as is the default.
+from wsgiref.simple_server import WSGIServer, WSGIRequestHandler
from lazr.restful.publisher import WebServiceRequestTraversal
from pkg_resources import resource_string
@@ -41,6 +46,8 @@ from mailman.core.system import system
from mailman.interfaces.rest import IResolvePathNames
from mailman.rest.publication import AdminWebServicePublication
+log = logging.getLogger('mailman.http')
+
class AdminWebServiceRequest(WebServiceRequestTraversal, BrowserRequest):
@@ -82,11 +89,20 @@ class AdminWebServiceApplication:
-def start():
- """Start the WSGI admin REST service."""
+class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler):
+ """Handler class which just logs output to the right place."""
+
+ def log_message(self, format, *args):
+ """See `BaseHTTPRequestHandler`."""
+ log.info('%s - - %s', self.address_string(), format % args)
+
+
+def make_server():
+ """Create the WSGI admin REST server."""
zcml = resource_string('mailman.rest', 'configure.zcml')
xmlconfig.string(zcml)
host = config.webservice.hostname
port = int(config.webservice.port)
- server = make_server(host, port, AdminWebServiceApplication)
- server.serve_forever()
+ server = WSGIServer((host, port), AdminWebServiceWSGIRequestHandler)
+ server.set_app(AdminWebServiceApplication)
+ return server