or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

index.mddocs/

0

# wsproto

1

2

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.

3

4

## Package Information

5

6

- **Package Name**: wsproto

7

- **Package Type**: pypi

8

- **Language**: Python

9

- **Installation**: `pip install wsproto`

10

- **Supported Python**: 3.7.0 or higher

11

12

## Core Imports

13

14

```python

15

from wsproto import WSConnection, ConnectionType

16

```

17

18

Common event imports:

19

20

```python

21

from wsproto.events import (

22

Request, AcceptConnection, RejectConnection, RejectData,

23

TextMessage, BytesMessage, CloseConnection,

24

Ping, Pong

25

)

26

```

27

28

Low-level protocol imports:

29

30

```python

31

from wsproto.connection import Connection, ConnectionState, CLIENT, SERVER

32

from wsproto.frame_protocol import (

33

FrameProtocol, FrameDecoder, MessageDecoder,

34

Opcode, CloseReason, Frame, Header, RsvBits, ParseFailed

35

)

36

from wsproto.extensions import Extension, PerMessageDeflate, SUPPORTED_EXTENSIONS

37

from wsproto.handshake import H11Handshake

38

from wsproto.utilities import (

39

ProtocolError, LocalProtocolError, RemoteProtocolError,

40

generate_nonce, generate_accept_token,

41

normed_header_dict, split_comma_header

42

)

43

from wsproto.typing import Headers

44

```

45

46

## Basic Usage

47

48

### Client Connection

49

50

```python

51

from wsproto import WSConnection, ConnectionType

52

from wsproto.events import Request, AcceptConnection, TextMessage

53

54

# Create a client connection

55

ws = WSConnection(ConnectionType.CLIENT)

56

57

# Generate handshake request

58

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

59

60

# Send data_to_send over your network connection

61

# ... network sending code ...

62

63

# Process received network data

64

ws.receive_data(received_bytes)

65

66

# Handle events

67

for event in ws.events():

68

if isinstance(event, AcceptConnection):

69

print("Connection established!")

70

elif isinstance(event, TextMessage):

71

print(f"Received text: {event.data}")

72

```

73

74

### Server Connection

75

76

```python

77

from wsproto import WSConnection, ConnectionType

78

from wsproto.events import Request, AcceptConnection

79

80

# Create a server connection

81

ws = WSConnection(ConnectionType.SERVER)

82

83

# Process incoming handshake data

84

ws.receive_data(received_handshake_bytes)

85

86

# Handle events

87

for event in ws.events():

88

if isinstance(event, Request):

89

# Accept the connection

90

data_to_send = ws.send(AcceptConnection())

91

# Send data_to_send over network

92

```

93

94

## Architecture

95

96

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

97

98

- **WSConnection**: High-level interface managing handshake and connection state

99

- **Connection**: Low-level WebSocket connection handling frames and messages

100

- **H11Handshake**: HTTP/1.1 handshake protocol implementation

101

- **FrameProtocol**: WebSocket frame parsing and generation

102

- **Event System**: Type-safe event-driven API for all WebSocket operations

103

- **Extensions**: Pluggable extension system (permessage-deflate support included)

104

105

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

106

107

## Capabilities

108

109

### Connection Management

110

111

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

112

113

```python { .api }

114

class WSConnection:

115

def __init__(self, connection_type: ConnectionType) -> None: ...

116

def send(self, event: Event) -> bytes: ...

117

def receive_data(self, data: Optional[bytes]) -> None: ...

118

def events(self) -> Generator[Event, None, None]: ...

119

120

class ConnectionType(Enum):

121

CLIENT = 1

122

SERVER = 2

123

124

class ConnectionState(Enum):

125

CONNECTING = 0

126

OPEN = 1

127

REMOTE_CLOSING = 2

128

LOCAL_CLOSING = 3

129

CLOSED = 4

130

REJECTING = 5

131

```

132

133

[Connection Management](./connection-management.md)

134

135

### Event System

136

137

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

138

139

