CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-ktor--ktor-client-websockets

Ktor client WebSocket plugin - provides WebSocket support for the Ktor HTTP client on multiple platforms including iOS x64

Pending
Overview
Eval results
Files

websocket-connections.mddocs/

WebSocket Connections

Ktor Client WebSockets provides multiple functions for establishing WebSocket connections with different usage patterns and security options.

Connection Functions

webSocket() - Session with Block

Establishes a WebSocket connection and executes a block with the session, automatically closing the connection afterward:

suspend fun HttpClient.webSocket(
    method: HttpMethod = HttpMethod.Get,
    host: String? = null,
    port: Int? = null,
    path: String? = null,
    request: HttpRequestBuilder.() -> Unit = {},
    block: suspend DefaultClientWebSocketSession.() -> Unit
)

suspend fun HttpClient.webSocket(
    request: HttpRequestBuilder.() -> Unit,
    block: suspend DefaultClientWebSocketSession.() -> Unit
)

suspend fun HttpClient.webSocket(
    urlString: String,
    request: HttpRequestBuilder.() -> Unit = {},
    block: suspend DefaultClientWebSocketSession.() -> Unit
)

Usage:

client.webSocket(
    method = HttpMethod.Get,
    host = "echo.websocket.org",
    port = 80,
    path = "/"
) {
    send("Hello WebSocket!")
    val frame = incoming.receive()
    println("Received: ${frame}")
}
// Connection automatically closed after block completion

URL string variant:

client.webSocket("ws://echo.websocket.org/") {
    send("Hello from URL!")
    val response = incoming.receive()
    println("Response: $response")
}

webSocketSession() - Manual Session Management

Creates a WebSocket session that must be manually managed and closed:

suspend fun HttpClient.webSocketSession(
    method: HttpMethod = HttpMethod.Get,
    host: String? = null,
    port: Int? = null,
    path: String? = null,
    block: HttpRequestBuilder.() -> Unit = {}
): DefaultClientWebSocketSession

suspend fun HttpClient.webSocketSession(
    block: HttpRequestBuilder.() -> Unit
): DefaultClientWebSocketSession

suspend fun HttpClient.webSocketSession(
    urlString: String,
    block: HttpRequestBuilder.() -> Unit = {}
): DefaultClientWebSocketSession

Usage:

val session = client.webSocketSession(
    host = "echo.websocket.org",
    port = 80,
    path = "/"
)

try {
    session.send("Manual session message")
    val frame = session.incoming.receive()
    println("Received: $frame")
} finally {
    session.close()
}

ws() - Short Alias

Convenience alias for webSocket() with identical functionality:

suspend fun HttpClient.ws(
    method: HttpMethod = HttpMethod.Get,
    host: String? = null,
    port: Int? = null,
    path: String? = null,
    request: HttpRequestBuilder.() -> Unit = {},
    block: suspend DefaultClientWebSocketSession.() -> Unit
)

suspend fun HttpClient.ws(
    request: HttpRequestBuilder.() -> Unit,
    block: suspend DefaultClientWebSocketSession.() -> Unit
)

suspend fun HttpClient.ws(
    urlString: String,
    request: HttpRequestBuilder.() -> Unit = {},
    block: suspend DefaultClientWebSocketSession.() -> Unit
)

Usage:

client.ws("ws://echo.websocket.org/") {
    send("Short alias message")
    val frame = incoming.receive()
    println("Response: $frame")
}

wss() - Secure WebSocket Connections

Establishes secure WebSocket connections over TLS/SSL:

suspend fun HttpClient.wss(
    method: HttpMethod = HttpMethod.Get,
    host: String? = null,
    port: Int? = null,
    path: String? = null,
    request: HttpRequestBuilder.() -> Unit = {},
    block: suspend DefaultClientWebSocketSession.() -> Unit
)

suspend fun HttpClient.wss(
    request: HttpRequestBuilder.() -> Unit,
    block: suspend DefaultClientWebSocketSession.() -> Unit
)

suspend fun HttpClient.wss(
    urlString: String,
    request: HttpRequestBuilder.() -> Unit = {},
    block: suspend DefaultClientWebSocketSession.() -> Unit
)

Usage:

client.wss(
    host = "secure.websocket.example.com",
    port = 443,
    path = "/secure-endpoint"
) {
    send("Secure message")
    val frame = incoming.receive()
    println("Secure response: $frame")
}

URL string variant:

client.wss("wss://secure.websocket.example.com/api/v1/socket") {
    send("Secure connection established")
    val response = incoming.receive()
    println("Secure response: $response")
}

Request Configuration

All connection functions accept a request configuration block for customizing the WebSocket handshake:

Headers

client.webSocket("ws://example.com/") {
    headers {
        append("Authorization", "Bearer $token")
        append("X-Custom-Header", "value")
    }
}

URL Parameters

client.webSocket(
    host = "api.example.com",
    path = "/socket"
) {
    url {
        parameters.append("token", authToken)
        parameters.append("room", roomId)
    }
}

Protocol and Port Override

client.webSocket("ws://example.com:8080/socket") {
    url {
        protocol = URLProtocol.WSS // Override to secure
        port = 443 // Override port
    }
}

Connection Examples

Basic Text Communication

client.webSocket("ws://echo.websocket.org/") {
    // Send text frame
    send("Hello WebSocket!")
    
    // Receive and process frames
    for (frame in incoming) {
        when (frame) {
            is Frame.Text -> {
                val text = frame.readText()
                println("Received text: $text")
                if (text == "exit") break
            }
            is Frame.Close -> {
                println("Connection closed: ${frame.readReason()}")
                break
            }
            else -> println("Received frame: $frame")
        }
    }
}

Binary Data Transfer

client.webSocket("ws://example.com/binary") {
    // Send binary frame
    val data = "Binary data".toByteArray()
    send(Frame.Binary(true, data))
    
    // Receive binary frame
    val frame = incoming.receive()
    if (frame is Frame.Binary) {
        val receivedData = frame.data
        println("Received ${receivedData.size} bytes")
    }
}

Authentication with Headers

client.webSocket("ws://secure.example.com/socket") {
    headers {
        append("Authorization", "Bearer $jwt")
        append("X-API-Key", apiKey)
    }
} {
    send("Authenticated connection established")
    
    for (frame in incoming) {
        when (frame) {
            is Frame.Text -> {
                handleMessage(frame.readText())
            }
            is Frame.Close -> break
            else -> { /* Handle other frame types */ }
        }
    }
}

Connection with Custom Timeout

withTimeout(30.seconds) {
    client.webSocket("ws://example.com/socket") {
        timeout {
            requestTimeoutMillis = 15_000
            connectTimeoutMillis = 10_000
        }
    } {
        // WebSocket operations
        send("Message with timeout")
        val response = incoming.receive()
        println("Response: $response")
    }
}

Error Handling

WebSocket connections can fail during handshake or operation:

try {
    client.webSocket("ws://unreliable.example.com/") {
        send("Test message")
        val frame = incoming.receive()
        println("Success: $frame")
    }
} catch (e: WebSocketException) {
    println("WebSocket error: ${e.message}")
} catch (e: ConnectTimeoutException) {
    println("Connection timeout: ${e.message}")
} catch (e: IOException) {
    println("Network error: ${e.message}")
}

Connection Lifecycle

  1. Handshake: HTTP upgrade request sent to server
  2. Protocol Switch: HTTP connection upgraded to WebSocket
  3. Session Active: Bidirectional frame communication
  4. Ping/Pong: Automatic heartbeat (if configured)
  5. Close Handshake: Graceful connection termination
  6. Cleanup: Resources automatically released

Install with Tessl CLI

npx tessl i tessl/maven-io-ktor--ktor-client-websockets

docs

content-serialization.md

index.md

plugin-configuration.md

raw-websocket-operations.md

session-operations.md

websocket-connections.md

tile.json