[elbe-devel] [PATCH 5/6] elbepack: daemon: remove cherrypy usage

Thomas Weißschuh thomas.weissschuh at linutronix.de
Tue Jun 25 16:25:37 CEST 2024


Only WSGI server from cherrypy is used.
And through private APIs at that.

Switch to the stdlib WSGI server.
While it is single-threaded, so is the elbe initvm itself.
In case multithreading is needed in the future it is still possible to
switch either to ThreadingHTTPServer or even a dedicated WSGI server
library.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh at linutronix.de>
---
 elbepack/commands/daemon.py | 59 ++++++++++++++++++++++++++++++---------------
 1 file changed, 40 insertions(+), 19 deletions(-)

diff --git a/elbepack/commands/daemon.py b/elbepack/commands/daemon.py
index 08b396eb043f..af15da5923f2 100644
--- a/elbepack/commands/daemon.py
+++ b/elbepack/commands/daemon.py
@@ -4,14 +4,41 @@
 
 import contextlib
 import importlib
+import wsgiref.simple_server
 from optparse import OptionParser
 from pkgutil import iter_modules
 
-import cherrypy
-
 import elbepack.daemons
 
 
+def _not_found(start_response):
+    start_response('404 Not Found', [('Content-Type', 'text/plain')])
+    return [b'not found']
+
+
+class _WsgiDispatcher:
+    def __init__(self, mapping):
+        self.mapping = mapping
+
+    def __call__(self, environ, start_response):
+        path_info = environ['PATH_INFO']
+        parts = path_info.split('/', maxsplit=2)
+        if len(parts) != 3:
+            return _not_found(start_response)
+        _, app_name, _ = parts
+
+        app = self.mapping.get(app_name)
+        if app is None:
+            return _not_found(start_response)
+
+        return app(environ, start_response)
+
+
+class _ElbeWSGIRequestHandler(wsgiref.simple_server.WSGIRequestHandler):
+    def log_request(self, *args, **kargs):
+        pass  # Noop
+
+
 def get_daemonlist():
     return [x for _, x, _ in iter_modules(elbepack.daemons.__path__)]
 
@@ -36,6 +63,8 @@ def run_command(argv):
     (opt, _) = oparser.parse_args(argv)
 
     with contextlib.ExitStack() as stack:
+        mapping = {}
+
         for d in daemons:
             print(f'enable {d}')
             module = 'elbepack.daemons.' + str(d)
@@ -43,20 +72,12 @@ def run_command(argv):
             app = cmdmod.get_app()
             if hasattr(app, 'stop'):
                 stack.callback(app.stop)
-            cherrypy.tree.graft(app, '/' + str(d))
-
-        cherrypy.server.unsubscribe()
-        server = cherrypy._cpserver.Server()
-        server.socket_host = opt.host
-        server.socket_port = opt.port
-        server.thread_pool = 30
-
-        # For SSL Support
-        # server.ssl_module            = 'pyopenssl'
-        # server.ssl_certificate       = 'ssl/certificate.crt'
-        # server.ssl_private_key       = 'ssl/private.key'
-        # server.ssl_certificate_chain = 'ssl/bundle.crt'
-
-        server.subscribe()
-        cherrypy.engine.start()
-        cherrypy.engine.block()
+            mapping[d] = app
+
+        dispatcher = _WsgiDispatcher(mapping)
+
+        with wsgiref.simple_server.make_server(
+                opt.host, opt.port, dispatcher,
+                handler_class=_ElbeWSGIRequestHandler,
+        ) as httpd:
+            httpd.serve_forever()

-- 
2.45.2



More information about the elbe-devel mailing list