```python { .api }

140

class Event(ABC): ...

141

142

class Request(Event):

143

host: str

144

target: str

145

extensions: Union[Sequence[Extension], Sequence[str]] = field(default_factory=list)

146

extra_headers: Headers = field(default_factory=list)

147

subprotocols: List[str] = field(default_factory=list)

148

149

class AcceptConnection(Event):

150

subprotocol: Optional[str] = None

151

extensions: List[Extension] = field(default_factory=list)

152

extra_headers: Headers = field(default_factory=list)

153

154

class TextMessage(Event):

155

data: str

156

frame_finished: bool = True

157

message_finished: bool = True

158

159

class BytesMessage(Event):

160

data: bytes

161

frame_finished: bool = True

162

message_finished: bool = True

163

```

164

165

[Event System](./event-system.md)

166

167

### Extensions

168

169

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

170

171

```python { .api }

172

class Extension:

173

name: str

174

def enabled(self) -> bool: ...

175

def offer(self) -> Union[bool, str]: ...

176

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

177

178

class PerMessageDeflate(Extension):

179

name = "permessage-deflate"

180

def __init__(

181

self,

182

client_no_context_takeover: bool = False,

183

client_max_window_bits: Optional[int] = None,

184

server_no_context_takeover: bool = False,

185

server_max_window_bits: Optional[int] = None,

186

) -> None: ...

187

```

188

189

[Extensions](./extensions.md)

190

191

### Low-Level Protocol

192

193

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

194

195

```python { .api }

196

class FrameProtocol:

197

def __init__(self, client: bool, extensions: List[Extension]) -> None: ...

198

def send_data(self, payload: Union[bytes, bytearray, str] = b"", fin: bool = True) -> bytes: ...

199

def ping(self, payload: bytes = b"") -> bytes: ...

200

def pong(self, payload: bytes = b"") -> bytes: ...

201

def close(self, code: Optional[int] = None, reason: Optional[str] = None) -> bytes: ...

202

203

class Opcode(IntEnum):

204

CONTINUATION = 0x0

205

TEXT = 0x1

206

BINARY = 0x2

207

CLOSE = 0x8

208

PING = 0x9

209

PONG = 0xA

210

211

class CloseReason(IntEnum):

212

NORMAL_CLOSURE = 1000

213

GOING_AWAY = 1001

214

PROTOCOL_ERROR = 1002

215

# ... other close codes

216

```

217

218

[Low-Level Protocol](./low-level-protocol.md)

219

220

### Utilities

221

222

Helper functions for WebSocket handshake token generation and header processing.

223

224

```python { .api }

225

def generate_nonce() -> bytes:

226

"""

227

Generate a WebSocket handshake nonce.

228

229

Creates a random 16-byte value encoded in base64, used for the

230

Sec-WebSocket-Key header in client handshake requests.

231

232

Returns:

233

Base64-encoded random nonce bytes

234

"""

235

236

def generate_accept_token(token: bytes) -> bytes:

237

"""

238

Generate WebSocket accept token for handshake response.

239

240

Takes the client's Sec-WebSocket-Key value and generates the

241

corresponding Sec-WebSocket-Accept value using SHA-1 and

242

the WebSocket GUID as specified in RFC 6455.

243

244

Args:

245

token: The Sec-WebSocket-Key value from client

246

247

Returns:

248

Base64-encoded accept token for server response

249

"""

250

251

def normed_header_dict(headers: Union[Headers, H11Headers]) -> Dict[bytes, bytes]:

252

"""

253

Normalize HTTP headers to a dictionary.

254

255

Converts header list to dictionary, joining multiple values

256

with commas where appropriate.

257

258

Args:

259

headers: Headers as list of tuples or h11 headers

260

261

Returns:

262

Dictionary mapping header names to values

263

"""

264

265

def split_comma_header(value: bytes) -> List[str]:

266

"""

267

Split comma-separated header value.

268

269

Parses header values that contain comma-separated lists,

270

such as extension and subprotocol headers.

271

272

Args:

273

value: Header value as bytes

274

275

Returns:

276

List of individual header values

277

"""

278

```

279

280

## Types

281

282

```python { .api }

283

from typing import List, Tuple, Generator, Optional, Union, Sequence, Dict

284

from dataclasses import dataclass, field

285

from enum import Enum, IntEnum

286

from h11._headers import Headers as H11Headers

287

288

Headers = List[Tuple[bytes, bytes]]

289

290

class ProtocolError(Exception): ...

291

class LocalProtocolError(ProtocolError): ...

292

class RemoteProtocolError(ProtocolError):

293

def __init__(self, message: str, event_hint: Optional[Event] = None) -> None: ...

294

event_hint: Optional[Event]

295

```