websocketserver.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #!/usr/bin/env python
  2. '''
  3. Python WebSocket server base
  4. Copyright 2011 Joel Martin
  5. Copyright 2016-2018 Pierre Ossman
  6. Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
  7. '''
  8. import sys
  9. from http.server import BaseHTTPRequestHandler, HTTPServer
  10. from websockify.websocket import WebSocket, WebSocketWantReadError, WebSocketWantWriteError
  11. class WebSocketRequestHandlerMixIn:
  12. """WebSocket request handler mix-in class
  13. This class modifies and existing request handler to handle
  14. WebSocket requests. The request handler will continue to function
  15. as before, except that WebSocket requests are intercepted and the
  16. methods handle_upgrade() and handle_websocket() are called. The
  17. standard do_GET() will be called for normal requests.
  18. The class instance SocketClass can be overridden with the class to
  19. use for the WebSocket connection.
  20. """
  21. SocketClass = WebSocket
  22. def handle_one_request(self):
  23. """Extended request handler
  24. This is where WebSocketRequestHandler redirects requests to the
  25. new methods. Any sub-classes must call this method in order for
  26. the calls to function.
  27. """
  28. self._real_do_GET = self.do_GET
  29. self.do_GET = self._websocket_do_GET
  30. try:
  31. super().handle_one_request()
  32. finally:
  33. self.do_GET = self._real_do_GET
  34. def _websocket_do_GET(self):
  35. # Checks if it is a websocket request and redirects
  36. self.do_GET = self._real_do_GET
  37. if (self.headers.get('upgrade') and
  38. self.headers.get('upgrade').lower() == 'websocket'):
  39. self.handle_upgrade()
  40. else:
  41. self.do_GET()
  42. def handle_upgrade(self):
  43. """Initial handler for a WebSocket request
  44. This method is called when a WebSocket is requested. By default
  45. it will create a WebSocket object and perform the negotiation.
  46. The WebSocket object will then replace the request object and
  47. handle_websocket() will be called.
  48. """
  49. websocket = self.SocketClass()
  50. try:
  51. websocket.accept(self.request, self.headers)
  52. except Exception:
  53. exc = sys.exc_info()[1]
  54. self.send_error(400, str(exc))
  55. return
  56. self.log_request(101)
  57. self.request = websocket
  58. # Other requests cannot follow Websocket data
  59. self.close_connection = True
  60. self.handle_websocket()
  61. def handle_websocket(self):
  62. """Handle a WebSocket connection.
  63. This is called when the WebSocket is ready to be used. A
  64. sub-class should perform the necessary communication here and
  65. return once done.
  66. """
  67. pass
  68. # Convenient ready made classes
  69. class WebSocketRequestHandler(WebSocketRequestHandlerMixIn,
  70. BaseHTTPRequestHandler):
  71. pass
  72. class WebSocketServer(HTTPServer):
  73. pass