Ktor 3.0.0-rc-1 Help

Migrating from 2.2.x to 3.0.x

This guide provides instructions on how to migrate your Ktor application from the 2.2.x version to 3.0.x.

Ktor Server

ApplicationEngine, ApplicationEnvironment, and Application

Several design changes have been introduced to improve configurability and provide a more defined separation between the ApplicationEngine, ApplicationEnvironment and Application instances.

Before v3.0.0, ApplicationEngine managed ApplicationEnvironment, which in turn managed Application.

In the current design, however, Application is responsible for creating, owning, and initiating both ApplicationEngine and ApplicationEnvironment.

This restructuring comes with the following set of breaking changes:

These changes will impact existing code that relies on the previous model.

Renamed classes

Package

2.x.x

3.0.x

io.ktor:ktor-server-core

ApplicationEngineEnvironmentBuilder

ApplicationEnvironmentBuilder

io.ktor:ktor-server-core

applicationEngineEnvironment

applicationEnvironment

start() and stop() methods are removed from ApplicationEngineEnvironment

With the merge of AplicationEngineEnvironment to ApplicationEnvironment, the start() and stop() methods are now only accessible through ApplicationEngine.

2.x.x

3.0.x

ApplicationEngineEnvironment.start()

ApplicationEngine.start()

ApplicationEngineEnvironment.stop()

ApplicationEngine.stop()

Additionally, in the following table you can see the list of removed properties and their current corresponding ownership:

2.x.x

3.0.x

ApplicationEngineEnvironment.connectors

ApplciationEngine.Configuration.connectors

ApplicationEnvironment.developmentMode

Application.developmentMode

ApplicationEnvironment.monitor

Application.monitor

ApplicationEnvironment.parentCoroutineContext

Application.parentCoroutineContext

ApplicationEnvironment.rootPath

Application.rootPath

The ownership changes can be illustrated through the following example:

import io.ktor.server.application.* import io.ktor.server.cio.* import io.ktor.server.engine.* import org.slf4j.helpers.NOPLogger fun defaultServer(module: Application.() -> Unit) = embeddedServer(CIO, environment = applicationEngineEnvironment { log = NOPLogger.NOP_LOGGER connector { port = 8080 } module(module) } )
import io.ktor.server.application.* import io.ktor.server.cio.* import io.ktor.server.engine.* import org.slf4j.helpers.NOPLogger fun defaultServer(module: Application.() -> Unit) = embeddedServer(CIO, environment = applicationEnvironment { log = NOPLogger.NOP_LOGGER }, configure = { connector { port = 8080 } }, module )

Introduction of ServerConfigBuilder

A new entity, ServerConfigBuilder, has been introduced for configuring server properties and replaces the previous configration mechanism of ApplicationPropertiesBuilder. ServerConfigBuilder is used to build instances of the ServerConfig class, which now holds modules, paths, and environment details previously managed by ApplicationProperties.

Additionally, in the embeddedServer() function, the applicationProperties attribute has been renamed to rootConfig to reflect this new configuration approach.

Package

2.x.x

3.0.x

io.ktor:ktor-server-core

ApplicationProperties

ServerConfig

io.ktor:ktor-server-core

ApplciationPropertiesBuilder

ServerConfigBuilder

Introduction of EmbeddedServer

The class EmbeddedServer is introduced and used to replace ApplicationEngine as a return type of the embeddedServer() function.

For more details about the model change, see issue KTOR-3857 on YouTrack.

TestApplication explicit loading of modules

TestApplication no longer automatically loads modules from a configuration file ( e.g. application.conf). Instead, you must explicitly load your modules within the testApplication function or load the configuration file manually.

Explicit module loading

To explicitly load modules, use the application function within testApplication. This approach allows you to manually specify which modules to load, providing greater control over your test setup.

import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import kotlin.test.* class ApplicationTest { @Test fun testRoot() = testApplication { client.get("/").apply { assertEquals(HttpStatusCode.OK, status) assertEquals("Hello World!", bodyAsText()) } } }
import com.example.plugins.* import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* import io.ktor.server.testing.* import kotlin.test.* class ApplicationTest { @Test fun testRoot() = testApplication { application { configureRouting() } client.get("/").apply { assertEquals(HttpStatusCode.OK, status) assertEquals("Hello World!", bodyAsText()) } } }

Load modules from a configuration file

If you want to load modules from a configuration file, use the environment function to specify the configuration file for your test.

@Test fun testHello() = testApplication { environment { config = ApplicationConfig("application-custom.conf") } }

For more information on configuring the test application, see the Testing section.

CallLogging plugin package has been renamed

The CallLogging plugin package has been renamed due to a typo.

2.x.x

3.0.x

io.ktor.server.plugins.callloging

io.ktor.server.plugins.calllogging

ktor-server-host-common module has been removed

Due to Application requiring knowledge of ApplicationEngine, the contents of ktor-server-host-common module have been merged into ktor-server-core, namely the io.ktor.server.engine package.

Ensure that your dependencies are updated accordingly. In most cases, you can simply remove the ktor-server-host-common dependency.

Locations plugin has been removed

The Locations plugin for the Ktor server has been removed. To create type-safe routing, use the Resources plugin instead. This requires the following changes:

  • Replace the io.ktor:ktor-server-locations artifact with io.ktor:ktor-server-resources.

  • The Resources plugin depends on the Kotlin serialization plugin. To add the serialization plugin, see the kotlinx.serialization setup.

  • Update the plugin import from io.ktor.server.locations.* to io.ktor.server.resources.*.

  • Additionally, import the Resource module from io.ktor.resources.

The following example shows how to implement these changes:

import io.ktor.server.locations.* @Location("/articles") class article(val value: Int) fun Application.module() { install(Locations) routing { get<article> { // Get all articles ... call.respondText("List of articles") } } }
import io.ktor.resources.Resource import io.ktor.server.resources.* @Resource("/articles") class Articles(val value: Int) fun Application.module() { install(Resources) routing { get<Articles> { // Get all articles ... call.respondText("List of articles") } } }

For more information on working with Resources, refer to Type-safe routing.

Session encryption method update

The encryption method offered by the Sessions plugin has been updated to enhance security.

Specifically, the SessionTransportTransformerEncrypt method, which previously derived the MAC from the decrypted session value, now computes it from the encrypted value.

To ensure compatibility with existing sessions, Ktor has introduced the backwardCompatibleRead property. For current configurations, include the property in the constructor of SessionTransportTransformerEncrypt:

install(Sessions) { cookie<UserSession>("user_session") { // ... transform( SessionTransportTransformerEncrypt( secretEncryptKey, // your encrypt key here secretSignKey, // your sign key here backwardCompatibleRead = true ) ) } }

For more information on session encryption in Ktor, see Sign and encrypt session data.

Last modified: 13 September 2024