Ktor 1.3 Release

Posted on by

Ktor 1.3 was released recently, and we’re happy to share the details with you in this blog post.

Ktor consists of two parts: the server engine and a flexible asynchronous HTTP client. The current release focuses mainly on the HTTP client. Here you can find the complete changelog for this release.

The client is a multiplatform library that supports JVM, JS, Android, and iOS and is now often used in cross-platform mobile applications. Our main goal for the next releases is to make the server engine multiplatform, too.

The other areas we’re going to work on are:

Improving integration with the kotlinx.serialization library.

Supporting CIO (coroutines-based I/O client engine) on Kotlin/Native to make it a default multiplatform engine used in HttpClient.

If you currently use Ktor, either server or HttpClient, or have tried it at some point before, please take part in the following survey:

We’d be really grateful if you could share your experience with us!

Now let’s dive into the details of what Ktor 1.3 release brings.

HttpClient

Introducing HttpStatement

In the previous Ktor versions, you needed to explicitly close the HttpResponse . However, that was often a source of confusion. We’ve found a lot of cases where someone had forgotten to close the HttpResponse , even in simple examples, and got memory leaks because of it. To improve this situation we introduce the incompatible change in Ktor 1.3: HttpResponse no longer implements the Closeable interface. Thus the 1.3.0 Ktor release is not backwards compatible with the previous version Ktor 1.2.X.

HttpResponse is in-memory by default; and there is no need to close it anymore:

fun main(): Unit = runBlocking { val client = HttpClient() val url = "http://kotlinlang.org/" val response = client.get(url) val text = response.readText() println(text) // no longer need to 'close' the response }

If you need to handle streaming or big responses, use the new HttpStatement class. HttpStatement doesn’t perform any network requests until you explicitly call the execute method:

val statement = client.request("$TEST_SERVER/content/stream") // ... statement.execute { response: HttpResponse -> // working with the response }

For instance, you can read the data by chunks:

client.get(url).execute { response -> val channel = response.receive() while (!channel.isClosedForRead) { val packet = channel.readRemaining(size) println(packet.readText()) } }

Configuring Proxy

The HttpClient adds experimental support for proxy. If you need to send requests under proxy, you can configure its address in the corresponding parameters:

HttpClient { engine { proxy = ProxyBuilder.http("http://proxy-host:3128") } }

Note that because of the platform restrictions it’s only supported for JVM and Native targets (except WatchOS) and isn’t supported for JavaScript. More details on how to configure it for different platforms can be found here.

Using NSURLSession for iOS engine

The iOS engine now provides a way to configure NSURLSession:

HttpClient(Ios) { engine { configureSession { networkServiceType = NSURLNetworkServiceTypeBackground } } }

NSURLSession is a default API to interact with HTTP / HTTPS protocols on iOS, so now you can use it to tweak all the iOS-related settings.

Working with JSON improved

The following changes are supported both on HttpClient and server, so far in an experimental state.

Simplified collections serialization in JSON

In the previous Ktor versions, you needed to register auxiliary types for serializing collections. Now this process is simplified: JsonFeature handles collection types without additional configuration. And all the related functions like setMapper , setListMapper , register are now deprecated.

There is no need to register List<User> in JsonFeature anymore:

install(JsonFeature) // ... val list = client.get<List>("https://example/json/users")

The same applies when working with JSON on a server, you can specify the collection types with the expected generic arguments when receiving the content:

install(ContentNegotiation) { register(ContentType.Application.Json, SerializationConverter()) } routing { post("/entity") { val receivedList = call.receive<List>() // process the list } }

kotlinx.serialization DSL

Ktor now supports a way to construct a JSON body using the kotlinx.serialization DSL:

client.post("http://localhost:9090") { contentType(ContentType.Application.Json) body = json { "key1" to 123 "map" to json { "key2" to "abc" } } }

To use it on a client, install JsonFeature and add the ktor-client-serialization dependency. On the server, use the SerializationConverter.

Migration Steps

To migrate your Ktor application to the new version, you’ll need to:

Update all your usages of HttpResponse : simply remove the close calls, and use HttpStatement when needed.

: simply remove the calls, and use when needed. Update the imports. The kotlinx.io dependency has been removed, so you’ll need to replace imports in the following way: import kotlinx.io. -> import io.ktor.utils.io. import kotlinx.coroutines.io. -> import io.ktor.utils.io.

dependency has been removed, so you’ll need to replace imports in the following way:

Note that there’s no binary compatibility with 1.2.x, so if you use any external Ktor features you’ll need to recompile them against the latest version. Also, make sure that you’re using 5.4.1+ Gradle metadata version.

Thank you for reading this and don’t forget to take the survey!