-"""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
self._bus.unregister(self._name)
-Response = Optional[Tuple[HTTPStatus, Headers, bytes]]
+Response = Optional[Tuple[http.HTTPStatus, Headers, bytes]]
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."""
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: