Spaces:
Sleeping
Sleeping
| # WebSocket bridge: browser <-> bridge (:8765) <-> MeshCat WS (:7000) | |
| # Compatible with websockets >= 11 (incl. 15.0.1). One-arg handler. | |
| import asyncio | |
| import logging | |
| import websockets | |
| UPSTREAM = "ws://127.0.0.1:7000/" | |
| logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") | |
| async def pump(src, dst, label): | |
| try: | |
| async for msg in src: | |
| await dst.send(msg) | |
| except websockets.ConnectionClosedOK: | |
| logging.info("%s closed cleanly", label) | |
| except websockets.ConnectionClosed as e: | |
| logging.info("%s closed: code=%s reason=%s", label, e.code, e.reason) | |
| except Exception: | |
| logging.exception("%s error", label) | |
| async def handler(client_ws): | |
| # Connect to MeshCat’s WS; disable compression to avoid deflate quirks | |
| async with websockets.connect( | |
| UPSTREAM, | |
| ping_interval=20, | |
| ping_timeout=20, | |
| max_size=None, | |
| compression=None, | |
| ) as upstream_ws: | |
| logging.info("Bridge connected: client <-> %s", UPSTREAM) | |
| # bidirectional forwarding | |
| c2u = asyncio.create_task(pump(client_ws, upstream_ws, "client->upstream")) | |
| u2c = asyncio.create_task(pump(upstream_ws, client_ws, "upstream->client")) | |
| done, pending = await asyncio.wait({c2u, u2c}, return_when=asyncio.FIRST_COMPLETED) | |
| for t in pending: | |
| t.cancel() | |
| async def main(): | |
| async with websockets.serve( | |
| handler, | |
| "127.0.0.1", | |
| 8765, | |
| ping_interval=20, | |
| ping_timeout=20, | |
| max_size=None, | |
| compression=None, | |
| ): | |
| logging.info("WS bridge listening on ws://127.0.0.1:8765/") | |
| await asyncio.Future() # run forever | |
| if __name__ == "__main__": | |
| asyncio.run(main()) | |