WebSocket client connection. This class should not be instantiated directly; use the `websocket_connect` function instead.
| 1345 | |
| 1346 | |
| 1347 | class WebSocketClientConnection(simple_httpclient._HTTPConnection): |
| 1348 | """WebSocket client connection. |
| 1349 | |
| 1350 | This class should not be instantiated directly; use the |
| 1351 | `websocket_connect` function instead. |
| 1352 | """ |
| 1353 | |
| 1354 | protocol = None # type: WebSocketProtocol |
| 1355 | |
| 1356 | def __init__( |
| 1357 | self, |
| 1358 | request: httpclient.HTTPRequest, |
| 1359 | on_message_callback: Optional[Callable[[Union[None, str, bytes]], None]] = None, |
| 1360 | compression_options: Optional[Dict[str, Any]] = None, |
| 1361 | ping_interval: Optional[float] = None, |
| 1362 | ping_timeout: Optional[float] = None, |
| 1363 | max_message_size: int = _default_max_message_size, |
| 1364 | subprotocols: Optional[List[str]] = [], |
| 1365 | ) -> None: |
| 1366 | self.connect_future = Future() # type: Future[WebSocketClientConnection] |
| 1367 | self.read_queue = Queue(1) # type: Queue[Union[None, str, bytes]] |
| 1368 | self.key = base64.b64encode(os.urandom(16)) |
| 1369 | self._on_message_callback = on_message_callback |
| 1370 | self.close_code = None # type: Optional[int] |
| 1371 | self.close_reason = None # type: Optional[str] |
| 1372 | self.params = _WebSocketParams( |
| 1373 | ping_interval=ping_interval, |
| 1374 | ping_timeout=ping_timeout, |
| 1375 | max_message_size=max_message_size, |
| 1376 | compression_options=compression_options, |
| 1377 | ) |
| 1378 | |
| 1379 | scheme, sep, rest = request.url.partition(":") |
| 1380 | scheme = {"ws": "http", "wss": "https"}[scheme] |
| 1381 | request.url = scheme + sep + rest |
| 1382 | request.headers.update( |
| 1383 | { |
| 1384 | "Upgrade": "websocket", |
| 1385 | "Connection": "Upgrade", |
| 1386 | "Sec-WebSocket-Key": self.key, |
| 1387 | "Sec-WebSocket-Version": "13", |
| 1388 | } |
| 1389 | ) |
| 1390 | if subprotocols is not None: |
| 1391 | request.headers["Sec-WebSocket-Protocol"] = ",".join(subprotocols) |
| 1392 | if compression_options is not None: |
| 1393 | # Always offer to let the server set our max_wbits (and even though |
| 1394 | # we don't offer it, we will accept a client_no_context_takeover |
| 1395 | # from the server). |
| 1396 | # TODO: set server parameters for deflate extension |
| 1397 | # if requested in self.compression_options. |
| 1398 | request.headers[ |
| 1399 | "Sec-WebSocket-Extensions" |
| 1400 | ] = "permessage-deflate; client_max_window_bits" |
| 1401 | |
| 1402 | # Websocket connection is currently unable to follow redirects |
| 1403 | request.follow_redirects = False |
| 1404 |