Change WebSocket request handler to a mix-in

We can't get the inheritence right in non-trivial cases as a regular
base class, so change it to be a mix-in that is to be combined with
one of the existing request handlers from the Python library.
This commit is contained in:
Pierre Ossman 2018-08-15 17:05:34 +02:00
parent 6ba82d371b
commit be5d30ad25
2 changed files with 25 additions and 17 deletions

View File

@ -3,7 +3,7 @@
''' '''
Python WebSocket server base Python WebSocket server base
Copyright 2011 Joel Martin Copyright 2011 Joel Martin
Copyright 2016 Pierre Ossman Copyright 2016-2018 Pierre Ossman
Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3) Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
''' '''
@ -17,14 +17,14 @@ except ImportError:
from websockify.websocket import WebSocket, WebSocketWantReadError, WebSocketWantWriteError from websockify.websocket import WebSocket, WebSocketWantReadError, WebSocketWantWriteError
class WebSocketRequestHandler(BaseHTTPRequestHandler): class WebSocketRequestHandlerMixIn:
"""WebSocket request handler base class. """WebSocket request handler mix-in class
This class forms the base for a server that wishes to handle This class modifies and existing request handler to handle
WebSocket requests. It functions exactly as BastHTTPRequestHandler, WebSocket requests. The request handler will continue to function
except that WebSocket requests are intercepted and the methods as before, except that WebSocket requests are intercepted and the
handle_upgrade() and handle_websocket() are called. The standard methods handle_upgrade() and handle_websocket() are called. The
do_GET() will be called for normal requests. standard do_GET() will be called for normal requests.
The class instance SocketClass can be overridden with the class to The class instance SocketClass can be overridden with the class to
use for the WebSocket connection. use for the WebSocket connection.
@ -32,9 +32,6 @@ class WebSocketRequestHandler(BaseHTTPRequestHandler):
SocketClass = WebSocket SocketClass = WebSocket
def __init__(self, request, client_address, server):
BaseHTTPRequestHandler.__init__(self, request, client_address, server)
def handle_one_request(self): def handle_one_request(self):
"""Extended request handler """Extended request handler
@ -45,7 +42,12 @@ class WebSocketRequestHandler(BaseHTTPRequestHandler):
self._real_do_GET = self.do_GET self._real_do_GET = self.do_GET
self.do_GET = self._websocket_do_GET self.do_GET = self._websocket_do_GET
try: try:
BaseHTTPRequestHandler.handle_one_request(self) # super() only works for new style classes
if issubclass(WebSocketRequestHandlerMixIn, object):
super(WebSocketRequestHandlerMixIn, self).handle_one_request()
else:
# Assume handle_one_request() hasn't been overriden
BaseHTTPRequestHandler.handle_one_request(self)
finally: finally:
self.do_GET = self._real_do_GET self.do_GET = self._real_do_GET
@ -93,5 +95,11 @@ class WebSocketRequestHandler(BaseHTTPRequestHandler):
""" """
pass pass
# Convenient ready made classes
class WebSocketRequestHandler(WebSocketRequestHandlerMixIn,
BaseHTTPRequestHandler):
pass
class WebSocketServer(HTTPServer): class WebSocketServer(HTTPServer):
pass pass

View File

@ -45,7 +45,7 @@ if sys.platform == 'win32':
sys.exit("Windows is not supported at this time") sys.exit("Windows is not supported at this time")
from websockify.websocket import WebSocket, WebSocketWantReadError, WebSocketWantWriteError from websockify.websocket import WebSocket, WebSocketWantReadError, WebSocketWantWriteError
from websockify.websocketserver import WebSocketRequestHandler from websockify.websocketserver import WebSocketRequestHandlerMixIn
class CompatibleWebSocket(WebSocket): class CompatibleWebSocket(WebSocket):
def select_subprotocol(self, protocols): def select_subprotocol(self, protocols):
@ -56,7 +56,7 @@ class CompatibleWebSocket(WebSocket):
return '' return ''
# HTTP handler with WebSocket upgrade support # HTTP handler with WebSocket upgrade support
class WebSockifyRequestHandler(WebSocketRequestHandler, SimpleHTTPRequestHandler): class WebSockifyRequestHandler(WebSocketRequestHandlerMixIn, SimpleHTTPRequestHandler):
""" """
WebSocket Request Handler Class, derived from SimpleHTTPRequestHandler. WebSocket Request Handler Class, derived from SimpleHTTPRequestHandler.
Must be sub-classed with new_websocket_client method definition. Must be sub-classed with new_websocket_client method definition.
@ -99,7 +99,7 @@ class WebSockifyRequestHandler(WebSocketRequestHandler, SimpleHTTPRequestHandler
if self.logger is None: if self.logger is None:
self.logger = WebSockifyServer.get_logger() self.logger = WebSockifyServer.get_logger()
WebSocketRequestHandler.__init__(self, req, addr, server) SimpleHTTPRequestHandler.__init__(self, req, addr, server)
def log_message(self, format, *args): def log_message(self, format, *args):
self.logger.info("%s - - [%s] %s" % (self.address_string(), self.log_date_time_string(), format % args)) self.logger.info("%s - - [%s] %s" % (self.address_string(), self.log_date_time_string(), format % args))
@ -221,7 +221,7 @@ class WebSockifyRequestHandler(WebSocketRequestHandler, SimpleHTTPRequestHandler
self.validate_connection() self.validate_connection()
self.auth_connection() self.auth_connection()
WebSocketRequestHandler.handle_upgrade(self) WebSocketRequestHandlerMixIn.handle_upgrade(self)
def handle_websocket(self): def handle_websocket(self):
# Indicate to server that a Websocket upgrade was done # Indicate to server that a Websocket upgrade was done
@ -306,7 +306,7 @@ class WebSockifyRequestHandler(WebSocketRequestHandler, SimpleHTTPRequestHandler
if self.rec: if self.rec:
self.rec.write("'EOF'];\n") self.rec.write("'EOF'];\n")
self.rec.close() self.rec.close()
WebSocketRequestHandler.finish(self) SimpleHTTPRequestHandler.finish(self)
def handle(self): def handle(self):
# When using run_once, we have a single process, so # When using run_once, we have a single process, so