浏览代码

- An 'OK' URL was added at /ok.html which just returns the string
'OK' (can be used for up checks or speed checks via
plain-old-HTTP).

- Micro-optimizations.

Chris McDonough 17 年之前
父节点
当前提交
6b60bc25c8
共有 6 个文件被更改,包括 87 次插入12 次删除
  1. 4 0
      CHANGES.txt
  2. 6 8
      src/supervisor/http.py
  3. 52 4
      src/supervisor/tests/test_http.py
  4. 10 0
      src/supervisor/tests/test_xmlrpc.py
  5. 12 0
      src/supervisor/web.py
  6. 3 0
      src/supervisor/xmlrpc.py

+ 4 - 0
CHANGES.txt

@@ -118,6 +118,10 @@ Next Release
     SUPERVISOR_SERVER_URL.  This contains the server URL for the
     SUPERVISOR_SERVER_URL.  This contains the server URL for the
     supervisord running the child.
     supervisord running the child.
 
 
+  - An 'OK' URL was added at /ok.html which just returns the string
+    'OK' (can be used for up checks or speed checks via
+    plain-old-HTTP).
+
 3.0a2
 3.0a2
 
 
   - Fixed the README.txt example for defining the supervisor RPC
   - Fixed the README.txt example for defining the supervisor RPC

+ 6 - 8
src/supervisor/http.py

@@ -654,9 +654,8 @@ class logtail_handler:
         self.supervisord = supervisord
         self.supervisord = supervisord
 
 
     def match(self, request):
     def match(self, request):
-        path, params, query, fragment = request.split_uri()
-        return (path[:len(self.path)] == self.path)
-
+        return request.uri.startswith(self.path)
+        
     def handle_request(self, request):
     def handle_request(self, request):
         if request.command != 'GET':
         if request.command != 'GET':
             request.error (400) # bad request
             request.error (400) # bad request
@@ -720,8 +719,7 @@ class mainlogtail_handler:
         self.supervisord = supervisord
         self.supervisord = supervisord
 
 
     def match(self, request):
     def match(self, request):
-        path, params, query, fragment = request.split_uri()
-        return (path[:len(self.path)] == self.path)
+        return request.uri.startswith(self.path)
 
 
     def handle_request(self, request):
     def handle_request(self, request):
         if request.command != 'GET':
         if request.command != 'GET':
@@ -807,8 +805,8 @@ def make_http_server(options, supervisord):
     else:
     else:
         options.logger.critical('Running without any HTTP authentication '
         options.logger.critical('Running without any HTTP authentication '
                                 'checking')
                                 'checking')
-    hs.install_handler(uihandler)
-    hs.install_handler(tailhandler)
     hs.install_handler(maintailhandler)
     hs.install_handler(maintailhandler)
-    hs.install_handler(xmlrpchandler)
+    hs.install_handler(tailhandler)
+    hs.install_handler(uihandler) # second-to-last for speed
+    hs.install_handler(xmlrpchandler) # last for speed (first checked)
     return hs
     return hs

+ 52 - 4
src/supervisor/tests/test_http.py

@@ -10,14 +10,23 @@ from supervisor.tests.base import DummyProcess
 
 
 from supervisor.http import NOT_DONE_YET
 from supervisor.http import NOT_DONE_YET
 
 
-class LogtailHandlerTests(unittest.TestCase):
+class HandlerTests:
+    def _makeOne(self, supervisord):
+        return self._getTargetClass()(supervisord)
+
+    def test_match(self):
+        class DummyRequest:
+            def __init__(self, uri):
+                self.uri = uri
+        supervisor = DummySupervisor()
+        handler = self._makeOne(supervisor)
+        self.assertEqual(handler.match(DummyRequest(handler.path)), True)
+
+class LogtailHandlerTests(HandlerTests, unittest.TestCase):
     def _getTargetClass(self):
     def _getTargetClass(self):
         from supervisor.http import logtail_handler
         from supervisor.http import logtail_handler
         return logtail_handler
         return logtail_handler
 
 
-    def _makeOne(self, supervisord):
-        return self._getTargetClass()(supervisord)
-
     def test_handle_request_stdout_logfile_none(self):
     def test_handle_request_stdout_logfile_none(self):
         options = DummyOptions()
         options = DummyOptions()
         pconfig = DummyPConfig(options, 'process1', '/bin/process1', priority=1,
         pconfig = DummyPConfig(options, 'process1', '/bin/process1', priority=1,
@@ -59,6 +68,45 @@ class LogtailHandlerTests(unittest.TestCase):
         self.assertEqual(len(request.producers), 1)
         self.assertEqual(len(request.producers), 1)
         self.assertEqual(request._done, True)
         self.assertEqual(request._done, True)
 
 
+class MainLogTailHandlerTests(HandlerTests, unittest.TestCase):
+    def _getTargetClass(self):
+        from supervisor.http import mainlogtail_handler
+        return mainlogtail_handler
+
+    def test_handle_request_stdout_logfile_none(self):
+        supervisor = DummySupervisor()
+        handler = self._makeOne(supervisor)
+        request = DummyRequest('/mainlogtail', None, None, None)
+        handler.handle_request(request)
+        self.assertEqual(request._error, 410)
+
+    def test_handle_request_stdout_logfile_missing(self):
+        supervisor = DummySupervisor()
+        supervisor.options.logfile = '/not/there'
+        request = DummyRequest('/mainlogtail', None, None, None)
+        handler = self._makeOne(supervisor)
+        handler.handle_request(request)
+        self.assertEqual(request._error, 410)
+
+    def test_handle_request(self):
+        supervisor = DummySupervisor()
+        import tempfile
+        import os
+        import stat
+        f = tempfile.NamedTemporaryFile()
+        t = f.name
+        supervisor.options.logfile = t
+        handler = self._makeOne(supervisor)
+        request = DummyRequest('/mainlogtail', None, None, None)
+        handler.handle_request(request)
+        self.assertEqual(request._error, None)
+        from medusa import http_date
+        self.assertEqual(request.headers['Last-Modified'],
+                         http_date.build_http_date(os.stat(t)[stat.ST_MTIME]))
+        self.assertEqual(request.headers['Content-Type'], 'text/plain')
+        self.assertEqual(len(request.producers), 1)
+        self.assertEqual(request._done, True)
+    
 
 
 class TailFProducerTests(unittest.TestCase):
 class TailFProducerTests(unittest.TestCase):
     def _getTargetClass(self):
     def _getTargetClass(self):

+ 10 - 0
src/supervisor/tests/test_xmlrpc.py

@@ -32,6 +32,16 @@ class XMLRPCHandlerTests(unittest.TestCase):
         from supervisor.xmlrpc import RootRPCInterface
         from supervisor.xmlrpc import RootRPCInterface
         self.assertEqual(handler.rpcinterface.__class__, RootRPCInterface)
         self.assertEqual(handler.rpcinterface.__class__, RootRPCInterface)
 
 
+    def test_match(self):
+        class DummyRequest:
+            def __init__(self, uri):
+                self.uri = uri
+        supervisor = DummySupervisor()
+        subinterfaces = [('supervisor', DummySupervisorRPCNamespace())]
+        handler = self._makeOne(supervisor, subinterfaces)
+        self.assertEqual(handler.match(DummyRequest('/RPC2')), True)
+        self.assertEqual(handler.match(DummyRequest('/nope')), False)
+
     def test_continue_request_nosuchmethod(self):
     def test_continue_request_nosuchmethod(self):
         supervisor = DummySupervisor()
         supervisor = DummySupervisor()
         subinterfaces = [('supervisor', DummySupervisorRPCNamespace())]
         subinterfaces = [('supervisor', DummySupervisorRPCNamespace())]

+ 12 - 0
src/supervisor/web.py

@@ -499,6 +499,14 @@ class StatusView(MeldView):
 
 
         return root.write_xhtmlstring()
         return root.write_xhtmlstring()
 
 
+class OKView:
+    delay = 0
+    def __init__(self, context):
+        self.context = context
+        
+    def __call__(self):
+        return {'body':'OK'}
+
 VIEWS = {
 VIEWS = {
     'index.html': {
     'index.html': {
           'template':'ui/status.html',
           'template':'ui/status.html',
@@ -508,6 +516,10 @@ VIEWS = {
            'template':'ui/tail.html',
            'template':'ui/tail.html',
            'view':TailView,
            'view':TailView,
            },
            },
+    'ok.html': {
+           'template':None,
+           'view':OKView,
+           },
     }
     }
 
 
 
 

+ 3 - 0
src/supervisor/xmlrpc.py

@@ -321,6 +321,9 @@ class supervisor_xmlrpc_handler(xmlrpc_handler):
     def __init__(self, supervisord, subinterfaces):
     def __init__(self, supervisord, subinterfaces):
         self.rpcinterface = RootRPCInterface(subinterfaces)
         self.rpcinterface = RootRPCInterface(subinterfaces)
         self.supervisord = supervisord
         self.supervisord = supervisord
+
+    def match(self, request):
+        return request.uri.startswith('/RPC2')
         
         
     def continue_request (self, data, request):
     def continue_request (self, data, request):
         logger = self.supervisord.options.logger
         logger = self.supervisord.options.logger