### Initialize wsproto WebSocket Client Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/basic-usage.md Demonstrates how to instantiate a WSConnection in client mode and initiate a connection request. This setup requires the host and target path to be defined. ```python from wsproto import ConnectionType, WSConnection from wsproto.events import Request ws = WSConnection(ConnectionType.CLIENT) request = Request(host="example.com", target='foo') data = ws.send(request) ``` -------------------------------- ### Install wsproto via pip Source: https://github.com/python-hyper/wsproto/blob/main/README.rst Command to install the wsproto library using the Python package manager. ```console pip install wsproto ``` -------------------------------- ### Initialize Post-Handshake Connection Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/advanced-usage.md Demonstrates how to instantiate a Connection object directly when the WebSocket handshake is performed externally. This is useful for dual-stack setups or custom HTTP handling. ```python connection = Connection(extensions) # Agreed extensions sock.send(connection.send(Message(data=b"Hi"))) connection.receive_data(sock.recv(4096)) for event in connection.events(): # As with WSConnection, only without any handshake events ``` -------------------------------- ### Python wsproto Synchronous WebSocket Client Example Source: https://context7.com/python-hyper/wsproto/llms.txt This complete example demonstrates a synchronous WebSocket client using wsproto. It establishes a TCP connection, performs the WebSocket handshake by sending a 'Request' and processing the 'AcceptConnection' or 'RejectConnection' events. It then sends messages, handles incoming 'TextMessage', 'Ping', and 'CloseConnection' events, and echoes received messages before closing the connection. ```python import socket from wsproto import WSConnection, ConnectionType from wsproto.events import ( AcceptConnection, RejectConnection, TextMessage, BytesMessage, Ping, Pong, CloseConnection, Request, Message ) from wsproto.frame_protocol import CloseReason def websocket_client(host: str, port: int, path: str = "/"): """Complete synchronous WebSocket client.""" # Create TCP connection sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(30.0) sock.connect((host, port)) # Create WebSocket connection ws = WSConnection(ConnectionType.CLIENT) try: # Send handshake request request = Request(host=host, target=path) sock.send(ws.send(request)) # Wait for handshake response data = sock.recv(4096) ws.receive_data(data) connected = False for event in ws.events(): if isinstance(event, AcceptConnection): connected = True print(f"Connected! Subprotocol: {event.subprotocol}") elif isinstance(event, RejectConnection): raise ConnectionError(f"Rejected: {event.status_code}") if not connected: raise ConnectionError("No handshake response") # Send a message sock.send(ws.send(Message(data="Hello, server!"))) # Receive messages while True: data = sock.recv(4096) if not data: ws.receive_data(None) break ws.receive_data(data) for event in ws.events(): if isinstance(event, TextMessage): print(f"Received: {event.data}") if event.message_finished: # Echo back then close sock.send(ws.send(Message(data=f"Got: {event.data}"))) sock.send(ws.send(CloseConnection(code=1000, reason="Done"))) elif isinstance(event, Ping): sock.send(ws.send(event.response())) elif isinstance(event, CloseConnection): sock.send(ws.send(event.response())) return finally: sock.close() # Usage if __name__ == "__main__": websocket_client("echo.websocket.org", 80, "/") ``` -------------------------------- ### wsproto: Test Folder Installation Fix (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet details a packaging fix in wsproto (v0.15.0 and v0.14.1) where the test folder was mistakenly installed as a package named 'test'. This has been corrected to prevent unintended package installations. ```python Bugfix prevent the test folder being installed as a package called test. Stop installing a "test" package on installation. ``` -------------------------------- ### wsproto: Type Hinting and Dataclass Improvements (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet summarizes improvements in type hinting and data structure usage within wsproto. It mentions the switch to dataclass-based events starting from v0.15.0, the addition of type hints throughout the codebase, and the support for PEP 561 via a py.typed file to enable type checking for users. ```python Switch events to be dataclass based, otherwise the API is consistent. Add type hints throughout and support PEP 561 via a py.typed file. This should allow projects that use wsproto to type check their usage of wsproto. Improve Python typing, specifically bytes vs. bytearray. ``` -------------------------------- ### Process Incoming Data with wsproto Source: https://context7.com/python-hyper/wsproto/llms.txt The `receive_data()` method processes incoming network bytes for WebSocket connections. After feeding data, iterate over `events()` to get parsed events. Pass `None` to signal a closed TCP connection. Handles text, binary, ping, pong, and close events. ```python from wsproto import WSConnection, ConnectionType from wsproto.events import TextMessage, BytesMessage, Ping, Pong, CloseConnection ws = WSConnection(ConnectionType.CLIENT) # ... connection established ... # Main receive loop while True: data = sock.recv(4096) if not data: # TCP connection closed - notify wsproto ws.receive_data(None) break # Feed data to wsproto ws.receive_data(data) # Process all parsed events for event in ws.events(): if isinstance(event, TextMessage): print(f"Text message: {event.data}") print(f"Frame finished: {event.frame_finished}") print(f"Message finished: {event.message_finished}") elif isinstance(event, BytesMessage): print(f"Binary message: {len(event.data)} bytes") elif isinstance(event, Ping): # Must respond to pings per RFC 6455 pong_data = ws.send(event.response()) sock.send(pong_data) elif isinstance(event, Pong): print(f"Pong received: {event.payload}") elif isinstance(event, CloseConnection): print(f"Close frame: code={event.code}, reason={event.reason}") # Must send close response close_response = ws.send(event.response()) sock.send(close_response) break ``` -------------------------------- ### Initialize WebSocket Connections Source: https://github.com/python-hyper/wsproto/blob/main/README.rst Demonstrates how to instantiate a WSConnection object for either client or server roles using the wsproto library. ```python from wsproto import WSConnection, ConnectionType from wsproto.events import Request # Client connection ws_client = WSConnection(ConnectionType.CLIENT) ws_client.send(Request(host='echo.websocket.org', target='/')) # Server connection ws_server = WSConnection(ConnectionType.SERVER) ``` -------------------------------- ### Create Server WebSocket Connection with wsproto Source: https://context7.com/python-hyper/wsproto/llms.txt Illustrates setting up a WebSocket server connection using WSConnection. It shows how to handle incoming TCP connections, receive the WebSocket upgrade request, and respond by sending either an AcceptConnection or RejectConnection event. The server must manage the network transport and process the Request event. ```python import socket from wsproto import WSConnection, ConnectionType from wsproto.events import Request, AcceptConnection, RejectConnection, TextMessage # Create server WebSocket connection ws = WSConnection(ConnectionType.SERVER) # Accept incoming TCP connection (assume server socket setup) server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind(("0.0.0.0", 8765)) server.listen(1) client_socket, addr = server.accept() print(f"Client connected: {addr}") # Receive WebSocket upgrade request data = client_socket.recv(4096) ws.receive_data(data) # Process the Request event and accept connection for event in ws.events(): if isinstance(event, Request): print(f"WebSocket request for: {event.target}") print(f"Host: {event.host}") print(f"Subprotocols requested: {event.subprotocols}") # Accept the connection (optionally with subprotocol) accept_data = ws.send(AcceptConnection(subprotocol=None)) client_socket.send(accept_data) # Or reject with custom status and headers: # reject_data = ws.send(RejectConnection(status_code=403, headers=[(b"X-Reason", b"Forbidden")])) ``` -------------------------------- ### Initialize WebSocket Connection and Extensions Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/advanced-usage.md Demonstrates how to perform a client-side extension handshake and initialize a wsproto Connection object. It requires a list of accepted extensions and a list of proposed extensions to configure the connection state. ```python from wsproto import Connection, ConnectionType from wsproto.extensions import client_extensions_handshake, PerMessageDeflate accepted_extensions = [] proposed_extensions = [PerMessageDeflate()] extensions = client_extensions_handshake(accepted_extensions, proposed_extensions) connection = Connection(ConnectionType.CLIENT, extensions=extensions) ``` -------------------------------- ### Initialize wsproto WebSocket Server Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/basic-usage.md Initializes a server-side connection and demonstrates the requirement to explicitly accept or reject incoming connection requests. ```python from wsproto import ConnectionType, WSConnection from wsproto.events import Request ws = WSConnection(ConnectionType.SERVER) for event in ws.events(): if isinstance(event, Request): print('Accepting connection request') sock.send(ws.send(AcceptConnection())) ``` -------------------------------- ### WSConnection - Server Initialization Source: https://context7.com/python-hyper/wsproto/llms.txt Handles incoming WebSocket upgrade requests on the server side. ```APIDOC ## POST /WSConnection (Server Mode) ### Description Processes an incoming WebSocket upgrade request and sends an acceptance or rejection response. ### Method POST ### Endpoint WSConnection(ConnectionType.SERVER) ### Parameters #### Request Body - **subprotocol** (string) - Optional - The subprotocol to negotiate with the client. ### Request Example { "subprotocol": null } ### Response #### Success Response (200) - **bytes** (binary) - The raw bytes to be sent over the network to accept the connection. #### Response Example { "data": "b'HTTP/1.1 101 Switching Protocols...'" } ``` -------------------------------- ### wsproto: Accepting Bytes and State Checking (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet details changes in how wsproto handles input and internal state. It covers accepting bytes alongside strings for the path argument in `initiate_upgrade_connection` and implementing state checks before sending events to prevent invalid operations. ```python Accept bytes alongside string as path argument in initiate_upgrade_connection. Check the state when sending events, raising if the event cannot be sent in the current state. ``` -------------------------------- ### Create Client WebSocket Connection with wsproto Source: https://context7.com/python-hyper/wsproto/llms.txt Demonstrates how to initialize a client WebSocket connection using WSConnection. It covers initiating the handshake by sending a Request event and processing the server's response, including checking for an AcceptConnection event. This requires network I/O handled by a separate library like socket. ```python import socket from wsproto import WSConnection, ConnectionType from wsproto.events import Request, AcceptConnection, TextMessage, CloseConnection # Create client WebSocket connection ws = WSConnection(ConnectionType.CLIENT) # Connect to server via TCP sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(("echo.websocket.org", 80)) # Initiate WebSocket handshake - send Request event handshake_data = ws.send(Request(host="echo.websocket.org", target="/")) sock.send(handshake_data) # Receive and process server response response_data = sock.recv(4096) ws.receive_data(response_data) # Check for AcceptConnection event for event in ws.events(): if isinstance(event, AcceptConnection): print("WebSocket connection established!") print(f"Subprotocol: {event.subprotocol}") print(f"Extensions: {event.extensions}") ``` -------------------------------- ### Initiate WebSocket Upgrade Request Source: https://context7.com/python-hyper/wsproto/llms.txt Shows how to construct and send a WebSocket upgrade request as a client, including custom headers and subprotocols. ```python from wsproto import WSConnection, ConnectionType from wsproto.events import Request ws_client = WSConnection(ConnectionType.CLIENT) request = Request( host="api.example.com", target="/websocket/v2?token=abc123", subprotocols=["graphql-ws", "subscriptions-transport-ws"], extra_headers=[ (b"Authorization", b"Bearer token123"), (b"X-Custom-Header", b"value") ] ) sock.send(ws_client.send(request)) ``` -------------------------------- ### POST /connection/post-handshake Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/advanced-usage.md Demonstrates how to initialize a WebSocket connection manually after the handshake has been performed externally, allowing for custom protocol negotiation. ```APIDOC ## POST /connection/post-handshake ### Description Initializes a `wsproto.Connection` object directly when the WebSocket handshake is handled outside of the library (e.g., in a dual-stack HTTP setup). ### Method POST ### Endpoint /connection/post-handshake ### Request Body - **extensions** (list) - Required - List of agreed-upon WebSocket extensions. ### Request Example { "extensions": ["permessage-deflate"] } ### Response #### Success Response (200) - **connection** (object) - The initialized Connection instance ready to process events. #### Response Example { "status": "connected", "connection_id": "ws-12345" } ``` -------------------------------- ### wsproto: License and Build Environment Updates (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet notes updates to the project's build and licensing information. It includes adding an additional license identifier to `pyproject.toml` and using Python 3.13 for building documentation to align with the ReadTheDocs build environment. ```python Add additional license identifier to pyproject.toml. Use Python 3.13 to build the docs to match ReadTheDocs build environment. ``` -------------------------------- ### Initialize Low-Level WebSocket Connection Source: https://context7.com/python-hyper/wsproto/llms.txt Demonstrates how to use the Connection class for manual frame handling after an external handshake, such as in HTTP/2 environments. It shows how to process events and send responses without relying on the default handshake flow. ```python from wsproto.connection import Connection, ConnectionType from wsproto.events import Message, TextMessage, BytesMessage, Ping, CloseConnection from wsproto.extensions import PerMessageDeflate extensions = [PerMessageDeflate()] connection = Connection( connection_type=ConnectionType.SERVER, extensions=extensions, trailing_data=b"" ) message_bytes = connection.send(Message(data="Hello from HTTP/2 WebSocket")) connection.receive_data(h2_stream_data) for event in connection.events(): if isinstance(event, TextMessage): print(f"Received: {event.data}") response_bytes = connection.send(Message(data=f"Echo: {event.data}")) elif isinstance(event, Ping): pong_bytes = connection.send(event.response()) elif isinstance(event, CloseConnection): close_bytes = connection.send(event.response()) ``` -------------------------------- ### wsproto: Documentation and Typing Enhancements (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet highlights improvements in documentation and Python typing within wsproto v1.3.0. It includes adding documentation for `wsproto.Connection` and refining type checking, particularly concerning `bytes` versus `bytearray`. ```python Add docs for `wsproto.Connection` Improve Python typing, specifically bytes vs. bytearray. ``` -------------------------------- ### Configure WebSocket Server for HTTP/2 Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/advanced-usage.md Shows how to perform extension negotiation for a WebSocket stream within an HTTP/2 context. It uses server_extensions_handshake to agree on extensions before initializing the Connection. ```python from wsproto.connection import Connection, ConnectionType from wsproto.extensions import PerMessageDeflate from wsproto.handshake import server_extensions_handshake # WebSocket request has been received request_extensions: List[str] supported_extensions = [PerMessageDeflate()] accepts = server_extensions_handshake(request_extensions, supported_extensions) if accepts: response_headers.append({"sec-websocket-extensions": accepts}) # Send the response headers connection = Connection(ConnectionType.SERVER, supported_extensions) ``` -------------------------------- ### WSConnection - Client Initialization Source: https://context7.com/python-hyper/wsproto/llms.txt Initializes a WebSocket client connection and performs the handshake process. ```APIDOC ## POST /WSConnection (Client Mode) ### Description Initializes a new WebSocket connection in client mode and sends the initial upgrade request to the server. ### Method POST ### Endpoint WSConnection(ConnectionType.CLIENT) ### Parameters #### Request Body - **host** (string) - Required - The hostname of the WebSocket server. - **target** (string) - Required - The path to connect to on the server. ### Request Example { "host": "echo.websocket.org", "target": "/" } ### Response #### Success Response (200) - **bytes** (binary) - The raw bytes to be sent over the network to initiate the handshake. #### Response Example { "data": "b'GET / HTTP/1.1\\r\\nHost: echo.websocket.org...'" } ``` -------------------------------- ### Python wsproto Server: Handle Incoming WebSocket Request Source: https://context7.com/python-hyper/wsproto/llms.txt This snippet shows how a WebSocket server using wsproto handles an incoming request. It demonstrates receiving data, iterating through events, checking for the 'Request' event, and responding with either an 'AcceptConnection' for a specific subprotocol ('graphql-ws') or a 'RejectConnection' for unsupported subprotocols. It also shows how to send rejection data. ```python from wsproto import WSConnection, ConnectionType from wsproto.events import Request, AcceptConnection, RejectConnection, RejectData # Assume incoming_data and sock are defined elsewhere # ws_server = WSConnection(ConnectionType.SERVER) # ws_server.receive_data(incoming_data) # for event in ws_server.events(): # if isinstance(event, Request): # print(f"Target: {event.target}") # print(f"Host: {event.host}") # print(f"Subprotocols: {event.subprotocols}") # print(f"Extensions: {event.extensions}") # print(f"Extra headers: {event.extra_headers}") # # Validate and accept with chosen subprotocol # if "graphql-ws" in event.subprotocols: # accept = AcceptConnection( # subprotocol="graphql-ws", # extra_headers=[(b"X-Server-Version", b"1.0")] # ) # sock.send(ws_server.send(accept)) # else: # # Reject with custom status and body # reject = RejectConnection( # status_code=400, # headers=[(b"Content-Type", b"application/json")], # has_body=True # ) # sock.send(ws_server.send(reject)) # # Send rejection body # body = RejectData( # data=b'{"error": "Unsupported subprotocol"}', # body_finished=True # ) # sock.send(ws_server.send(body)) ``` -------------------------------- ### Manage WebSocket Connection Closure with wsproto Source: https://context7.com/python-hyper/wsproto/llms.txt Demonstrates how to initiate a connection closure using CloseConnection and how to properly respond to a peer-initiated closure as required by RFC 6455. It includes a list of standard close codes for troubleshooting. ```python from wsproto import WSConnection, ConnectionType from wsproto.events import CloseConnection, Message from wsproto.frame_protocol import CloseReason ws = WSConnection(ConnectionType.CLIENT) # Initiate close with standard codes close_data = ws.send(CloseConnection(code=CloseReason.NORMAL_CLOSURE, reason="Goodbye")) sock.send(close_data) # Handle received close for event in ws.events(): if isinstance(event, CloseConnection): print(f"Peer closing: code={event.code}, reason={event.reason}") response_data = ws.send(event.response()) sock.send(response_data) sock.shutdown(socket.SHUT_WR) sock.close() ``` -------------------------------- ### wsproto: Masking Method Change (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet explains the removal of wsaccel support in wsproto v0.15.0 and the adoption of the aiohttp/@willmcgugan masking method. It notes that wsaccel was unmaintained and the new method offers comparable performance. ```python Drop wsaccel support and utilise the aiohttp/@willmcgugan masking method. wsaccel is unmaintained and this new masking method is almost as quick. ``` -------------------------------- ### wsproto: Dependency and Header Handling (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet covers changes related to dependencies and header handling in wsproto. It includes loosening the h11 requirement, explicitly requiring the Host header in handshakes, and fixing the "Upgrade" header value to match RFC specifications. ```python Loosen the h11 requirement to >= 0.8.1 as wsproto is compatible with 0.9 onwards. Explicitly require Host header in handshake. Fix "Upgrade" header value to match RFC. ``` -------------------------------- ### Exception Handling Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/api.md Documentation for protocol error exceptions raised by wsproto. ```APIDOC ## Exceptions ### LocalProtocolError - **Description**: Raised when a local programming error occurs or an action is requested that violates the WebSocket standard or current state. ### RemoteProtocolError - **Description**: Raised when the remote peer sends data incompatible with the WebSocket standard. - **Parameters**: - **message** (str) - Error description. - **event_hint** (Event | None) - A suggested event to send back to the client. ``` -------------------------------- ### wsproto: Handling Rejection Events (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet shows the introduction of RejectConnection and RejectData events in wsproto v0.13.0. These events allow server connections to reject incoming connections and client connections to emit rejection responses, including an optional response body represented by RejectData. ```python Introduce RejectConnection and RejectData events to be used by a server connection to reject rather than accept a connection or by a client connection to emit the rejection response. The RejectData event represents the rejection response body, if present. ``` -------------------------------- ### Implement WebSocket Keep-Alive with Ping and Pong Source: https://context7.com/python-hyper/wsproto/llms.txt Explains how to use Ping and Pong frames to maintain connection liveness. It covers sending pings, responding to incoming pings with the response() method, and calculating round-trip latency. ```python from wsproto import WSConnection, ConnectionType from wsproto.events import Ping, Pong import time ws = WSConnection(ConnectionType.CLIENT) # Send ping with payload ping_data = ws.send(Ping(payload=b"keepalive-12345")) sock.send(ping_data) # Handle ping/pong in event loop for event in ws.events(): if isinstance(event, Ping): pong_response = ws.send(event.response()) sock.send(pong_response) elif isinstance(event, Pong): print(f"Pong received with payload: {event.payload}") ``` -------------------------------- ### Configure PerMessageDeflate Compression Source: https://context7.com/python-hyper/wsproto/llms.txt Shows how to propose and accept the PerMessageDeflate extension for automatic message compression. This configuration helps optimize bandwidth for large payloads. ```python from wsproto import WSConnection, ConnectionType from wsproto.events import Request, AcceptConnection, Message from wsproto.extensions import PerMessageDeflate # Client: Request compression deflate = PerMessageDeflate(client_no_context_takeover=False, client_max_window_bits=15) ws_client = WSConnection(ConnectionType.CLIENT) request_data = ws_client.send(Request(host="example.com", target="/ws", extensions=[deflate])) sock.send(request_data) # Server: Accept compression server_deflate = PerMessageDeflate(client_max_window_bits=12, server_max_window_bits=12) ws_server = WSConnection(ConnectionType.SERVER) # Messages are automatically compressed/decompressed ws_client.send(Message(data="x" * 10000)) ``` -------------------------------- ### Perform Network I/O with wsproto Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/basic-usage.md Shows how to integrate wsproto with standard Python sockets. Since wsproto does not perform I/O, the output of ws.send() must be transmitted via socket, and received data must be fed back into ws.receive_data(). ```python sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(("example.com", 80)) sock.send(data) # Receiving data data = sock.recv(4096) ws.receive_data(data) ``` -------------------------------- ### Configure WebSocket Client for HTTP/2 Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/advanced-usage.md Initializes the client-side handshake logic for WebSocket extensions when operating over an HTTP/2 connection. ```python from wsproto.connection import Connection, ConnectionType from wsproto.extensions import PerMessageDeflate from wsproto.handshake import client_extensions_handshake ``` -------------------------------- ### wsproto: Python Version Support Evolution (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet tracks the evolution of Python version support in wsproto. It details the dropping of support for older Python versions (e.g., 2.x, 3.5, 3.6, 3.7, 3.8, 3.9) and the addition of support for newer versions (e.g., 3.8, 3.9, 3.10, 3.12, 3.13, 3.14). ```python Drop support for Python 2. Please pin to ~= 0.14.0 if you support Python 2. Drop support for Python 3.5, meaning the minimum supported version is Python 3.6.1. Added support for Python 3.10. Drop support for Python 3.6, meaning the minimum supported version is Python 3.7.0. Added support for Python 3.8 and 3.9. Add support for Python 3.12, 3.13, and 3.14. Drop support for Python 3.7, 3.8, and 3.9. ``` -------------------------------- ### Connection - Low-Level Post-Handshake API Source: https://context7.com/python-hyper/wsproto/llms.txt Demonstrates how to use the `Connection` class for direct WebSocket frame handling after an external handshake, suitable for HTTP/2 or custom implementations. ```APIDOC ## Connection - Low-Level Post-Handshake API ### Description Provides direct WebSocket frame handling after the handshake is complete externally. Use this for HTTP/2 WebSockets or custom handshake implementations. ### Method N/A (Class usage) ### Endpoint N/A ### Parameters N/A ### Request Example ```python from wsproto.connection import Connection, ConnectionType from wsproto.events import Message, TextMessage, BytesMessage, Ping, CloseConnection from wsproto.extensions import PerMessageDeflate # Create connection after external handshake (e.g., HTTP/2) # Pass agreed-upon extensions from handshake negotiation extensions = [PerMessageDeflate()] # Extensions agreed during HTTP/2 handshake connection = Connection( connection_type=ConnectionType.SERVER, extensions=extensions, trailing_data=b"" ) # Send messages message_bytes = connection.send(Message(data="Hello from HTTP/2 WebSocket")) # Wrap in HTTP/2 DATA frame and send via h2 # Receive data from HTTP/2 stream connection.receive_data(h2_stream_data) # Process events (same as WSConnection but no handshake events) for event in connection.events(): if isinstance(event, TextMessage): print(f"Received: {event.data}") response_bytes = connection.send(Message(data=f"Echo: {event.data}")) # Send via HTTP/2 elif isinstance(event, Ping): pong_bytes = connection.send(event.response()) # Send via HTTP/2 elif isinstance(event, CloseConnection): close_bytes = connection.send(event.response()) # Send via HTTP/2 and close stream ``` ### Response N/A (Handles events and generates bytes for sending) ``` -------------------------------- ### Implement Synchronous WebSocket Echo Server Source: https://context7.com/python-hyper/wsproto/llms.txt This snippet demonstrates a complete synchronous WebSocket server using standard Python sockets. It handles the initial handshake, processes incoming text and binary messages, responds to pings, and manages the closing handshake. ```python import socket from wsproto import WSConnection, ConnectionType from wsproto.events import ( Request, AcceptConnection, TextMessage, BytesMessage, Ping, CloseConnection, Message ) from wsproto.frame_protocol import CloseReason def websocket_server(host: str, port: int): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind((host, port)) server.listen(5) print(f"Server listening on {host}:{port}") try: while True: client_sock, addr = server.accept() handle_client(client_sock) except KeyboardInterrupt: print("Shutting down...") finally: server.close() def handle_client(sock: socket.socket): ws = WSConnection(ConnectionType.SERVER) try: while True: data = sock.recv(4096) if not data: ws.receive_data(None) break ws.receive_data(data) out_data = b"" for event in ws.events(): if isinstance(event, Request): out_data += ws.send(AcceptConnection()) elif isinstance(event, TextMessage): out_data += ws.send(Message(data=event.data[::-1])) elif isinstance(event, BytesMessage): out_data += ws.send(Message(data=event.data)) elif isinstance(event, Ping): out_data += ws.send(event.response()) elif isinstance(event, CloseConnection): out_data += ws.send(event.response()) sock.send(out_data) return if out_data: sock.send(out_data) finally: sock.close() if __name__ == "__main__": websocket_server("127.0.0.1", 8765) ``` -------------------------------- ### Respond to WebSocket Ping Frames in Python Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/basic-usage.md Illustrates how to handle incoming Ping frames from a remote WebSocket endpoint using wsproto. It shows how to send a Pong response using the Ping.response() method. Both client and server must reply to ping events. ```python if isinstance(event, Ping): sock.send(ws.send(event.response())) ``` -------------------------------- ### wsproto: Update Connection Event Handling (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet demonstrates the API changes in wsproto v0.13.0, where event handling for connection management was updated. It shows how to send events like AcceptConnection, Message, CloseConnection, Ping, and Pong using the new `send` method, replacing older methods like `accept`, `send_data`, and `close`. ```python connection.accept(subprotocol=subprotocol) -> connection.send(AcceptConnection(subprotocol=subprotocol)) connection.send_data(data) -> connection.send(Message(payload=payload)) connection.close(code) -> connection.send(CloseConnection(code=code)) connection.ping() -> connection.send(Ping()) connection.pong() -> connection.send(Pong()) ``` -------------------------------- ### wsproto: Dependency and Protocol Version Updates (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet details dependency requirement changes and protocol version handling in wsproto v1.3.0. It includes requiring `h11>=0.16`, fixing the "Upgrade" header value, and adding the "Switching Protocols" reason to handshake responses. ```python Require h11>=0.16 dependency. Fix "Upgrade" header value to match RFC. Add reason "Switching Protocols" to handshake response. ``` -------------------------------- ### Handle WebSocket Closing Handshake in Python Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/basic-usage.md Demonstrates how to properly close a WebSocket connection using wsproto. It shows how to send a CloseConnection event and respond to incoming close frames. Both client and server must reply to close events. ```python if isinstance(event, CloseConnection): sock.send(ws.send(event.response())) ``` -------------------------------- ### wsproto: Bug Fixes and Minor Improvements (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet lists various bug fixes and minor improvements across wsproto releases. It includes fixes for close frame payloads, Host header encoding, handling multiple Sec-WebSocket headers, and preventing invalid window bit sizes. It also mentions linting, styling, and packaging improvements. ```python Bugfix: When a close frame with status NO_STATUS_RCVD is sent, send an empty payload. Bugfix: Changing both encoding and decoding of the Host, from ascii to idna. Bugfix: Support multiple Sec-WebSocket-Extensions and Sec-WebSocket-Protocol headers. Prevent invalid window bit sizes. Various linting, styling, and packaging improvements. ``` -------------------------------- ### Send WebSocket Events using wsproto send() Source: https://context7.com/python-hyper/wsproto/llms.txt Shows how to use the `send()` method of WSConnection to generate network bytes for various WebSocket events. This includes sending text and binary messages, handling large messages with fragmentation, sending ping frames, and initiating a connection close handshake. The generated bytes must be transmitted over the network. ```python from wsproto import WSConnection, ConnectionType from wsproto.events import Request, Message, TextMessage, BytesMessage, Ping, CloseConnection ws = WSConnection(ConnectionType.CLIENT) # Send text message text_bytes = ws.send(Message(data="Hello, WebSocket!")) sock.send(text_bytes) # Send binary message binary_bytes = ws.send(Message(data=b"\x00\x01\x02\x03")) sock.send(binary_bytes) # Send message in fragments (for large messages) ws.send(Message(data="First part...", message_finished=False)) ws.send(Message(data="...second part...", message_finished=False)) ws.send(Message(data="...final part", message_finished=True)) # Send ping with optional payload ping_bytes = ws.send(Ping(payload=b"heartbeat")) sock.send(ping_bytes) # Close connection with code and reason close_bytes = ws.send(CloseConnection(code=1000, reason="Normal closure")) sock.send(close_bytes) ``` -------------------------------- ### wsproto: Sending Bytes Directly (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet highlights the change in wsproto v0.13.0 where the `send` method now directly returns the bytes to be sent, replacing the previous `bytes_to_send` method. It also notes that responses to Ping and Close messages must now be sent via `send`, and the Ping and CloseConnection events gain a `response` method. ```python Switch from a ``bytes_to_send`` method to the ``send`` method returning the bytes to send directly. Responses to Ping and Close messages must now be sent (via ``send``), with the ``Ping`` and ``CloseConnection`` events gaining a ``response`` method. ``` -------------------------------- ### Extension Management Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/api.md Details on accessing and managing supported WebSocket extensions. ```APIDOC ## wsproto.extensions.Extension ### Description Base class and registry for WebSocket extensions. ### SUPPORTED_EXTENSIONS - **Type**: Dictionary - **Description**: Maps extension names (e.g., 'permessage-deflate') to their respective implementation classes. ``` -------------------------------- ### Protocol Errors - LocalProtocolError and RemoteProtocolError Source: https://context7.com/python-hyper/wsproto/llms.txt Explains how to handle `LocalProtocolError` for programming mistakes and `RemoteProtocolError` for peer violations to ensure robust WebSocket communication. ```APIDOC ## Protocol Errors - LocalProtocolError and RemoteProtocolError ### Description Handles `LocalProtocolError` for local programming errors and `RemoteProtocolError` for protocol violations by the remote peer to implement robust error recovery. ### Method N/A (Exception handling) ### Endpoint N/A ### Parameters N/A ### Request Example ```python from wsproto import WSConnection, ConnectionType from wsproto.events import Message, CloseConnection, Request, AcceptConnection from wsproto.utilities import LocalProtocolError, RemoteProtocolError from wsproto.frame_protocol import CloseReason ws = WSConnection(ConnectionType.CLIENT) # LocalProtocolError - your code did something wrong try: # Can't send message before connection is established ws.send(Message(data="premature message")) except LocalProtocolError as e: print(f"Local error: {e}") # Fix your code - don't send messages before handshake # RemoteProtocolError - peer violated protocol try: # Peer sent invalid data ws.receive_data(b"invalid websocket data") list(ws.events()) except RemoteProtocolError as e: print(f"Remote protocol error: {e}") # event_hint suggests how to respond if e.event_hint is not None: # Send suggested response (usually RejectConnection or CloseConnection) error_response = ws.send(e.event_hint) sock.send(error_response) # Robust server event loop with error handling def handle_connection_safely(ws, sock): try: while True: data = sock.recv(4096) if not data: ws.receive_data(None) break ws.receive_data(data) for event in ws.events(): # ... handle events ... pass except RemoteProtocolError as e: print(f"Client protocol error: {e}") if e.event_hint: sock.send(ws.send(e.event_hint)) except LocalProtocolError as e: print(f"Server bug: {e}") sock.send(ws.send(CloseConnection(code=CloseReason.INTERNAL_ERROR))) finally: sock.close() ``` ### Response N/A (Handles exceptions) ``` -------------------------------- ### ConnectionType Enum Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/api.md An enumeration of connection types for wsproto. ```APIDOC ## class wsproto.ConnectionType ### Description An enumeration of connection types. ### Values * CLIENT * SERVER ``` -------------------------------- ### Request Event - WebSocket Upgrade Request Source: https://context7.com/python-hyper/wsproto/llms.txt Details the `Request` event, used by clients to initiate WebSocket connections and by servers to respond with `AcceptConnection` or `RejectConnection`. ```APIDOC ## Request Event - WebSocket Upgrade Request ### Description Represents a WebSocket upgrade request. Clients send it to initiate connections; servers receive it and must respond with `AcceptConnection` or `RejectConnection`. ### Method N/A (Event handling) ### Endpoint N/A ### Parameters N/A ### Request Example ```python from wsproto import WSConnection, ConnectionType from wsproto.events import Request, AcceptConnection, RejectConnection, RejectData # Client: Create and send request ws_client = WSConnection(ConnectionType.CLIENT) request = Request( host="api.example.com", target="/websocket/v2?token=abc123", subprotocols=["graphql-ws", "subscriptions-transport-ws"], extra_headers=[ (b"Authorization", b"Bearer token123"), (b"X-Custom-Header", b"value") ] ) sock.send(ws_client.send(request)) ``` ### Response N/A (Server would respond with `AcceptConnection` or `RejectConnection` based on this event) ``` -------------------------------- ### wsproto: Type Hinting Fixes (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet mentions bug fixes related to type hints in wsproto, specifically addressing badly formatted hints and minor issues identified through type checking in v0.14.0. ```python Bugfix badly formatted type hints. Bugfix minor issues identified by type checking. ``` -------------------------------- ### AcceptConnection Event in wsproto Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/api.md Represents the acceptance of a WebSocket upgrade request. This event is used by both clients receiving a server acceptance and servers accepting a client's upgrade request. It can include accepted subprotocols and extra headers. ```python class wsproto.events.AcceptConnection(subprotocol: [str](https://docs.python.org/3/library/stdtypes.html#str) | [None](https://docs.python.org/3/library/constants.html#None) = None, extensions: [list](https://docs.python.org/3/library/stdtypes.html#list)[[Extension](#wsproto.extensions.Extension)] = , extra_headers: Headers = ) The acceptance of a Websocket upgrade request. This event is fired when a CLIENT receives an acceptance response from a server. It is also used to accept an upgrade request when acting as a SERVER. Fields: #### extra_headers Any additional (non websocket related) headers present in the acceptance response. #### subprotocol The accepted subprotocol to use. ``` -------------------------------- ### wsproto: Support for HTTP/2 WebSockets (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet describes the addition of HTTP/2 WebSocket support in wsproto v0.14.0. It notes that this feature requires a separate HTTP/2 parser (like hyper-h2) and introduces a breaking change by renaming `handshake_extensions`. ```python Support HTTP/2 WebSockets. This requires a HTTP/2 parser (not included), with hyper-h2 recommended. It renames ``handshake_extensions`` and hence is a breaking change. ``` -------------------------------- ### wsproto: Error Handling Updates (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet details the error handling changes in wsproto v0.13.0. It explains the switch from returning Fail events to raising RemoteProtocolError for protocol-level issues and from ValueError to LocalProtocolError for state-incompatible actions. It also notes the addition of event_hint to RemoteProtocolErrors. ```python Switch from Fail events being returned to raising ``RemoteProtocolError``. Switch from ValueError`s to LocalProtocolError`s being raised when an action is taken that is incompatible with the connection state or websocket standard. Add an event_hint to RemoteProtocolErrors to hint at how to respond to issues. ``` -------------------------------- ### wsproto: Event Structure Changes (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet illustrates the renaming of event structures in wsproto v0.13.0. It maps the old event names to their new equivalents, such as ConnectionRequested to Request, ConnectionEstablished to AcceptConnection, and DataReceived to Message. This change aims to provide a more consistent event-driven API. ```python ConnectionRequested -> Request ConnectionEstablished -> AcceptConnection ConnectionClosed -> CloseConnection DataReceived -> Message TextMessage -> TextMessage BytesReceived -> BytesMessage PingReceived -> Ping PongReceived -> Pong ``` -------------------------------- ### wsproto: Clarifying Subprotocol Type (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet addresses a bug fix in wsproto v0.14.0 related to subprotocol types, clarifying that it should be a string (`str`) rather than bytes (`bytes`). ```python Bugfix clarify subprotocol type as str not bytes. ``` -------------------------------- ### Handle Protocol Errors Source: https://context7.com/python-hyper/wsproto/llms.txt Explains how to catch and respond to LocalProtocolError and RemoteProtocolError. It provides patterns for robust error recovery and safe connection termination. ```python from wsproto import WSConnection, ConnectionType from wsproto.events import Message, CloseConnection from wsproto.utilities import LocalProtocolError, RemoteProtocolError from wsproto.frame_protocol import CloseReason ws = WSConnection(ConnectionType.CLIENT) try: ws.send(Message(data="premature message")) except LocalProtocolError as e: print(f"Local error: {e}") try: ws.receive_data(b"invalid websocket data") list(ws.events()) except RemoteProtocolError as e: print(f"Remote protocol error: {e}") if e.event_hint is not None: error_response = ws.send(e.event_hint) def handle_connection_safely(ws, sock): try: while True: data = sock.recv(4096) if not data: ws.receive_data(None) break ws.receive_data(data) for event in ws.events(): pass except RemoteProtocolError as e: print(f"Client protocol error: {e}") if e.event_hint: sock.send(ws.send(e.event_hint)) except LocalProtocolError as e: print(f"Server bug: {e}") sock.send(ws.send(CloseConnection(code=CloseReason.INTERNAL_ERROR))) finally: sock.close() ``` -------------------------------- ### Connection Class Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/api.md A low-level WebSocket connection object that wraps HTTP and WebSocket frame protocols. ```APIDOC ## class wsproto.Connection ### Description A low-level WebSocket connection object. This wraps two other protocol objects, an HTTP/1.1 protocol object used to do the initial HTTP upgrade handshake and a WebSocket frame protocol object used to exchange messages and other control frames. ### Methods #### __init__(connection_type: ConnectionType, extensions: list[Extension] | None = None, trailing_data: bytes = b'') Constructor. * **Parameters:** * **connection_type** (ConnectionType) – Whether this object is on the client- or server-side of a connection. To initialise as a client pass `CLIENT` otherwise pass `SERVER`. * **extensions** (list[Extension] | None) – The proposed extensions. * **trailing_data** (bytes) – Data that has been received, but not yet processed. #### events() -> Generator[Event, None, None] Return a generator that provides any events that have been generated by protocol activity. * **Returns:** generator of Event subclasses #### receive_data(data: bytes | None) Pass some received data to the connection for handling. * **Parameters:** * **data** (bytes) – The data received from the remote peer on the network. ``` -------------------------------- ### Process WebSocket Data Source: https://github.com/python-hyper/wsproto/blob/main/README.rst Shows how to send outgoing data generated by the state machine and process incoming byte strings into events. ```python # Send outgoing data some_socket.send(ws.bytes_to_send()) # Receive incoming data ws.receive_data(some_byte_string_of_data) ``` -------------------------------- ### Send WebSocket Response Data Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst Demonstrates how to generate bytes to send over a WebSocket connection using the wsproto library. It utilizes the connection object to process an event response. ```python bytes_to_send = connection.send(event.response()) ``` -------------------------------- ### Ping and Pong Control Frames Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/api.md Managing WebSocket Ping and Pong control frames for connection health. ```APIDOC ## Ping and Pong Events ### Description Events for handling Ping/Pong control frames. Applications must manually respond to Pings with a Pong. ### Methods - **Ping.response()**: Returns a Pong event object to be sent back to the peer. ### Response Example ```python if isinstance(event, wsproto.events.Ping): pong = event.response() # Send pong frame back ``` ``` -------------------------------- ### Extension Handshake Functions Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/api.md Functions for negotiating WebSocket extensions during the handshake. ```APIDOC ## Extension Handshake Functions ### Function: wsproto.handshake.client_extensions_handshake Negotiates extensions from the client's perspective. - **Parameters:** - `accepted` (Iterable[str]): Accepted extensions. - `supported` (Sequence[wsproto.extensions.Extension]): Supported extensions. - **Returns:** List of negotiated `wsproto.extensions.Extension`. ### Function: wsproto.handshake.server_extensions_handshake Negotiates extensions from the server's perspective. - **Parameters:** - `requested` (Iterable[str]): Requested extensions. - `supported` (list[wsproto.extensions.Extension]): Supported extensions. - **Returns:** Bytes for the header value or None if no extensions are agreed upon. ``` -------------------------------- ### wsproto: BytesMessage Type Hint Fix (Python) Source: https://github.com/python-hyper/wsproto/blob/main/CHANGELOG.rst This snippet addresses a type hint correction in wsproto v1.3.2, allowing `BytesMessage` to accept `bytes` again, in addition to `bytearray`. ```python Fix type hints to allow BytesMessage to accept bytes again, as well as bytearray. ``` -------------------------------- ### Handle WebSocket Events Source: https://github.com/python-hyper/wsproto/blob/main/docs/source/basic-usage.md Iterates through events generated by the connection instance to handle various WebSocket states such as connection acceptance, pings, and incoming messages. ```python for event in ws.events(): if isinstance(event, AcceptConnection): print('Connection established') elif isinstance(event, RejectConnection): print('Connection rejected') elif isinstance(event, CloseConnection): print('Connection closed: code={} reason={}'.format(event.code, event.reason)) sock.send(ws.send(event.response())) elif isinstance(event, Ping): print('Received Ping frame with payload {}'.format(event.payload)) sock.send(ws.send(event.response())) elif isinstance(event, TextMessage): print('Received TEXT data: {}'.format(event.data)) elif isinstance(event, BytesMessage): print('Received BINARY data: {}'.format(event.data)) ```