or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

connection-management.mdevent-system.mdextensions.mdindex.mdlow-level-protocol.md
tile.json

tessl/pypi-wsproto

WebSockets state-machine based protocol implementation

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/wsproto@1.2.x

To install, run

npx @tessl/cli install tessl/pypi-wsproto@1.2.0

index.mddocs/

wsproto

A pure-Python implementation of a WebSocket protocol stack. wsproto is written from the ground up to be embeddable in any program, ensuring WebSocket communication as defined in RFC 6455 and RFC 7692 (compression extensions) regardless of programming paradigm. The library provides a purely in-memory solution defined in terms of data actions and WebSocket frames, without providing parsing, network, or concurrency layers.

Package Information

  • Package Name: wsproto
  • Package Type: pypi
  • Language: Python
  • Installation: pip install wsproto
  • Supported Python: 3.7.0 or higher

Core Imports

from wsproto import WSConnection, ConnectionType

Common event imports:

from wsproto.events import (
    Request, AcceptConnection, RejectConnection, RejectData,
    TextMessage, BytesMessage, CloseConnection,
    Ping, Pong
)

Low-level protocol imports:

from wsproto.connection import Connection, ConnectionState, CLIENT, SERVER
from wsproto.frame_protocol import (
    FrameProtocol, FrameDecoder, MessageDecoder,
    Opcode, CloseReason, Frame, Header, RsvBits, ParseFailed
)
from wsproto.extensions import Extension, PerMessageDeflate, SUPPORTED_EXTENSIONS
from wsproto.handshake import H11Handshake
from wsproto.utilities import (
    ProtocolError, LocalProtocolError, RemoteProtocolError,
    generate_nonce, generate_accept_token, 
    normed_header_dict, split_comma_header
)
from wsproto.typing import Headers

Basic Usage

Client Connection

from wsproto import WSConnection, ConnectionType
from wsproto.events import Request, AcceptConnection, TextMessage

# Create a client connection
ws = WSConnection(ConnectionType.CLIENT)

# Generate handshake request
data_to_send = ws.send(Request(host='echo.websocket.org', target='/'))

# Send data_to_send over your network connection
# ... network sending code ...

# Process received network data
ws.receive_data(received_bytes)

# Handle events
for event in ws.events():
    if isinstance(event, AcceptConnection):
        print("Connection established!")
    elif isinstance(event, TextMessage):
        print(f"Received text: {event.data}")

Server Connection

from wsproto import WSConnection, ConnectionType
from wsproto.events import Request, AcceptConnection

# Create a server connection
ws = WSConnection(ConnectionType.SERVER)

# Process incoming handshake data
ws.receive_data(received_handshake_bytes)

# Handle events
for event in ws.events():
    if isinstance(event, Request):
        # Accept the connection
        data_to_send = ws.send(AcceptConnection())
        # Send data_to_send over network

Architecture

wsproto uses a state-machine based architecture with clear separation of concerns:

  • WSConnection: High-level interface managing handshake and connection state
  • Connection: Low-level WebSocket connection handling frames and messages
  • H11Handshake: HTTP/1.1 handshake protocol implementation
  • FrameProtocol: WebSocket frame parsing and generation
  • Event System: Type-safe event-driven API for all WebSocket operations
  • Extensions: Pluggable extension system (permessage-deflate support included)

This design enables maximum reusability across different network implementations, event loops, and concurrency models while maintaining complete RFC compliance.

Capabilities

Connection Management

Core connection establishment, state management, and lifecycle control for both client and server WebSocket connections.

class WSConnection:
    def __init__(self, connection_type: ConnectionType) -> None: ...
    def send(self, event: Event) -> bytes: ...
    def receive_data(self, data: Optional[bytes]) -> None: ...
    def events(self) -> Generator[Event, None, None]: ...

class ConnectionType(Enum):
    CLIENT = 1
    SERVER = 2

class ConnectionState(Enum):
    CONNECTING = 0
    OPEN = 1
    REMOTE_CLOSING = 2
    LOCAL_CLOSING = 3
    CLOSED = 4
    REJECTING = 5

Connection Management

Event System

Comprehensive event-driven API covering all WebSocket operations including handshake, messages, control frames, and connection lifecycle.

class Event(ABC): ...

class Request(Event):
    host: str
    target: str
    extensions: Union[Sequence[Extension], Sequence[str]] = field(default_factory=list)
    extra_headers: Headers = field(default_factory=list)
    subprotocols: List[str] = field(default_factory=list)

class AcceptConnection(Event):
    subprotocol: Optional[str] = None
    extensions: List[Extension] = field(default_factory=list)
    extra_headers: Headers = field(default_factory=list)

class TextMessage(Event):
    data: str
    frame_finished: bool = True
    message_finished: bool = True

class BytesMessage(Event):
    data: bytes
    frame_finished: bool = True
    message_finished: bool = True

Event System

Extensions

WebSocket extensions support including RFC 7692 permessage-deflate compression with configurable parameters and negotiation.

class Extension:
    name: str
    def enabled(self) -> bool: ...
    def offer(self) -> Union[bool, str]: ...
    def accept(self, offer: str) -> Optional[Union[bool, str]]: ...

class PerMessageDeflate(Extension):
    name = "permessage-deflate"
    def __init__(
        self,
        client_no_context_takeover: bool = False,
        client_max_window_bits: Optional[int] = None,
        server_no_context_takeover: bool = False,
        server_max_window_bits: Optional[int] = None,
    ) -> None: ...

Extensions

Low-Level Protocol

Direct frame protocol access for advanced use cases requiring fine-grained control over WebSocket frame generation and parsing.

class FrameProtocol:
    def __init__(self, client: bool, extensions: List[Extension]) -> None: ...
    def send_data(self, payload: Union[bytes, bytearray, str] = b"", fin: bool = True) -> bytes: ...
    def ping(self, payload: bytes = b"") -> bytes: ...
    def pong(self, payload: bytes = b"") -> bytes: ...
    def close(self, code: Optional[int] = None, reason: Optional[str] = None) -> bytes: ...

class Opcode(IntEnum):
    CONTINUATION = 0x0
    TEXT = 0x1
    BINARY = 0x2
    CLOSE = 0x8
    PING = 0x9
    PONG = 0xA

class CloseReason(IntEnum):
    NORMAL_CLOSURE = 1000
    GOING_AWAY = 1001
    PROTOCOL_ERROR = 1002
    # ... other close codes

Low-Level Protocol

Utilities

Helper functions for WebSocket handshake token generation and header processing.

def generate_nonce() -> bytes:
    """
    Generate a WebSocket handshake nonce.
    
    Creates a random 16-byte value encoded in base64, used for the
    Sec-WebSocket-Key header in client handshake requests.
    
    Returns:
        Base64-encoded random nonce bytes
    """

def generate_accept_token(token: bytes) -> bytes:
    """
    Generate WebSocket accept token for handshake response.
    
    Takes the client's Sec-WebSocket-Key value and generates the
    corresponding Sec-WebSocket-Accept value using SHA-1 and
    the WebSocket GUID as specified in RFC 6455.
    
    Args:
        token: The Sec-WebSocket-Key value from client
        
    Returns:
        Base64-encoded accept token for server response
    """

def normed_header_dict(headers: Union[Headers, H11Headers]) -> Dict[bytes, bytes]:
    """
    Normalize HTTP headers to a dictionary.
    
    Converts header list to dictionary, joining multiple values
    with commas where appropriate.
    
    Args:
        headers: Headers as list of tuples or h11 headers
        
    Returns:
        Dictionary mapping header names to values
    """

def split_comma_header(value: bytes) -> List[str]:
    """
    Split comma-separated header value.
    
    Parses header values that contain comma-separated lists,
    such as extension and subprotocol headers.
    
    Args:
        value: Header value as bytes
        
    Returns:
        List of individual header values
    """

Types

from typing import List, Tuple, Generator, Optional, Union, Sequence, Dict
from dataclasses import dataclass, field
from enum import Enum, IntEnum
from h11._headers import Headers as H11Headers

Headers = List[Tuple[bytes, bytes]]

class ProtocolError(Exception): ...
class LocalProtocolError(ProtocolError): ...
class RemoteProtocolError(ProtocolError):
    def __init__(self, message: str, event_hint: Optional[Event] = None) -> None: ...
    event_hint: Optional[Event]