Published 14 May 2026
Features
- KTOR-8421 Route.contentType should support multiple ContentType
- KTOR-7961 Add known TDM headers to the HttpHeaders object
- KTOR-9418 Support getAs from the root ApplicationConfig
- KTOR-9559 DNS configuration for the Apache5 client
- KTOR-9554 DNS configuration for OkHttp client engine
- KTOR-9555 Custom SSE heartbeat function
- KTOR-8914 Dependency injection: read annotations in function references
- KTOR-8300 Sessions: Add a way to create a user session shared for all user devices or look up sessions of the same user
- KTOR-9521 Upgrade to Kotlin 2.3.21
- KTOR-9276 Make DynamicProviderConfig.authenticateFunction suspend
- KTOR-9491 Provide parameter validation convenience functions
- KTOR-9506 OpenAPI: Support prefixItems in JsonSchema for tuple type definitions
- KTOR-470 Add an option to not resend the session cookie if the session data wasn't changed.
- KTOR-9355 Deprecate HttpHeaders.AcceptCharset
- KTOR-7659 Make ktor-network compatible with ES modules for nodejs
- KTOR-9350 JS: Make ES2015 the default target for tests
- KTOR-7578 Update Digest authentication implementation according to RFC 7616
Improvements
- KTOR-9503 The JacksonConverter.streamRequestBody property name is confusing
- KTOR-9552 Deprecation notice for io.ktor.server.auth.Principal does not explain what to use instead
- KTOR-7458 Jetty Jakarta: Provide an easy way to disable SNI hostname validation
- KTOR-9354 Websockets: webSocket builder function should return a Route to be describable
- KTOR-9488 Nonce and hex function performance optimizations
Bugfixes
- KTOR-9524 Netty response hangs after connection lost
- KTOR-9542 Netty: The request handler runs on worker event loop instead of call event loop since 3.4.3
- KTOR-9531 Netty server intermittently drops requests after upgrading to 3.4.3
- KTOR-8151 MicrometerMetrics: "MeterFilters configured after a Meter has been registered" warning when a metric is registered before installing the plugin
- KTOR-9411 Darwin throws DarwinHttpRequestException instead of FrameTooBigException
- KTOR-8320 CallLogging: plugin usage in testApplication breaks console standard output
- KTOR-8906 Jackson, with request body streaming on, exhausts Dispatchers.IO
- KTOR-8709 Websockets: Unable to close session with a custom CloseReason
- KTOR-9567 Flaky UnixSockets on Windows: WSAEOPNOTSUPP from bind()
- KTOR-9183 A client call wrapped with
withTimeoutthrows a generic CancellationException instead of TimeoutCancellationException - KTOR-8199 Autoreloading: default watch patterns don't match anything when project path contain spaces
- KTOR-9549 Kotlin/JS: ktor-ktor-client-core.mjs is incompatible with Vite: toRaw naming conflict
- KTOR-9544 Apache: body channel not cancelled when caller scope is cancelled
- KTOR-9546 HttpClient: cancelling ByteReadChannel body does not propagate to engine
- KTOR-455 Content-Disposition additional parameters should be inside quotes
- KTOR-9500 RawSourceChannel returns false positive on awaitContent
- KTOR-646 Netty engine still print annoying exceptions
- KTOR-9527 Curl: Freeze when receiving large responses
- KTOR-9460 Curl: Can't build shared library with Ktor 3.4.2
- KTOR-9483 Curl: backpressure implementation is never used
- KTOR-9545 Curl: body channel not cancelled when caller scope is cancelled
- KTOR-9540 Curl: CancelWebSocket task may cancel a new HTTP request due to easy handle pointer reuse
- KTOR-9539 Curl: WebSocket bearer token refresh fails due to stale native handle reuse
- KTOR-9536 Netty call hang when channel becomes inactive before response is sent
- KTOR-4752 OkHttp: Websockets pinging doesn't work
- KTOR-9409 call.respond performance regression caused by transitive kotlin-reflect:2.3.0
- KTOR-9487 ZSTD decoder fails if the compressed frame is larger than 4096 bytes
- KTOR-8271 MockEngine, HttpTimeout: the virtual clock of kotlinx coroutines isn't respected
- KTOR-6683 Plugin onCallReceive/transformBody is not called for receive()
- KTOR-7416 Jetty, Java: Custom Host header doesn't override the default value
- KTOR-9203 CIOMultipartDataBase: Call thread is blocked when releasing file parts