Ktor 1.3が最近リリースされましたので、このブログ投稿でその詳細をお伝えします。
Ktorはサーバーエンジンとフレキシブルな非同期HTTPクライアントの2つの部分から構成されています。 今回のリリースでは、主にHTTPクライアントに注力しています。 このリリースの完全な変更ログはこちらで確認できます。
クライアントはJVM、JS、Android、iOSに対応したマルチプラットフォームなライブラリであり、クロスプラットフォームモバイルアプリケーションでよく使用されています。 次のリリースでは、サーバーエンジンもマルチプラットフォーム対応にすることをメインゴールにしています。
それ以外の項目としては、以下を計画しています。
- kotlinx.serializationライブラリとの統合の改善。
- CIO(コルーチンベースのI/Oクライアントエンジン)をKotlin/Native上でサポートを実現し、HttpClientで使用されるデフォルトのマルチプラットフォームエンジンにします。
現在Ktor(ServerかHttpClientのいずれか)をお使いの方、または以前お試しになったことのある方は、以下のアンケートへのご協力をお願いします。
アンケートに参加する
あなたの体験を教えていただければ幸いです。
それではKtor 1.3のリリースで提供されるものを詳しくご紹介します。
HttpClient
HttpStatementのご紹介
Ktorの旧バージョンでは、HttpResponse
を明示的にcloseする必要がありました。 しかし、これはしばしば混乱の元となっていました。 私たちは単純なサンプルでさえも、HttpResponse
のclose漏れが原因でメモリリークが発生する事例を多数目の当たりにしてきました。 この状況を改善するため、Ktor 1.3では互換性のない変更を行いました。HttpResponse
は今後、Closeable
インターフェースを実装しません。 そのため、1.3.0 Ktorのリリースは旧バージョンのKtor 1.2.Xとは後方互換性がありません。
HttpResponse
がデフォルトでメモリ内に格納されるようになったため、もうcloseする必要はありません。
fun main(): Unit = runBlocking {
val client = HttpClient()
val url = "http://kotlinlang.org/"
val response = client.get<HttpResponse>(url)
val text = response.readText()
println(text)
// no longer need to 'close' the response
}
ストリーミングや大きなレスポンスを処理したい場合は新しいHttpStatement
クラスを使用してください。 HttpStatement
は、明示的にexecute
メソッドが呼び出されない限りネットワーク要求を実行しません。
val statement = client.request<HttpStatement>("$TEST_SERVER/content/stream")
// ...
statement.execute { response: HttpResponse ->
// working with the response
}
例えば、データをチャンク単位で読み込むことができます。
client.get<HttpStatement>(url).execute { response ->
val channel = response.receive<ByteReadChannel>()
while (!channel.isClosedForRead) {
val packet = channel.readRemaining(size)
println(packet.readText())
}
}
プロキシの構成
HttpClient
がexperimental supportとしてプロキシに対応しました。 プロキシ経由でリクエストを送信したい場合、対応するパラメータでプロキシのアドレスを設定できます。
HttpClient {
engine {
proxy = ProxyBuilder.http("http://proxy-host:3128")
}
}
ただし、プラットフォーム上の制約のため、JVMとNativeのターゲット(WatchOSを除く)のみに対応しており、JavaScriptには対応していませんのでご注意ください。 各種プラットフォームでのプロキシの構成方法に関する詳細は、こちらをご覧ください。
iOSエンジンでのNSURLSession
の利用
iOSエンジンでNSURLSessionを構成するオプションが提供されるようになりました。
HttpClient(Ios) {
engine {
configureSession {
networkServiceType = NSURLNetworkServiceTypeBackground
}
}
}
NSURLSession
はiOSでHTTP / HTTPSプロトコルを処理するデフォルトのAPIですので、これを使ってiOSに関するすべての設定を微調整することができます。
JSON関連の処理に対する改善
以下の変更はHttpClientとServerの両方でサポートされていますが、現在はexperimental扱いです。
JSONでコレクションのシリアル化を単純化
Ktorの旧バージョンでは、コレクションをシリアル化する際に補助型を登録する必要がありました。 今回のリリースではこの手続きが単純化され、JsonFeature
が追加設定なしでコレクション型を処理するようになりました。 また、setMapper
、setListMapper
、register
などの関連する関数はすべて非推奨になりました。
もう、JsonFeature
にList<User>
を登録する必要はありません。
install(JsonFeature)
// ...
val list = client.get<List<User>>("https://example/json/users")
同じことはJSONをサーバー上で処理する場合にも当てはまります。コンテンツを受信する際に、必要な汎用引数を使ってコレクション型を指定できます。
install(ContentNegotiation) {
register(ContentType.Application.Json, SerializationConverter())
}
routing {
post("/entity") {
val receivedList = call.receive<List<MyEntity>>()
// process the list
}
}
kotlinx.serialization DSL
Ktorがkotlinx.serialization
DSLを使ってJSONのbodyを構築できるようになりました。
client.post<String>("http://localhost:9090") {
contentType(ContentType.Application.Json)
body = json {
"key1" to 123
"map" to json {
"key2" to "abc"
}
}
}
クライアントでこれを使用するには、JsonFeatureをインストールしてからktor-client-serializationの依存関係を追加してください。 サーバーではSerializationConverterを使用してください。
移行手順
Ktorアプリケーションを新バージョンに移行するには、以下の手順を実行する必要があります。
HttpResponse
の使用箇所をすべて更新します(単純にclose
の呼び出しを削除し、必要に応じてHttpStatement
を使用します)。- import文を更新します。
kotlinx.io
の依存物が削除されたため、import文を次のように置換する必要があります。 import kotlinx.io.
->import io.ktor.utils.io.
import kotlinx.coroutines.io.
->import io.ktor.utils.io.
1.2.xとはバイナリ互換ではないため、外部のKtorの機能を使用する場合はそれらを最新バージョンに対してコンパイルしなおす必要があります。 また、5.4.1以降のGradleメタデータバージョンを使用していることを確認してください。
最後までお読みいただき、ありがとうございました。また、アンケートへのご協力もお願いします!