or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-configuration.mdcookie-management.mdengine-configuration.mdform-handling.mdhttp-caching.mdindex.mdplugin-system.mdrequest-building.mdresponse-handling.mdwebsocket-support.md

websocket-support.mddocs/

0

# WebSocket Support

1

2

Full-duplex WebSocket communication with extensions support, content conversion, and platform-specific optimizations for real-time applications.

3

4

## Capabilities

5

6

### WebSockets Plugin

7

8

Core WebSocket plugin providing client-side WebSocket functionality.

9

10

```kotlin { .api }

11

/**

12

* WebSocket client plugin for full-duplex communication

13

*/

14

object WebSockets : HttpClientPlugin<WebSockets.Config, WebSockets> {

15

override val key: AttributeKey<WebSockets> = AttributeKey("WebSocket")

16

17

/**

18

* WebSocket configuration

19

*/

20

class Config {

21

/** Ping interval in milliseconds (-1 to disable) */

22

var pingInterval: Long = -1L

23

24

/** Maximum frame size in bytes */

25

var maxFrameSize: Long = Long.MAX_VALUE

26

27

/** Content converter for serialization */

28

var contentConverter: WebsocketContentConverter? = null

29

30

/**

31

* Configure WebSocket extensions

32

*/

33

fun extensions(block: WebSocketExtensionsConfig.() -> Unit)

34

}

35

}

36

```

37

38

### WebSocket Connection Functions

39

40

Functions for establishing WebSocket connections with various configuration options.

41

42

```kotlin { .api }

43

/**

44

* Create WebSocket session with request configuration

45

*/

46

suspend fun HttpClient.webSocketSession(

47

block: HttpRequestBuilder.() -> Unit

48

): DefaultClientWebSocketSession

49

50

/**

51

* Create WebSocket session with URL components

52

*/

53

suspend fun HttpClient.webSocketSession(

54

method: HttpMethod = HttpMethod.Get,

55

host: String = "localhost",

56

port: Int = DEFAULT_PORT,

57

path: String = "/",

58

block: HttpRequestBuilder.() -> Unit = {}

59

): DefaultClientWebSocketSession

60

61

/**

62

* Create WebSocket session with URL string

63

*/

64

suspend fun HttpClient.webSocketSession(

65

urlString: String,

66

block: HttpRequestBuilder.() -> Unit = {}

67

): DefaultClientWebSocketSession

68

69

/**

70

* Use WebSocket with session handler

71

*/

72

suspend fun HttpClient.webSocket(

73

request: HttpRequestBuilder.() -> Unit = {},

74

block: suspend DefaultClientWebSocketSession.() -> Unit

75

)

76

77

/**

78

* Use WebSocket with URL and session handler

79

*/

80

suspend fun HttpClient.webSocket(

81

urlString: String,

82

request: HttpRequestBuilder.() -> Unit = {},

83

block: suspend DefaultClientWebSocketSession.() -> Unit

84

)

85

86

/**

87

* Use WebSocket with URL components

88

*/

89

suspend fun HttpClient.webSocket(

90

method: HttpMethod = HttpMethod.Get,

91

host: String = "localhost",

92

port: Int = DEFAULT_PORT,

93

path: String = "/",

94

request: HttpRequestBuilder.() -> Unit = {},

95

block: suspend DefaultClientWebSocketSession.() -> Unit

96

)

97

```

98

99

**Usage Examples:**

100

101

```kotlin

102

import io.ktor.client.plugins.websocket.*

103

import io.ktor.websocket.*

104

105

val client = HttpClient {

106

install(WebSockets) {

107

pingInterval = 20_000 // 20 seconds

108

maxFrameSize = 1024 * 1024 // 1MB

109

}

110

}

111

112

// Simple WebSocket usage

113

client.webSocket("wss://echo.websocket.org") {

114

send("Hello WebSocket!")

115

116

for (frame in incoming) {

117

when (frame) {

118

is Frame.Text -> {

119

val message = frame.readText()

120

println("Received: $message")

121

}

122

is Frame.Binary -> {

123

val data = frame.readBytes()

124

println("Received ${data.size} bytes")

125

}

126

is Frame.Close -> {

127

println("Connection closed")

128

break

129

}

130

else -> {}

131

}

132

}

133

}

134

135

// WebSocket session for manual control

136

val session = client.webSocketSession("wss://api.example.com/ws") {

137

headers["Authorization"] = "Bearer $token"

138

}

139

140

try {

141

session.send("Hello")

142

val frame = session.incoming.receive()

143

// Process frame

144

} finally {

145

session.close()

146

}

147

```

148

149

### WebSocket Session Interface

150

151

Interface for WebSocket communication sessions with frame handling.

152

153

```kotlin { .api }

154

/**

155

* Default client WebSocket session implementation

156

*/

157

interface DefaultClientWebSocketSession : ClientWebSocketSession {

158

/** Incoming frames channel */

159

val incoming: ReceiveChannel<Frame>

160

161

/** Outgoing frames channel */

162

val outgoing: SendChannel<Frame>

163

164

/** WebSocket extensions */

165

val extensions: List<WebSocketExtension<*>>

166

167

/**

168

* Send text frame

169

*/

170

suspend fun send(content: String)

171

172

/**

173

* Send binary frame

174

*/

175

suspend fun send(content: ByteArray)

176

177

/**

178

* Send frame

179

*/

180

suspend fun send(frame: Frame)

181

182

/**

183

* Close WebSocket connection

184

*/

185

suspend fun close(reason: CloseReason = CloseReason(CloseReason.Codes.NORMAL, ""))

186

187

/**

188

* Flush outgoing frames

189

*/

190

fun flush()

191

}

192

```

193

194

**Usage Examples:**

195

196

```kotlin

197

client.webSocket("wss://api.example.com/chat") {

198

// Send different types of content

199

send("Hello, World!") // Text frame

200

send(byteArrayOf(1, 2, 3, 4)) // Binary frame

201

send(Frame.Text("Custom text frame"))

202

send(Frame.Binary(true, byteArrayOf(5, 6, 7, 8)))

203

204

// Handle different frame types

205

for (frame in incoming) {

206

when (frame) {

207

is Frame.Text -> {

208

val text = frame.readText()

209

println("Text: $text")

210

211

// Echo back

212

send("Echo: $text")

213

}

214

is Frame.Binary -> {

215

val bytes = frame.readBytes()

216

println("Binary data: ${bytes.size} bytes")

217

}

218

is Frame.Ping -> {

219

println("Ping received")

220

// Pong is sent automatically

221

}

222

is Frame.Pong -> {

223

println("Pong received")

224

}

225

is Frame.Close -> {

226

val reason = frame.readReason()

227

println("Connection closed: ${reason?.message}")

228

break

229

}

230

}

231

}

232

}

233

```

234

235

### WebSocket Capabilities

236

237

Engine capabilities for WebSocket support and extensions.

238

239

```kotlin { .api }

240

/**

241

* Basic WebSocket support capability

242

*/

243

object WebSocketCapability : HttpClientEngineCapability<Unit>

244

245

/**

246

* WebSocket extensions support capability

247

*/

248

object WebSocketExtensionsCapability : HttpClientEngineCapability<List<WebSocketExtensionConfig>>

249

```

250

251

**Usage Examples:**

252

253

```kotlin

254

val client = HttpClient(CIO)

255

256

// Check WebSocket support

257

if (client.isSupported(WebSocketCapability)) {

258

println("WebSocket is supported by this engine")

259

260

// Use WebSocket functionality

261

client.webSocket("wss://api.example.com/ws") {

262

// WebSocket logic

263

}

264

} else {

265

println("WebSocket not supported")

266

}

267

268

// Check extensions support

269

if (client.isSupported(WebSocketExtensionsCapability)) {

270

println("WebSocket extensions are supported")

271

}

272

```

273

274

### Short Aliases

275

276

Convenient short aliases for WebSocket functions.

277

278

```kotlin { .api }

279

/**

280

* Short alias for webSocket function

281

*/

282

suspend fun HttpClient.ws(

283

urlString: String,

284

request: HttpRequestBuilder.() -> Unit = {},

285

block: suspend DefaultClientWebSocketSession.() -> Unit

286

) = webSocket(urlString, request, block)

287

288

/**

289

* Secure WebSocket connection (wss://)

290

*/

291

suspend fun HttpClient.wss(

292

host: String,

293

port: Int = 443,

294

path: String = "/",

295

request: HttpRequestBuilder.() -> Unit = {},

296

block: suspend DefaultClientWebSocketSession.() -> Unit

297

) = webSocket(HttpMethod.Get, host, port, path, request, block)

298

```

299

300

**Usage Examples:**

301

302

```kotlin

303

// Short alias

304

client.ws("wss://echo.websocket.org") {

305

send("Hello from ws!")

306

val response = (incoming.receive() as Frame.Text).readText()

307

println("Received: $response")

308

}

309

310

// Secure WebSocket with components

311

client.wss("api.example.com", 443, "/websocket") {

312

headers["Authorization"] = "Bearer $token"

313

} {

314

send("Authenticated message")

315

// Handle frames

316

}

317

```

318

319

### Content Conversion

320

321

Support for automatic serialization/deserialization of WebSocket messages.

322

323

```kotlin { .api }

324

/**

325

* WebSocket content converter interface

326

*/

327

interface WebsocketContentConverter {

328

/**

329

* Serialize object to WebSocket frame

330

*/

331

suspend fun serialize(

332

charset: Charset,

333

typeInfo: TypeInfo,

334

value: Any

335

): Frame

336

337

/**

338

* Deserialize WebSocket frame to object

339

*/

340

suspend fun deserialize(

341

charset: Charset,

342

typeInfo: TypeInfo,

343

content: Frame

344

): Any?

345

}

346

347

/**

348

* Send typed object (requires content converter)

349

*/

350

suspend inline fun <reified T> DefaultClientWebSocketSession.sendSerialized(data: T)

351

352

/**

353

* Receive typed object (requires content converter)

354

*/

355

suspend inline fun <reified T> DefaultClientWebSocketSession.receiveDeserialized(): T

356

```

357

358

**Usage Examples:**

359

360

```kotlin

361

import io.ktor.client.plugins.contentnegotiation.*

362

import io.ktor.serialization.kotlinx.json.*

363

import kotlinx.serialization.Serializable

364

365

@Serializable

366

data class ChatMessage(val user: String, val message: String, val timestamp: Long)

367

368

val client = HttpClient {

369

install(WebSockets) {

370

contentConverter = KotlinxWebsocketSerializationConverter(Json)

371

}

372

}

373

374

client.webSocket("wss://chat.example.com/room/123") {

375

// Send typed object

376

val message = ChatMessage("alice", "Hello everyone!", System.currentTimeMillis())

377

sendSerialized(message)

378

379

// Receive typed object

380

val receivedMessage: ChatMessage = receiveDeserialized()

381

println("${receivedMessage.user}: ${receivedMessage.message}")

382

}

383

```

384

385

### Error Handling

386

387

WebSocket-specific exception handling and error patterns.

388

389

```kotlin { .api }

390

/**

391

* Base WebSocket exception class

392

*/

393

open class WebSocketException(message: String) : IllegalStateException(message)

394

395

/**

396

* WebSocket connection failed exception

397

*/

398

class WebSocketConnectionException(message: String, cause: Throwable? = null)

399

: WebSocketException(message)

400

401

/**

402

* WebSocket close codes and reasons

403

*/

404

object CloseReason {

405

object Codes {

406

const val NORMAL = 1000

407

const val GOING_AWAY = 1001

408

const val PROTOCOL_ERROR = 1002

409

const val UNSUPPORTED_DATA = 1003

410

const val NO_STATUS = 1005

411

const val ABNORMAL_CLOSURE = 1006

412

const val INVALID_PAYLOAD = 1007

413

const val POLICY_VIOLATION = 1008

414

const val MESSAGE_TOO_BIG = 1009

415

const val MANDATORY_EXTENSION = 1010

416

const val INTERNAL_ERROR = 1011

417

const val TLS_HANDSHAKE_FAILED = 1015

418

}

419

}

420

421

data class CloseReason(val code: Short, val message: String)

422

```

423

424

**Usage Examples:**

425

426

```kotlin

427

try {

428

client.webSocket("wss://api.example.com/ws") {

429

send("Hello")

430

431

for (frame in incoming) {

432

when (frame) {

433

is Frame.Close -> {

434

val reason = frame.readReason()

435

when (reason?.code) {

436

CloseReason.Codes.NORMAL -> println("Normal close")

437

CloseReason.Codes.GOING_AWAY -> println("Server going away")

438

CloseReason.Codes.PROTOCOL_ERROR -> println("Protocol error")

439

else -> println("Close reason: ${reason?.message}")

440

}

441

break

442

}

443

// Handle other frames

444

else -> {}

445

}

446

}

447

}

448

} catch (e: WebSocketException) {

449

println("WebSocket error: ${e.message}")

450

} catch (e: WebSocketConnectionException) {

451

println("Connection failed: ${e.message}")

452

}

453

454

// Graceful close

455

client.webSocket("wss://api.example.com/ws") {

456

try {

457

// WebSocket communication

458

send("Hello")

459

} finally {

460

// Always close cleanly

461

close(CloseReason(CloseReason.Codes.NORMAL, "Client disconnecting"))

462

}

463

}

464

```