]> git.graph-it.com Git - graphit/controlpi-wsserver.git/commitdiff
Change to new websockets API master v0.4.1
authorBenjamin Braatz <bb@bbraatz.eu>
Tue, 31 Mar 2026 19:12:20 +0000 (21:12 +0200)
committerBenjamin Braatz <bb@bbraatz.eu>
Tue, 31 Mar 2026 19:35:29 +0000 (21:35 +0200)
controlpi_plugins/wsserver.py
setup.py

index c0dad68948396f930c71a6dc25c3728090a148d8..db2d47de105df78a55016abb88aa37ead3399bfb 100644 (file)
@@ -7,13 +7,13 @@ import http
 import json
 import os
 import sys
 import json
 import os
 import sys
-from websockets.datastructures import Headers
 from websockets.exceptions import ConnectionClosed
 from websockets.exceptions import ConnectionClosed
-from websockets.server import serve, WebSocketServerProtocol
+from websockets.asyncio.server import serve, ServerConnection
+from websockets.http11 import Request, Response
 
 from controlpi import BasePlugin, MessageBus, BusException, Message, MessageTemplate
 
 
 from controlpi import BasePlugin, MessageBus, BusException, Message, MessageTemplate
 
-from typing import Optional, Tuple
+from typing import Optional
 
 
 class Connection:
 
 
 class Connection:
@@ -22,7 +22,7 @@ class Connection:
     Instances are created on external connections to websocket.
     """
 
     Instances are created on external connections to websocket.
     """
 
-    def __init__(self, bus: MessageBus, websocket: WebSocketServerProtocol) -> None:
+    def __init__(self, bus: MessageBus, websocket: ServerConnection) -> None:
         """Initialise conncection.
 
         Message bus and websocket are set by websocket server when creating
         """Initialise conncection.
 
         Message bus and websocket are set by websocket server when creating
@@ -138,9 +138,6 @@ class Connection:
         self._bus.unregister(self._name)
 
 
         self._bus.unregister(self._name)
 
 
-Response = Optional[Tuple[http.HTTPStatus, Headers, bytes]]
-
-
 class WSServer(BasePlugin):
     """Websocket server plugin.
 
 class WSServer(BasePlugin):
     """Websocket server plugin.
 
@@ -216,15 +213,13 @@ class WSServer(BasePlugin):
                         base_url += "/"
                     self._web_proxies[path] = base_url
 
                         base_url += "/"
                     self._web_proxies[path] = base_url
 
-    async def _process_request(self, path: str, request_headers: Headers) -> Response:
+    async def _process_request(
+        self, websocket: ServerConnection, request: Request
+    ) -> Optional[Response]:
         """Serve as simple web server."""
         """Serve as simple web server."""
-        if "Upgrade" in request_headers:
+        if "Upgrade" in request.headers:
             return None
             return None
-        status = None
-        body = b""
-        response_headers = Headers()
-        response_headers["Server"] = "controlpi-wsserver websocket server"
-        response_headers["Connection"] = "close"
+        path = request.path
         location = ""
         url = ""
         start_path_length = 0
         location = ""
         url = ""
         start_path_length = 0
@@ -244,15 +239,19 @@ class WSServer(BasePlugin):
                     start_path += "/"
                 relative_path = path[len(start_path) :]
                 url = base_url + relative_path
                     start_path += "/"
                 relative_path = path[len(start_path) :]
                 url = base_url + relative_path
+        response = None
         if location:
             if os.path.isdir(location) and not path.endswith("/"):
         if location:
             if os.path.isdir(location) and not path.endswith("/"):
-                status = http.HTTPStatus.MOVED_PERMANENTLY
-                response_headers["Location"] = path + "/"
+                response = websocket.respond(http.HTTPStatus.MOVED_PERMANENTLY, "")
+                response.headers["Location"] = path + "/"
             else:
                 if os.path.isdir(location):
                     location = os.path.join(location, "index.html")
                 if os.path.isfile(location):
             else:
                 if os.path.isdir(location):
                     location = os.path.join(location, "index.html")
                 if os.path.isfile(location):
-                    status = http.HTTPStatus.OK
+                    # Read body from file:
+                    async with aiofiles.open(location, "rb") as f:
+                        body = (await f.read()).decode()
+                    response = websocket.respond(http.HTTPStatus.OK, body)
                     # Determine MIME type:
                     content_type = "application/octet-stream"
                     extension = os.path.basename(location).split(".")[-1]
                     # Determine MIME type:
                     content_type = "application/octet-stream"
                     extension = os.path.basename(location).split(".")[-1]
@@ -264,26 +263,22 @@ class WSServer(BasePlugin):
                         content_type = "text/css"
                     elif extension == "jpg":
                         content_type = "image/jpeg"
                         content_type = "text/css"
                     elif extension == "jpg":
                         content_type = "image/jpeg"
-                    response_headers["Content-Type"] = content_type
-                    # Read body from file:
-                    async with aiofiles.open(location, "rb") as f:
-                        body = await f.read()
-                    response_headers["Content-Length"] = str(len(body))
+                    del response.headers["Content-Type"]
+                    response.headers["Content-Type"] = content_type
         if url:
             async with aiohttp.ClientSession() as session:
         if url:
             async with aiohttp.ClientSession() as session:
-                async with session.get(url) as resp:
-                    status = http.HTTPStatus.OK
-                    response_headers["Content-Type"] = resp.headers["Content-Type"]
-                    response_headers["Content-Length"] = resp.headers["Content-Length"]
-                    body = await resp.read()
-        if not status:
-            status = http.HTTPStatus.NOT_FOUND
-            body = f"'{path}' not found!".encode()
-            response_headers["Content-Type"] = "text/plain"
-            response_headers["Content-Length"] = str(len(body))
-        return status, response_headers, body
+                async with session.get(url) as original:
+                    body = (await original.read()).decode()
+                    response = websocket.respond(http.HTTPStatus.OK, body)
+                    del response.headers["Content-Type"]
+                    response.headers["Content-Type"] = original.headers["Content-Type"]
+        if not response:
+            response = websocket.respond(
+                http.HTTPStatus.NOT_FOUND, f"'{path}' not found!"
+            )
+        return response
 
 
-    async def _handler(self, websocket: WebSocketServerProtocol, path: str) -> None:
+    async def _handler(self, websocket: ServerConnection) -> None:
         """Create and run connection."""
         connection = Connection(self.bus, websocket)
         await connection.run()
         """Create and run connection."""
         connection = Connection(self.bus, websocket)
         await connection.run()
index 7b6165c18edcf8a343ef79cadf3b835e8116f1a1..4054a7beb4093fec7bb31de2d850a822e92dcbb1 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ with open("README.md", "r") as readme_file:
 
 setuptools.setup(
     name="controlpi-wsserver",
 
 setuptools.setup(
     name="controlpi-wsserver",
-    version="0.4.0",
+    version="0.4.1",
     author="Graph-IT GmbH",
     author_email="info@graph-it.com",
     description="ControlPi Plugin for Websocket Servers",
     author="Graph-IT GmbH",
     author_email="info@graph-it.com",
     description="ControlPi Plugin for Websocket Servers",