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

View File

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