or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-io.mdauthentication.mdhttp-client-server.mdindex.mdnetworking.mdtemplates.mdtesting.mdutilities.mdweb-framework.mdwebsocket.md

websocket.mddocs/

0

# WebSocket Support

1

2

Full WebSocket protocol implementation for real-time, bidirectional communication between client and server. Supports both server-side handlers and client connections.

3

4

## Capabilities

5

6

### WebSocket Handler

7

8

Server-side WebSocket handler for processing incoming WebSocket connections, messages, and managing connection lifecycle.

9

10

```python { .api }

11

class WebSocketHandler(tornado.web.RequestHandler):

12

"""WebSocket request handler for server-side connections."""

13

14

def open(self, *args, **kwargs):

15

"""

16

Called when WebSocket connection is opened.

17

18

Args:

19

*args: URL path arguments

20

**kwargs: URL keyword arguments

21

"""

22

23

def on_message(self, message):

24

"""

25

Called when message is received from client.

26

27

Args:

28

message: Message content (str or bytes)

29

"""

30

31

def on_close(self):

32

"""Called when WebSocket connection is closed."""

33

34

def write_message(self, message, binary: bool = False):

35

"""

36

Send message to client.

37

38

Args:

39

message: Message to send (str or bytes)

40

binary: Whether message is binary

41

42

Raises:

43

WebSocketClosedError: If connection is closed

44

"""

45

46

def close(self, code: int = None, reason: str = None):

47

"""

48

Close WebSocket connection.

49

50

Args:

51

code: Close status code

52

reason: Close reason string

53

"""

54

55

def check_origin(self, origin: str) -> bool:

56

"""

57

Check if request origin is allowed.

58

59

Args:

60

origin: Request origin header

61

62

Returns:

63

True if origin is allowed, False otherwise

64

"""

65

66

def get_compression_options(self):

67

"""Get WebSocket compression options."""

68

69

def set_nodelay(self, value: bool):

70

"""Enable/disable Nagle's algorithm."""

71

72

def ping(self, data: bytes = b"") -> Future:

73

"""

74

Send ping frame to client.

75

76

Args:

77

data: Ping payload data

78

79

Returns:

80

Future that resolves when pong is received

81

"""

82

83

def on_pong(self, data: bytes):

84

"""

85

Called when pong frame is received.

86

87

Args:

88

data: Pong payload data

89

"""

90

```

91

92

### WebSocket Client

93

94

Client-side WebSocket connection for connecting to WebSocket servers and managing client connections.

95

96

```python { .api }

97

def websocket_connect(url: str, callback=None, connect_timeout: float = None, on_message_callback=None, compression_options=None, ping_interval: float = None, ping_timeout: float = None, max_message_size: int = None, subprotocols=None) -> Future:

98

"""

99

Connect to WebSocket server.

100

101

Args:

102

url: WebSocket URL (ws:// or wss://)

103

callback: Callback function (if not using async/await)

104

connect_timeout: Connection timeout in seconds

105

on_message_callback: Callback for incoming messages

106

compression_options: Compression configuration

107

ping_interval: Ping interval in seconds

108

ping_timeout: Ping timeout in seconds

109

max_message_size: Maximum message size in bytes

110

subprotocols: List of supported subprotocols

111

112

Returns:

113

Future resolving to WebSocketClientConnection

114

115

Usage:

116

conn = await websocket_connect("ws://example.com/websocket")

117

await conn.write_message("Hello")

118

msg = await conn.read_message()

119

conn.close()

120

"""

121

122

class WebSocketClientConnection:

123

"""Client-side WebSocket connection."""

124

125

def write_message(self, message, binary: bool = False) -> Future:

126

"""

127

Send message to server.

128

129

Args:

130

message: Message to send (str or bytes)

131

binary: Whether message is binary

132

133

Returns:

134

Future that resolves when message is sent

135

"""

136

137

def read_message(self, callback=None) -> Future:

138

"""

139

Read next message from server.

140

141

Args:

142

callback: Callback function (if not using async/await)

143

144

Returns:

145

Future resolving to message string/bytes or None if closed

146

"""

147

148

def close(self, code: int = None, reason: str = None):

149

"""

150

Close WebSocket connection.

151

152

Args:

153

code: Close status code

154

reason: Close reason string

155

"""

156

157

def ping(self, data: bytes = b"") -> Future:

158

"""

159

Send ping frame to server.

160

161

Args:

162

data: Ping payload data

163

164

Returns:

165

Future that resolves when pong is received

166

"""

167

168

@property

169

def protocol(self) -> WebSocketProtocol:

170

"""Get WebSocket protocol handler."""

171

```

172

173

### WebSocket Protocol

174

175

Low-level WebSocket protocol implementation handling frame parsing, masking, and protocol compliance.

176

177

```python { .api }

178

class WebSocketProtocol:

179

"""Abstract WebSocket protocol handler."""

180

181

def __init__(self, handler, mask_outgoing: bool = False, compression_options=None):

182

"""

183

Initialize WebSocket protocol.

184

185

Args:

186

handler: WebSocket handler object

187

mask_outgoing: Whether to mask outgoing frames

188

compression_options: Compression configuration

189

"""

190

191

def accept_connection(self, handler):

192

"""Accept WebSocket connection."""

193

194

def write_message(self, message, binary: bool = False, locked: bool = True):

195

"""Write WebSocket message."""

196

197

def read_message(self, callback):

198

"""Read WebSocket message."""

199

200

def close(self, code: int = None, reason: str = None):

201

"""Close WebSocket connection."""

202

203

def ping(self, data: bytes) -> Future:

204

"""Send ping frame."""

205

206

def pong(self, data: bytes):

207

"""Send pong frame."""

208

209

class WebSocketProtocol13(WebSocketProtocol):

210

"""WebSocket protocol version 13 implementation."""

211

212

def __init__(self, handler, mask_outgoing: bool = False, compression_options=None):

213

"""Initialize WebSocket protocol v13."""

214

215

def compute_accept_value(self, key: str) -> str:

216

"""Compute WebSocket accept value from key."""

217

218

def challenge_response(self, challenge: str) -> str:

219

"""Generate challenge response for client."""

220

```

221

222

### WebSocket Utilities

223

224

Utility functions for WebSocket protocol handling, frame processing, and connection management.

225

226

```python { .api }

227

def websocket_connect(url: str, **kwargs):

228

"""Create WebSocket client connection."""

229

230

def encode_username_password(username: str, password: str) -> str:

231

"""Encode credentials for WebSocket authentication."""

232

233

class WebSocketMask:

234

"""WebSocket frame masking utilities."""

235

236

@staticmethod

237

def mask(mask: bytes, data: bytes) -> bytes:

238

"""Apply WebSocket mask to data."""

239

```

240

241

## WebSocket Usage Examples

242

243

### Basic WebSocket Server

244

245

```python

246

import tornado.ioloop

247

import tornado.web

248

import tornado.websocket

249

250

class EchoWebSocket(tornado.websocket.WebSocketHandler):

251

def open(self):

252

print("WebSocket opened")

253

254

def on_message(self, message):

255

print(f"Received: {message}")

256

self.write_message(f"Echo: {message}")

257

258

def on_close(self):

259

print("WebSocket closed")

260

261

def check_origin(self, origin):

262

# Allow connections from any origin

263

return True

264

265

app = tornado.web.Application([

266

(r"/websocket", EchoWebSocket),

267

])

268

269

if __name__ == "__main__":

270

app.listen(8888)

271

print("WebSocket server started on ws://localhost:8888/websocket")

272

tornado.ioloop.IOLoop.current().start()

273

```

274

275

### WebSocket Client

276

277

```python

278

import asyncio

279

import tornado.websocket

280

281

async def websocket_client():

282

# Connect to WebSocket server

283

conn = await tornado.websocket.websocket_connect("ws://localhost:8888/websocket")

284

285

try:

286

# Send message

287

await conn.write_message("Hello WebSocket!")

288

289

# Read response

290

msg = await conn.read_message()

291

print(f"Received: {msg}")

292

293

finally:

294

# Close connection

295

conn.close()

296

297

if __name__ == "__main__":

298

asyncio.run(websocket_client())

299

```

300

301

### Chat Room WebSocket Server

302

303

```python

304

import tornado.ioloop

305

import tornado.web

306

import tornado.websocket

307

import json

308

309

class ChatWebSocket(tornado.websocket.WebSocketHandler):

310

clients = set()

311

312

def open(self):

313

print("Client connected")

314

ChatWebSocket.clients.add(self)

315

316

def on_message(self, message):

317

try:

318

data = json.loads(message)

319

# Broadcast message to all connected clients

320

for client in ChatWebSocket.clients:

321

if client != self: # Don't send back to sender

322

client.write_message(json.dumps({

323

'user': data.get('user', 'Anonymous'),

324

'message': data.get('message', ''),

325

'type': 'message'

326

}))

327

except json.JSONDecodeError:

328

self.write_message(json.dumps({

329

'error': 'Invalid JSON format',

330

'type': 'error'

331

}))

332

333

def on_close(self):

334

print("Client disconnected")

335

ChatWebSocket.clients.discard(self)

336

337

def check_origin(self, origin):

338

return True

339

340

app = tornado.web.Application([

341

(r"/chat", ChatWebSocket),

342

])

343

```

344

345

## Types

346

347

```python { .api }

348

# WebSocket message type

349

WebSocketMessage = Union[str, bytes, None]

350

351

# Close code type

352

WebSocketCloseCode = int

353

354

# Compression options type

355

CompressionOptions = Dict[str, Any]

356

357

# Subprotocols type

358

SubProtocols = List[str]

359

360

# WebSocket handler type

361

WebSocketHandlerType = Type[WebSocketHandler]

362

```

363

364

## Constants

365

366

```python { .api }

367

# WebSocket close codes

368

WS_CLOSE_NORMAL = 1000

369

WS_CLOSE_GOING_AWAY = 1001

370

WS_CLOSE_PROTOCOL_ERROR = 1002

371

WS_CLOSE_UNSUPPORTED_DATA = 1003

372

WS_CLOSE_NO_STATUS = 1005

373

WS_CLOSE_ABNORMAL = 1006

374

WS_CLOSE_INVALID_DATA = 1007

375

WS_CLOSE_POLICY_VIOLATION = 1008

376

WS_CLOSE_MESSAGE_TOO_BIG = 1009

377

WS_CLOSE_MISSING_EXTENSION = 1010

378

WS_CLOSE_INTERNAL_ERROR = 1011

379

380

# WebSocket opcodes

381

WS_OPCODE_CONTINUATION = 0x0

382

WS_OPCODE_TEXT = 0x1

383

WS_OPCODE_BINARY = 0x2

384

WS_OPCODE_CLOSE = 0x8

385

WS_OPCODE_PING = 0x9

386

WS_OPCODE_PONG = 0xa

387

```

388

389

## Exceptions

390

391

```python { .api }

392

class WebSocketError(Exception):

393

"""Base exception for WebSocket errors."""

394

395

class WebSocketClosedError(WebSocketError):

396

"""Exception raised when connection is closed."""

397

398

def __init__(self, real_error=None):

399

"""

400

Initialize WebSocket closed error.

401

402

Args:

403

real_error: Underlying error that caused closure

404

"""

405

```