MIME type for jpg and redirect path to trailing slash.
authorBenjamin Braatz <bb@bbraatz.eu>
Wed, 28 Jul 2021 12:08:57 +0000 (14:08 +0200)
committerBenjamin Braatz <bb@bbraatz.eu>
Wed, 28 Jul 2021 12:08:57 +0000 (14:08 +0200)
controlpi_plugins/wsserver.py

index a3706dbc0ee7671b0add1fdb87f0d7aaad5a83bf..1ba89818f003bbcfb9e607b917e1050f3b1e4877 100644 (file)
@@ -1,18 +1,11 @@
-"""Provide websocket server plugin.
-
-…
-
-TODO: documentation, doctests
-TODO: Let Debug web app collapse/expand nested structures
-TODO: Make Debug web app work with nested structures in commands
-"""
 import asyncio
+import http
 import json
 import os
 import sys
-from websockets import WebSocketServerProtocol, ConnectionClosed, serve
-from websockets.http import Headers
-from http import HTTPStatus
+from websockets.datastructures import Headers
+from websockets.exceptions import ConnectionClosed
+from websockets.legacy.server import serve, WebSocketServerProtocol
 
 from controlpi import BasePlugin, MessageBus, Message, MessageTemplate
 
@@ -96,7 +89,7 @@ class Connection:
         self._bus.unregister(self._name)
 
 
-Response = Optional[Tuple[HTTPStatus, Headers, bytes]]
+Response = Optional[Tuple[http.HTTPStatus, Headers, bytes]]
 
 
 class WSServer(BasePlugin):
@@ -142,13 +135,16 @@ class WSServer(BasePlugin):
         response_headers['Server'] = 'controlpi-wsserver websocket server'
         response_headers['Connection'] = 'close'
         if path not in self._web_files:
-            return (HTTPStatus.NOT_FOUND, response_headers,
+            return (http.HTTPStatus.NOT_FOUND, response_headers,
                     f"File '{path}' not found!".encode())
         file_info = self._web_files[path]
+        if 'redirect' in file_info:
+            response_headers['Location'] = file_info['redirect']
+            return http.HTTPStatus.MOVED_PERMANENTLY, response_headers, b''
         response_headers['Content-Type'] = file_info['type']
         body = open(file_info['location'], 'rb').read()
         response_headers['Content-Length'] = str(len(body))
-        return HTTPStatus.OK, response_headers, body
+        return http.HTTPStatus.OK, response_headers, body
 
     def process_conf(self) -> None:
         """Get host, port and path settings from configuration."""
@@ -194,19 +190,24 @@ class WSServer(BasePlugin):
                             file_info['type'] = 'text/javascript'
                         elif extension == 'css':
                             file_info['type'] = 'text/css'
+                        elif extension == 'jpg':
+                            file_info['type'] = 'image/jpeg'
                         # Register in instance variable:
                         self._web_files[file_path] = file_info
                         # Serve index.html also as directory:
                         if filename == 'index.html':
                             self._web_files[dir_path] = file_info
-                            self._web_files[dir_path.rstrip('/')] = file_info
+                            self._web_files[dir_path.rstrip('/')] = \
+                                {'redirect': dir_path}
 
     async def run(self) -> None:
         """Set up websocket server."""
         serving = False
         while not serving:
             try:
-                await serve(self._handler, host=self._host, port=self._port,
+                await serve(self._handler,
+                            host=self._host,
+                            port=self._port,
                             process_request=self._process_request)
                 serving = True
             except OSError: