------------------------------------------------------------
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

Reply via email to