Add new websocket class HttpWebSocket

This class acts as a glue between websocket and http functionality by
taking a 'request_handler' and using its functions for send_response(),
send_header() and end_headers().
This commit is contained in:
Linn Mattsson
2022-10-11 07:31:48 +00:00
committed by Pierre Ossman
parent 832ae23f00
commit 4695f96728
3 changed files with 90 additions and 4 deletions
+69
View File
@@ -0,0 +1,69 @@
""" Unit tests for websocketserver """
import unittest
from unittest.mock import patch, MagicMock
from websockify.websocketserver import HttpWebSocket
class HttpWebSocketTest(unittest.TestCase):
@patch("websockify.websocketserver.WebSocket.__init__", autospec=True)
def test_constructor(self, websock):
# Given
req_obj = MagicMock()
# When
sock = HttpWebSocket(req_obj)
# Then
websock.assert_called_once_with(sock)
self.assertEqual(sock.request_handler, req_obj)
@patch("websockify.websocketserver.WebSocket.__init__", MagicMock(autospec=True))
def test_send_response(self):
# Given
req_obj = MagicMock()
sock = HttpWebSocket(req_obj)
# When
sock.send_response(200, "message")
# Then
req_obj.send_response.assert_called_once_with(200, "message")
@patch("websockify.websocketserver.WebSocket.__init__", MagicMock(autospec=True))
def test_send_response_default_message(self):
# Given
req_obj = MagicMock()
sock = HttpWebSocket(req_obj)
# When
sock.send_response(200)
# Then
req_obj.send_response.assert_called_once_with(200, None)
@patch("websockify.websocketserver.WebSocket.__init__", MagicMock(autospec=True))
def test_send_header(self):
# Given
req_obj = MagicMock()
sock = HttpWebSocket(req_obj)
# When
sock.send_header("keyword", "value")
# Then
req_obj.send_header.assert_called_once_with("keyword", "value")
@patch("websockify.websocketserver.WebSocket.__init__", MagicMock(autospec=True))
def test_end_headers(self):
# Given
req_obj = MagicMock()
sock = HttpWebSocket(req_obj)
# When
sock.end_headers()
# Then
req_obj.end_headers.assert_called_once_with()
+19 -2
View File
@@ -12,6 +12,23 @@ from http.server import BaseHTTPRequestHandler, HTTPServer
from websockify.websocket import WebSocket, WebSocketWantReadError, WebSocketWantWriteError
class HttpWebSocket(WebSocket):
"""Class to glue websocket and http request functionality together"""
def __init__(self, request_handler):
super().__init__()
self.request_handler = request_handler
def send_response(self, code, message=None):
self.request_handler.send_response(code, message)
def send_header(self, keyword, value):
self.request_handler.send_header(keyword, value)
def end_headers(self):
self.request_handler.end_headers()
class WebSocketRequestHandlerMixIn:
"""WebSocket request handler mix-in class
@@ -25,7 +42,7 @@ class WebSocketRequestHandlerMixIn:
use for the WebSocket connection.
"""
SocketClass = WebSocket
SocketClass = HttpWebSocket
def handle_one_request(self):
"""Extended request handler
@@ -59,7 +76,7 @@ class WebSocketRequestHandlerMixIn:
The WebSocket object will then replace the request object and
handle_websocket() will be called.
"""
websocket = self.SocketClass()
websocket = self.SocketClass(self)
try:
websocket.accept(self.request, self.headers)
except Exception:
+2 -2
View File
@@ -29,10 +29,10 @@ if sys.platform == 'win32':
# make sockets pickle-able/inheritable
import multiprocessing.reduction
from websockify.websocket import WebSocket, WebSocketWantReadError, WebSocketWantWriteError
from websockify.websocket import WebSocketWantReadError, WebSocketWantWriteError
from websockify.websocketserver import WebSocketRequestHandlerMixIn
class CompatibleWebSocket(WebSocket):
class CompatibleWebSocket(WebSocketRequestHandlerMixIn.SocketClass):
def select_subprotocol(self, protocols):
# Handle old websockify clients that still specify a sub-protocol
if 'binary' in protocols: