Ktor client WebSocket plugin - provides WebSocket support for the Ktor HTTP client on multiple platforms including iOS x64
npx @tessl/cli install tessl/maven-io-ktor--ktor-client-websockets@2.3.0Ktor Client WebSockets is a multiplatform WebSocket client plugin for the Ktor HTTP client. It enables applications to establish and manage WebSocket connections with full bidirectional communication capabilities, automatic ping-pong heartbeat, configurable frame limits, and cross-platform compatibility across JVM, JavaScript, iOS x64, Android, and other Kotlin Multiplatform targets.
implementation("io.ktor:ktor-client-websockets:2.3.13")import io.ktor.client.*
import io.ktor.client.plugins.websocket.*
import io.ktor.websocket.*import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.websocket.*
import io.ktor.websocket.*
// Create client with WebSocket plugin
val client = HttpClient(CIO) {
install(WebSockets) {
pingInterval = 20_000 // 20 seconds
maxFrameSize = 1024 * 1024 // 1MB
}
}
// Connect to WebSocket and exchange messages
client.webSocket(
method = HttpMethod.Get,
host = "ws.postman-echo.com",
port = 443,
path = "/raw"
) {
// Send text frame
send("Hello WebSocket!")
// Receive frame
val frame = incoming.receive()
if (frame is Frame.Text) {
println("Received: ${frame.readText()}")
}
// Close connection
close(CloseReason(CloseReason.Codes.NORMAL, "Goodbye"))
}
client.close()Ktor Client WebSockets is built around several key components:
WebSocket plugin installation and configuration for HttpClient with customizable ping intervals, frame size limits, and content conversion.
fun HttpClientConfig<*>.WebSockets(config: WebSockets.Config.() -> Unit)
class WebSockets internal constructor(
val pingInterval: Long,
val maxFrameSize: Long,
private val extensionsConfig: WebSocketExtensionsConfig,
val contentConverter: WebsocketContentConverter? = null
) {
class Config {
var pingInterval: Long = -1L
var maxFrameSize: Long = Int.MAX_VALUE.toLong()
var contentConverter: WebsocketContentConverter? = null
fun extensions(block: WebSocketExtensionsConfig.() -> Unit)
}
companion object Plugin : HttpClientPlugin<Config, WebSockets>
}Core WebSocket connection establishment and session management functionality with support for different connection patterns and secure connections.
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.webSocketSession(
method: HttpMethod = HttpMethod.Get,
host: String? = null,
port: Int? = null,
path: String? = null,
block: HttpRequestBuilder.() -> Unit = {}
): DefaultClientWebSocketSession
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.wss(
method: HttpMethod = HttpMethod.Get,
host: String? = null,
port: Int? = null,
path: String? = null,
request: HttpRequestBuilder.() -> Unit = {},
block: suspend DefaultClientWebSocketSession.() -> Unit
)Client WebSocket session interfaces and operations for frame communication, session management, and HTTP call context access.
interface ClientWebSocketSession : WebSocketSession {
val call: HttpClientCall
}
class DefaultClientWebSocketSession(
override val call: HttpClientCall,
delegate: DefaultWebSocketSession
) : ClientWebSocketSession, DefaultWebSocketSession by delegate
val DefaultClientWebSocketSession.converter: WebsocketContentConverter?WebSocket content serialization and deserialization functionality using Ktor's content conversion system for automatic object transformation.
suspend fun DefaultClientWebSocketSession.sendSerialized(
data: Any?,
typeInfo: TypeInfo
)
suspend inline fun <reified T> DefaultClientWebSocketSession.sendSerialized(
data: T
)
suspend fun <T> DefaultClientWebSocketSession.receiveDeserialized(
typeInfo: TypeInfo
): T
suspend inline fun <reified T> DefaultClientWebSocketSession.receiveDeserialized(): TCIO engine-specific raw WebSocket operations that bypass automatic ping-pong processing and provide direct frame access.
suspend fun HttpClient.webSocketRawSession(
method: HttpMethod = HttpMethod.Get,
host: String? = null,
port: Int? = null,
path: String? = null,
block: HttpRequestBuilder.() -> Unit = {}
): ClientWebSocketSession
suspend fun HttpClient.webSocketRaw(
method: HttpMethod = HttpMethod.Get,
host: String? = null,
port: Int? = null,
path: String? = null,
request: HttpRequestBuilder.() -> Unit = {},
block: suspend ClientWebSocketSession.() -> Unit
)
suspend fun HttpClient.wsRaw(
method: HttpMethod = HttpMethod.Get,
host: String? = null,
port: Int? = null,
path: String? = null,
request: HttpRequestBuilder.() -> Unit = {},
block: suspend ClientWebSocketSession.() -> Unit
)
suspend fun HttpClient.wssRaw(
method: HttpMethod = HttpMethod.Get,
host: String? = null,
port: Int? = null,
path: String? = null,
request: HttpRequestBuilder.() -> Unit = {},
block: suspend ClientWebSocketSession.() -> Unit
)// Engine Capabilities
object WebSocketCapability : HttpClientEngineCapability<Unit>
object WebSocketExtensionsCapability : HttpClientEngineCapability<Unit>
// Exceptions
class WebSocketException(message: String, cause: Throwable? = null) : IllegalStateException
// WebSocket Frame Types (from ktor-websockets)
enum class FrameType(val controlFrame: Boolean, val opcode: Int) {
TEXT(false, 1),
BINARY(false, 2),
CLOSE(true, 8),
PING(true, 9),
PONG(true, 0xa)
}
sealed class Frame {
class Text(val fin: Boolean, val data: ByteArray) : Frame
class Binary(val fin: Boolean, val data: ByteArray) : Frame
class Close(val reason: CloseReason) : Frame
class Ping(val data: ByteArray) : Frame
class Pong(val data: ByteArray) : Frame
}
data class CloseReason(val code: Short, val message: String) {
enum class Codes(val code: Short) {
NORMAL(1000),
GOING_AWAY(1001),
PROTOCOL_ERROR(1002),
CANNOT_ACCEPT(1003),
NOT_CONSISTENT(1007),
VIOLATED_POLICY(1008),
TOO_BIG(1009),
NO_EXTENSION(1010),
INTERNAL_ERROR(1011),
SERVICE_RESTART(1012),
TRY_AGAIN_LATER(1013)
}
}
// WebSocket Session Interfaces (from ktor-websockets)
interface WebSocketSession : CoroutineScope {
var masking: Boolean
var maxFrameSize: Long
val incoming: ReceiveChannel<Frame>
val outgoing: SendChannel<Frame>
val extensions: List<WebSocketExtension<*>>
suspend fun send(frame: Frame)
suspend fun flush()
}
interface DefaultWebSocketSession : WebSocketSession {
var pingIntervalMillis: Long
var timeoutMillis: Long
val closeReason: Deferred<CloseReason?>
}