------------------------------------------------------------
revno: 6722
committer: Barry Warsaw <[email protected]>
branch nick: restful
timestamp: Mon 2009-05-04 11:05:51 -0400
message:
A working test of the REST server. http://localhost:8001/3.0/sys returns
useful information. It's GET only atm.
added:
src/mailman/rest/docs/
src/mailman/rest/docs/basic.txt
src/mailman/rest/testing/
src/mailman/rest/testing/__init__.py
src/mailman/rest/testing/server.py
modified:
src/mailman/queue/rest.py
src/mailman/rest/webservice.py
src/mailman/tests/test_documentation.py
=== modified file 'src/mailman/queue/rest.py'
--- src/mailman/queue/rest.py 2009-05-03 19:35:29 +0000
+++ src/mailman/queue/rest.py 2009-05-04 15:05:51 +0000
@@ -32,14 +32,14 @@
import logging
from mailman.queue import Runner
-from mailman.rest.webservice import start
+from mailman.rest.webservice import make_server
class RESTRunner(Runner):
def run(self):
try:
- start()
+ make_server.serve_forever()
except KeyboardInterrupt:
sys.exit(signal.SIGTERM)
except select.error as (errcode, message):
=== added directory 'src/mailman/rest/docs'
=== added file 'src/mailman/rest/docs/basic.txt'
--- src/mailman/rest/docs/basic.txt 1970-01-01 00:00:00 +0000
+++ src/mailman/rest/docs/basic.txt 2009-05-04 15:05:51 +0000
@@ -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()
=== added directory 'src/mailman/rest/testing'
=== added file 'src/mailman/rest/testing/__init__.py'
=== added file 'src/mailman/rest/testing/server.py'
--- src/mailman/rest/testing/server.py 1970-01-01 00:00:00 +0000
+++ src/mailman/rest/testing/server.py 2009-05-04 15:05:51 +0000
@@ -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()
=== modified file 'src/mailman/rest/webservice.py'
--- src/mailman/rest/webservice.py 2009-05-03 19:35:29 +0000
+++ src/mailman/rest/webservice.py 2009-05-04 15:05:51 +0000
@@ -23,11 +23,16 @@
__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.interfaces.rest import IResolvePathNames
from mailman.rest.publication import AdminWebServicePublication
+log = logging.getLogger('mailman.http')
+
class AdminWebServiceRequest(WebServiceRequestTraversal, BrowserRequest):
@@ -82,11 +89,20 @@
-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
=== modified file 'src/mailman/tests/test_documentation.py'
--- src/mailman/tests/test_documentation.py 2009-02-10 03:19:18 +0000
+++ src/mailman/tests/test_documentation.py 2009-05-04 15:05:51 +0000
@@ -30,11 +30,13 @@
import os
+import json
import random
import doctest
import unittest
from email import message_from_string
+from urllib2 import urlopen
import mailman
@@ -103,6 +105,22 @@
print '{0:{2}}: {1}'.format(key, msgdata[key], longest)
+def dump_json(url):
+ """Print the JSON dictionary read from a URL.
+
+ :param url: The url to open, read, and print.
+ :type url: string
+ """
+ fp = urlopen(url)
+ # fp does not support the context manager protocol.
+ try:
+ data = json.load(fp)
+ finally:
+ fp.close()
+ for key in sorted(data):
+ print '{0}: {1}'.format(key, data[key])
+
+
def setup(testobj):
"""Test setup."""
@@ -113,6 +131,7 @@
testobj.globs['commit'] = config.db.commit
testobj.globs['config'] = config
testobj.globs['create_list'] = create_list
+ testobj.globs['dump_json'] = dump_json
testobj.globs['dump_msgdata'] = dump_msgdata
testobj.globs['message_from_string'] = specialized_message_from_string
testobj.globs['smtpd'] = SMTPLayer.smtpd
--
Primary development focus
https://code.launchpad.net/~mailman-coders/mailman/3.0
Your team Mailman Checkins is subscribed to branch lp:mailman.
To unsubscribe from this branch go to
https://code.launchpad.net/~mailman-coders/mailman/3.0/+edit-subscription.
_______________________________________________
Mailman-checkins mailing list
[email protected]
Unsubscribe:
http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org