1.6.x から 2.0.x へのマイグレーション
このガイドでは、Ktorアプリケーションを1.6.xバージョンから2.0.xバージョンへ移行する方法について説明します。
Ktorサーバー
サーバーコードは 'io.ktor.server.*' パッケージに移動されました
サーバーAPIとクライアントAPIを統一し、より明確に区別するため、サーバーコードはio.ktor.server.*パッケージに移動されました (KTOR-2865)。 これは、以下に示すように、アプリケーションの依存関係とインポートを更新する必要があることを意味します。
依存関係
| サブシステム | 1.6.x | 2.0.0 |
|---|---|---|
| Locations | io.ktor:ktor-locations | io.ktor:ktor-server-locations |
| Webjars | io.ktor:ktor-webjars | io.ktor:ktor-server-webjars |
| AutoHeadResponse | io.ktor:ktor-server-core | io.ktor:ktor-server-auto-head-response |
| StatusPages | io.ktor:ktor-server-core | io.ktor:ktor-server-status-pages |
| CallId | io.ktor:ktor-server-core | io.ktor:ktor-server-call-id |
| DoubleReceive | io.ktor:ktor-server-core | io.ktor:ktor-server-double-receive |
| HTML DSL | io.ktor:ktor-html-builder | io.ktor:ktor-server-html-builder |
| FreeMarker | io.ktor:ktor-freemarker | io.ktor:ktor-server-freemarker |
| Velocity | io.ktor:ktor-velocity | io.ktor:ktor-server-velocity |
| Mustache | io.ktor:ktor-mustache | io.ktor:ktor-server-mustache |
| Thymeleaf | io.ktor:ktor-thymeleaf | io.ktor:ktor-server-thymeleaf |
| Pebble | io.ktor:ktor-pebble | io.ktor:ktor-server-pebble |
| kotlinx.serialization | io.ktor:ktor-serialization | io.ktor:ktor-server-content-negotiation, io.ktor:ktor-serialization-kotlinx-json |
| Gson | io.ktor:ktor-gson | io.ktor:ktor-server-content-negotiation, io.ktor:ktor-serialization-gson |
| Jackson | io.ktor:ktor-jackson | io.ktor:ktor-server-content-negotiation, io.ktor:ktor-serialization-jackson |
| Authentication | io.ktor:ktor-auth | io.ktor:ktor-server-auth |
| JWT authentication | io.ktor:ktor-auth-jwt | io.ktor:ktor-server-auth-jwt |
| LDAP authentication | io.ktor:ktor-auth-ldap | io.ktor:ktor-server-auth-ldap |
| DataConversion | io.ktor:ktor-server-core | io.ktor:ktor-server-data-conversion |
| DefaultHeaders | io.ktor:ktor-server-core | io.ktor:ktor-server-default-headers |
| Compression | io.ktor:ktor-server-core | io.ktor:ktor-server-compression |
| CachingHeaders | io.ktor:ktor-server-core | io.ktor:ktor-server-caching-headers |
| ConditionalHeaders | io.ktor:ktor-server-core | io.ktor:ktor-server-conditional-headers |
| CORS | io.ktor:ktor-server-core | io.ktor:ktor-server-cors |
| Forwarded headers | io.ktor:ktor-server-core | io.ktor:ktor-server-forwarded-header |
| HSTS | io.ktor:ktor-server-core | io.ktor:ktor-server-hsts |
| HttpsRedirect | io.ktor:ktor-server-core | io.ktor:ktor-server-http-redirect |
| PartialContent | io.ktor:ktor-server-core | io.ktor:ktor-server-partial-content |
| WebSockets | io.ktor:ktor-websockets | io.ktor:ktor-server-websockets |
| CallLogging | io.ktor:ktor-server-core | io.ktor:ktor-server-call-logging |
| Micrometer metric | io.ktor:ktor-metrics-micrometer | io.ktor:ktor-server-metrics-micrometer |
| Dropwizard metrics | io.ktor:ktor-metrics | io.ktor:ktor-server-metrics |
| Sessions | io.ktor:ktor-server-core | io.ktor:ktor-server-sessions |
すべてのプラグインを一度に追加するには、
io.ktor:ktor-serverアーティファクトを使用できます。
インポート
| サブシステム | 1.6.x | 2.0.0 |
|---|---|---|
| Application | import io.ktor.application.* | import io.ktor.server.application.* |
| Configuration | import io.ktor.config.* | import io.ktor.server.config.* |
| Routing | import io.ktor.routing.* | import io.ktor.server.routing.* |
| AutoHeadResponse | import io.ktor.features.* | import io.ktor.server.plugins.autohead.* |
| StatusPages | import io.ktor.features.* | import io.ktor.server.plugins.statuspages.* |
| CallId | import io.ktor.features.* | import io.ktor.server.plugins.callid.* |
| DoubleReceive | import io.ktor.features.* | import io.ktor.server.plugins.doublereceive.* |
| Requests | import io.ktor.request.* | import io.ktor.server.request.* |
| Responses | import io.ktor.response.* | import io.ktor.server.response.* |
| Plugins | import io.ktor.features.* | import io.ktor.server.plugins.* |
| Locations | import io.ktor.locations.* | import io.ktor.server.locations.* |
| Static content | import io.ktor.http.content.* | import io.ktor.server.http.content.* |
| HTML DSL | import io.ktor.html.* | import io.ktor.server.html.* |
| FreeMarker | import io.ktor.freemarker.* | import io.ktor.server.freemarker.* |
| Velocity | import io.ktor.velocity.* | import io.ktor.server.velocity.* |
| Mustache | import io.ktor.mustache.* | import io.ktor.server.mustache.* |
| Thymeleaf | import io.ktor.thymeleaf.* | import io.ktor.server.thymeleaf.* |
| Pebble | import io.ktor.pebble.* | import io.ktor.server.pebble.* |
| ContentNegotiation | import io.ktor.features.* | import io.ktor.server.plugins.contentnegotiation.* |
| kotlinx.serialization | import io.ktor.serialization.* | import io.ktor.serialization.kotlinx.json.* |
| Gson | import io.ktor.gson.* | import io.ktor.serialization.gson.* |
| Jackson | import io.ktor.jackson.* | import io.ktor.serialization.jackson.* |
| Authentication | import io.ktor.auth.* | import io.ktor.server.auth.* |
| JWT authentication | import io.ktor.auth.jwt.* | import io.ktor.server.auth.jwt.* |
| LDAP authentication | import io.ktor.auth.ldap.* | import io.ktor.server.auth.ldap.* |
| Sessions | import io.ktor.sessions.* | import io.ktor.server.sessions.* |
| DefaultHeaders | import io.ktor.features.* | import io.ktor.server.plugins.defaultheaders.* |
| Compression | import io.ktor.features.* | import io.ktor.server.plugins.compression.* |
| CachingHeaders | import io.ktor.features.* | import io.ktor.server.plugins.cachingheaders.* |
| ConditionalHeaders | import io.ktor.features.* | import io.ktor.server.plugins.conditionalheaders.* |
| CORS | import io.ktor.features.* | import io.ktor.server.plugins.cors.* |
| Forwarded headers | import io.ktor.features.* | import io.ktor.server.plugins.forwardedheaders.* |
| HSTS | import io.ktor.features.* | import io.ktor.server.plugins.hsts.* |
| HttpsRedirect | import io.ktor.features.* | import io.ktor.server.plugins.httpsredirect.* |
| PartialContent | import io.ktor.features.* | import io.ktor.server.plugins.partialcontent.* |
| WebSockets | import io.ktor.websocket.* | import io.ktor.server.websocket.* |
| CallLogging | import io.ktor.features.* | import io.ktor.server.plugins.callloging.* |
| Micrometer metric | import io.ktor.metrics.micrometer.* | import io.ktor.server.metrics.micrometer.* |
| Dropwizard metrics | import io.ktor.metrics.dropwizard.* | import io.ktor.server.metrics.dropwizard.* |
WebSocketsコードは 'websockets' パッケージに移動されました
WebSocketsコードはhttp-cioからwebsocketsパッケージに移動されました。これにより、インポートを以下のように更新する必要があります。
| 1.6.x | 2.0.0 |
|---|---|
import io.ktor.http.cio.websocket.* | import io.ktor.websocket.* |
この変更はクライアントにも影響することに注意してください。
FeatureはPluginに名称変更されました
Ktor 2.0.0では、Feature はリクエスト/レスポンスパイプラインをインターセプトする機能をより適切に記述するため、Plugin (プラグイン) に名称変更されました (KTOR-2326)。 これはKtor API全体に影響を与え、以下に説明するようにアプリケーションの更新が必要です。
インポート
任意のプラグインをインストールするには、インポートの更新が必要であり、サーバーコードをio.ktor.server.*パッケージに移動することにも依存します。
| 1.6.x | 2.0.0 |
|---|---|
import io.ktor.features.* | import io.ktor.server.plugins.* |
カスタムプラグイン
FeatureからPluginへの名称変更により、カスタムプラグインに関連するAPIに以下の変更が導入されます。
ApplicationFeatureインターフェースはBaseApplicationPluginに名称変更されました。FeaturesパイプラインフェーズはPluginsに名称変更されました。
v2.0.0以降、Ktorはカスタムプラグインを作成するための新しいAPIを提供することに注意してください。一般的に、このAPIはパイプライン、フェーズなどの内部Ktorコンセプトの理解を必要としません。代わりに、
onCall、onCallReceive、onCallRespondなどの様々なハンドラーを使用して、リクエストとレスポンスを処理する異なるステージにアクセスできます。パイプラインフェーズが新しいAPIハンドラーにどのようにマッピングされるかについては、このセクションで学習できます: パイプラインフェーズと新しいAPIハンドラーのマッピング。
コンテンツネゴシエーションとシリアライゼーション
コンテンツネゴシエーションとシリアライゼーションサーバーAPIは、サーバーとクライアント間でシリアライゼーションライブラリを再利用するようにリファクタリングされました。 主な変更点は以下の通りです。
ContentNegotiationはktor-server-coreから分離されたktor-server-content-negotiationアーティファクトに移動されました。- シリアライゼーションライブラリは
ktor-*から、クライアントでも使用されるktor-serialization-*アーティファクトに移動されました。
以下に示すように、アプリケーションの依存関係とインポートを更新する必要があります。
依存関係
| サブシステム | 1.6.x | 2.0.0 |
|---|---|---|
| ContentNegotiation | io.ktor:ktor-server-core | io.ktor:ktor-server-content-negotiation |
| kotlinx.serialization | io.ktor:ktor-serialization | io.ktor:ktor-serialization-kotlinx-json |
| Gson | io.ktor:ktor-gson | io.ktor:ktor-serialization-gson |
| Jackson | io.ktor:ktor-jackson | io.ktor:ktor-serialization-jackson |
インポート
| サブシステム | 1.6.x | 2.0.0 |
|---|---|---|
| kotlinx.serialization | import io.ktor.serialization.* | import io.ktor.serialization.kotlinx.json.* |
| Gson | import io.ktor.gson.* | import io.ktor.serialization.gson.* |
| Jackson | import io.ktor.jackson.* | import io.ktor.serialization.jackson.* |
カスタムコンバーター
ContentConverterインターフェースによって公開される関数のシグネチャは、以下のように変更されました。
interface ContentConverter {
suspend fun convertForSend(context: PipelineContext<Any, ApplicationCall>, contentType: ContentType, value: Any): Any?
suspend fun convertForReceive(context: PipelineContext<ApplicationReceiveRequest, ApplicationCall>): Any?
}interface ContentConverter {
suspend fun serialize(contentType: ContentType, charset: Charset, typeInfo: TypeInfo, value: Any): OutgoingContent?
suspend fun deserialize(charset: Charset, typeInfo: TypeInfo, content: ByteReadChannel): Any?
}テストAPI
v2.0.0では、Ktorサーバーはテストに新しいAPIを使用し、KTOR-971で説明されている様々な問題を解決します。主な変更点は以下の通りです。
withTestApplication/withApplication関数は、新しいtestApplication関数に置き換えられました。testApplication関数内では、既存のKtorクライアントインスタンスを使用してサーバーにリクエストを送信し、結果を検証する必要があります。- 特定の機能(例えば、クッキーやWebSockets)をテストするには、新しいクライアントインスタンスを作成し、対応するプラグインをインストールする必要があります。
1.6.xテストを2.0.0に移行するいくつかの例を見てみましょう。
基本的なサーバーテスト
以下のテストでは、handleRequest関数がclient.getリクエストに置き換えられています。
@Test
fun testRootLegacyApi() {
withTestApplication(Application::module) {
handleRequest(HttpMethod.Get, "/").apply {
assertEquals(HttpStatusCode.OK, response.status())
assertEquals("Hello, world!", response.content)
}
}
}@Test
fun testRoot() = testApplication {
val response = client.get("/")
assertEquals(HttpStatusCode.OK, response.status)
assertEquals("Hello, world!", response.bodyAsText())
}x-www-form-urlencoded
以下のテストでは、handleRequest関数がclient.postリクエストに置き換えられています。
@Test
fun testPostLegacyApi() = withTestApplication(Application::main) {
with(handleRequest(HttpMethod.Post, "/signup"){
addHeader(HttpHeaders.ContentType, ContentType.Application.FormUrlEncoded.toString())
setBody(listOf("username" to "JetBrains", "email" to "[email protected]", "password" to "foobar", "confirmation" to "foobar").formUrlEncode())
}) {
assertEquals("The 'JetBrains' account is created", response.content)
}
}@Test
fun testPost() = testApplication {
val response = client.post("/signup") {
header(HttpHeaders.ContentType, ContentType.Application.FormUrlEncoded.toString())
setBody(listOf("username" to "JetBrains", "email" to "[email protected]", "password" to "foobar", "confirmation" to "foobar").formUrlEncode())
}
assertEquals("The 'JetBrains' account is created", response.bodyAsText())
}multipart/form-data
v2.0.0でmultipart/form-dataを構築するには、MultiPartFormDataContentをクライアントのsetBody関数に渡す必要があります。
@Test
fun testUploadLegacyApi() = withTestApplication(Application::main) {
with(handleRequest(HttpMethod.Post, "/upload"){
val boundary = "WebAppBoundary"
val fileBytes = File("ktor_logo.png").readBytes()
addHeader(HttpHeaders.ContentType, ContentType.MultiPart.FormData.withParameter("boundary", boundary).toString())
setBody(boundary, listOf(
PartData.FormItem("Ktor logo", { }, headersOf(
HttpHeaders.ContentDisposition,
ContentDisposition.Inline
.withParameter(ContentDisposition.Parameters.Name, "description")
.toString()
)),
PartData.FileItem({ fileBytes.inputStream().asInput() }, {}, headersOf(
HttpHeaders.ContentDisposition,
ContentDisposition.File
.withParameter(ContentDisposition.Parameters.Name, "image")
.withParameter(ContentDisposition.Parameters.FileName, "ktor_logo.png")
.toString()
))
))
}) {
assertEquals("Ktor logo is uploaded to 'uploads/ktor_logo.png'", response.content)
}
}@Test
fun testUpload() = testApplication {
val boundary = "WebAppBoundary"
val response = client.post("/upload") {
setBody(
MultiPartFormDataContent(
formData {
append("description", "Ktor logo")
append("image", File("ktor_logo.png").readBytes(), Headers.build {
append(HttpHeaders.ContentType, "image/png")
append(HttpHeaders.ContentDisposition, "filename=\"ktor_logo.png\"")
})
},
boundary,
ContentType.MultiPart.FormData.withParameter("boundary", boundary)
)
)
}
assertEquals("Ktor logo is uploaded to 'uploads/ktor_logo.png'", response.bodyAsText())
}JSONデータ
v1.6.xでは、kotlinx.serializationライブラリが提供するJson.encodeToString関数を使用してJSONデータをシリアライズできます。 v2.0.0では、新しいクライアントインスタンスを作成し、特定の形式でコンテンツをシリアライズ/デシリアライズできるContentNegotiationプラグインをインストールする必要があります。
@Test
fun testPostCustomerLegacyApi() = withTestApplication(Application::main) {
with(handleRequest(HttpMethod.Post, "/customer"){
addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString())
setBody(Json.encodeToString(Customer(3, "Jet", "Brains")))
}) {
assertEquals("Customer stored correctly", response.content)
assertEquals(HttpStatusCode.Created, response.status())
}
}@Test
fun testPostCustomer() = testApplication {
val client = createClient {
install(ContentNegotiation) {
json()
}
}
val response = client.post("/customer") {
contentType(ContentType.Application.Json)
setBody(Customer(3, "Jet", "Brains"))
}
assertEquals("Customer stored correctly", response.bodyAsText())
assertEquals(HttpStatusCode.Created, response.status)
}テスト中のクッキーの保持
v1.6.xでは、テスト時にリクエスト間でクッキーを保持するためにcookiesSessionが使用されます。v2.0.0では、新しいクライアントインスタンスを作成し、HttpCookiesプラグインをインストールする必要があります。
@Test
fun testRequestsLegacyApi() = withTestApplication(Application::main) {
fun doRequestAndCheckResponse(path: String, expected: String) {
handleRequest(HttpMethod.Get, path).apply {
assertEquals(expected, response.content)
}
}
cookiesSession {
handleRequest(HttpMethod.Get, "/login") {}.apply {}
doRequestAndCheckResponse("/user", "Session ID is 123abc. Reload count is 0.")
doRequestAndCheckResponse("/user", "Session ID is 123abc. Reload count is 1.")
doRequestAndCheckResponse("/user", "Session ID is 123abc. Reload count is 2.")
handleRequest(HttpMethod.Get, "/logout").apply {}
doRequestAndCheckResponse("/user", "Session doesn't exist or is expired.")
}
} @Test
fun testRequests() = testApplication {
val client = createClient {
install(HttpCookies)
}
val loginResponse = client.get("/login")
val response1 = client.get("/user")
assertEquals("Session ID is 123abc. Reload count is 1.", response1.bodyAsText())
val response2 = client.get("/user")
assertEquals("Session ID is 123abc. Reload count is 2.", response2.bodyAsText())
val response3 = client.get("/user")
assertEquals("Session ID is 123abc. Reload count is 3.", response3.bodyAsText())
val logoutResponse = client.get("/logout")
assertEquals("Session doesn't exist or is expired.", logoutResponse.bodyAsText())
}WebSockets
旧APIでは、WebSocket会話をテストするためにhandleWebSocketConversationが使用されます。v2.0.0では、クライアントが提供するWebSocketsプラグインを使用することでWebSocket会話をテストできます。
@Test
fun testConversationLegacyApi() {
withTestApplication(Application::module) {
handleWebSocketConversation("/echo") { incoming, outgoing ->
val greetingText = (incoming.receive() as Frame.Text).readText()
assertEquals("Please enter your name", greetingText)
outgoing.send(Frame.Text("JetBrains"))
val responseText = (incoming.receive() as Frame.Text).readText()
assertEquals("Hi, JetBrains!", responseText)
}
}
} @Test
fun testConversation() {
testApplication {
val client = createClient {
install(WebSockets)
}
client.webSocket("/echo") {
val greetingText = (incoming.receive() as? Frame.Text)?.readText() ?: ""
assertEquals("Please enter your name", greetingText)
send(Frame.Text("JetBrains"))
val responseText = (incoming.receive() as Frame.Text).readText()
assertEquals("Hi, JetBrains!", responseText)
}
}
}DoubleReceive
v2.0.0では、DoubleReceiveプラグイン設定にcacheRawRequestプロパティが導入され、これはreceiveEntireContentとは逆の動作をします。
- v1.6.xでは、
receiveEntireContentプロパティはデフォルトでfalseに設定されています。 - v2.0.0では、
cacheRawRequestはデフォルトでtrueに設定されています。receiveEntireContentプロパティは削除されました。
Forwarded headers
v2.0.0では、ForwardedHeaderSupportとXForwardedHeaderSupportプラグインは、それぞれForwardedHeadersとXForwardedHeadersに名称変更されました。
Caching headers
キャッシュオプションを定義するために使用されるoptions関数は、OutgoingContentに加えてApplicationCallをラムダ引数として受け入れるようになりました。
install(CachingHeaders) {
options { outgoingContent ->
// ...
}
}install(CachingHeaders) {
options { call, outgoingContent ->
// ...
}
}Conditional headers
リソースバージョンのリストを定義するために使用されるversion関数は、OutgoingContentに加えてApplicationCallをラムダ引数として受け入れるようになりました。
install(ConditionalHeaders) {
version { outgoingContent ->
// ...
}
}install(ConditionalHeaders) {
version { call, outgoingContent ->
// ...
}
}CORS
CORS設定で使用されるいくつかの関数が名称変更されました。
host->allowHostheader->allowHeadermethod->allowMethod
install(CORS) {
host("0.0.0.0:5000")
header(HttpHeaders.ContentType)
method(HttpMethod.Options)
}install(CORS) {
allowHost("0.0.0.0:5000")
allowHeader(HttpHeaders.ContentType)
allowMethod(HttpMethod.Options)
}MicrometerMetrics
v1.6.xでは、HTTPリクエストの監視に使用されるKtorメトリクスのベース名(プレフィックス)を指定するためにbaseNameプロパティが使用されます。 デフォルトでは、ktor.http.serverに等しいです。 v2.0.0では、baseNameはmetricNameに置き換えられ、そのデフォルト値はktor.http.server.requestsです。
Ktorクライアント
リクエストとレスポンス
v2.0.0では、リクエストとレスポンスを行うために使用されるAPIが、より一貫性があり発見しやすいように更新されました (KTOR-29)。
リクエスト関数
複数のパラメータを持つリクエスト関数は非推奨になりました。例えば、portおよびpathパラメータは、HttpRequestBuilderによって公開されるurlパラメータに置き換える必要があります。
client.get(port = 8080, path = "/customer/3")client.get { url(port = 8080, path = "/customer/3") }また、HttpRequestBuilderを使用すると、リクエスト関数ラムダ内で追加のリクエストパラメータを指定できます。
リクエストボディ
リクエストボディを設定するために使用されていたHttpRequestBuilder.bodyプロパティは、HttpRequestBuilder.setBody関数に置き換えられました。
client.post("http://localhost:8080/post") {
body = "Body content"
}client.post("http://localhost:8080/post") {
setBody("Body content")
}レスポンス
v2.0.0では、リクエスト関数(get、post、put、submitFormなど)は、特定の型のオブジェクトを受け取るためのジェネリック引数を受け入れなくなりました。 現在、すべてのリクエスト関数はHttpResponseオブジェクトを返します。これは、特定の型インスタンスを受け取るためのジェネリック引数を持つbody関数を公開しています。 コンテンツを文字列またはチャネルとして受け取るために、bodyAsTextまたはbodyAsChannelを使用することもできます。
val httpResponse: HttpResponse = client.get("https://ktor.io/")
val stringBody: String = httpResponse.receive()
val byteArrayBody: ByteArray = httpResponse.receive()val httpResponse: HttpResponse = client.get("https://ktor.io/")
val stringBody: String = httpResponse.body()
val byteArrayBody: ByteArray = httpResponse.body()ContentNegotiationプラグインをインストールすると、以下のように任意のオブジェクトを受け取ることができます。
val customer: Customer = client.get("http://localhost:8080/customer/3")val customer: Customer = client.get("http://localhost:8080/customer/3").body()ストリーミングレスポンス
リクエスト関数からジェネリック引数が削除されたため、ストリーミングレスポンスを受け取るには個別の関数が必要です。 これを実現するために、prepareGetやpreparePostなどのprepareプレフィックスが付いた関数が追加されました。
public suspend fun HttpClient.prepareGet(builder: HttpRequestBuilder): HttpStatement
public suspend fun HttpClient.preparePost(builder: HttpRequestBuilder): HttpStatement以下に、この場合のコード変更方法の例を示します。
client.get<HttpStatement>("https://ktor.io/").execute { httpResponse ->
val channel: ByteReadChannel = httpResponse.receive()
while (!channel.isClosedForRead) {
// Read data
}
}client.prepareGet("https://ktor.io/").execute { httpResponse ->
val channel: ByteReadChannel = httpResponse.body()
while (!channel.isClosedForRead) {
// Read data
}
}完全な例は、こちらで確認できます: ストリーミングデータ。
レスポンス検証
v2.0.0では、レスポンス検証に使用されるexpectSuccessプロパティは、デフォルトでfalseに設定されています。 これには、コードに以下の変更が必要です。
- デフォルトの検証を有効にするには、非2xxレスポンスに対して例外をスローするように、
expectSuccessプロパティをtrueに設定します。 - もし
handleResponseExceptionWithRequestを使用して非2xx例外を処理する場合、expectSuccessも明示的に有効にする必要があります。
HttpResponseValidator
handleResponseException関数は、例外に追加情報を提供するためにHttpRequestへのアクセスを追加するhandleResponseExceptionWithRequestに置き換えられました。
HttpResponseValidator {
handleResponseException { exception ->
// ...
}
}HttpResponseValidator {
handleResponseExceptionWithRequest { exception, request ->
// ...
}
}コンテンツネゴシエーションとシリアライゼーション
Ktorクライアントは現在コンテンツネゴシエーションをサポートしており、Ktorサーバーとシリアライゼーションライブラリを共有しています。 主な変更点は以下の通りです。
JsonFeatureは、ktor-client-content-negotiationアーティファクトにあるContentNegotiationを推奨し、非推奨になりました。- シリアライゼーションライブラリは
ktor-client-*からktor-serialization-*アーティファクトに移動されました。
以下に示すように、クライアントコードの依存関係とインポートを更新する必要があります。
依存関係
| サブシステム | 1.6.x | 2.0.0 |
|---|---|---|
ContentNegotiation | n/a | io.ktor:ktor-client-content-negotiation |
| kotlinx.serialization | io.ktor:ktor-client-serialization | io.ktor:ktor-serialization-kotlinx-json |
| Gson | io.ktor:ktor-client-gson | io.ktor:ktor-serialization-gson |
| Jackson | io.ktor:ktor-client-jackson | io.ktor:ktor-serialization-jackson |
インポート
| サブシステム | 1.6.x | 2.0.0 |
|---|---|---|
ContentNegotiation | n/a | import io.ktor.client.plugins.contentnegotiation.* |
| kotlinx.serialization | import io.ktor.client.features.json.* | import io.ktor.serialization.kotlinx.json.* |
| Gson | import io.ktor.client.features.json.* | import io.ktor.serialization.gson.* |
| Jackson | import io.ktor.client.features.json.* | import io.ktor.serialization.jackson.* |
ベアラー認証
refreshTokens関数は、HttpResponseラムダ引数(it)の代わりに、ラムダレシーバー(this)としてRefreshTokenParamsインスタンスを使用するようになりました。
bearer {
refreshTokens { // it: HttpResponse
// ...
}
}bearer {
refreshTokens { // this: RefreshTokenParams
// ...
}
}RefreshTokenParamsは以下のプロパティを公開しています。
response: レスポンスパラメータにアクセスするためclient: トークンをリフレッシュするリクエストを行うためoldTokens:loadTokensを使用して取得したトークンにアクセスするため
HttpSend
HttpSendプラグインのAPIは以下のように変更されました。
client[HttpSend].intercept { originalCall, request ->
if (originalCall.something()) {
val newCall = execute(request)
// ...
}
}client.plugin(HttpSend).intercept { request ->
val originalCall = execute(request)
if (originalCall.something()) {
val newCall = execute(request)
// ...
}
}v2.0.0では、プラグインへのインデックスアクセスは利用できないことに注意してください。HttpClient.plugin関数を使用してください。
HttpClient.get(plugin: HttpClientPlugin) 関数は削除されました
v2.0.0では、クライアントプラグインを受け入れるHttpClient.get関数は削除されました。代わりにHttpClient.plugin関数を使用してください。
client.get(HttpSend).intercept { ... }
// or
client[HttpSend].intercept { ... }client.plugin(HttpSend).intercept { ... }FeatureはPluginに名称変更されました
Ktorサーバーと同様に、クライアントAPIでも_Feature_は_Plugin (プラグイン)_ に名称変更されました。 これは以下に説明するように、アプリケーションに影響を与える可能性があります。
インポート
プラグインをインストールするためのインポートを更新します。
| サブシステム | 1.6.x | 2.0.0 |
| import io.ktor.client.features.* | import io.ktor.client.plugins.* |
Authentication (認証) The Auth plugin handles authentication and authorization in your client application. | import io.ktor.client.features.auth.* import io.ktor.client.features.auth.providers.* | import io.ktor.client.plugins.auth.* import io.ktor.client.plugins.auth.providers.* |
Cookies (クッキー) The HttpCookies plugin handles cookies automatically and keep them between calls in a storage. | import io.ktor.client.features.cookies.* | import io.ktor.client.plugins.cookies.* |
Logging (ロギング) Required dependencies: io.ktor:ktor-client-logging Code example: %example_name% | import io.ktor.client.features.logging.* | import io.ktor.client.plugins.logging.* |
WebSockets (ウェブソケット) The Websockets plugin allows you to create a multi-way communication session between a server and a client. | import io.ktor.client.features.websocket.* | import io.ktor.client.plugins.websocket.* |
Content encoding (コンテンツエンコーディング) The ContentEncoding plugin allows you to enable specified compression algorithms (such as 'gzip' and 'deflate') and configure their settings. | import io.ktor.client.features.compression.* | import io.ktor.client.plugins.compression.* |
カスタムプラグイン
HttpClientFeatureインターフェースはHttpClientPluginに名称変更されました。
ネイティブターゲット向けの新しいメモリモデル
v2.0.0では、ネイティブターゲットでKtorクライアントを使用するには、新しいKotlin/Nativeメモリモデルを有効にする必要があります: 新しいMMを有効にする。
v2.2.0以降、新しいKotlin/Nativeメモリモデルはデフォルトで有効になっています。
'Ios' エンジンは 'Darwin' に名称変更されました
IosエンジンがiOSだけでなく、macOSやtvOSを含む他のオペレーティングシステムもターゲットとしているため、v2.0.0ではDarwinに名称変更されました。これにより、以下の変更が生じます。
io.ktor:ktor-client-iosアーティファクトはio.ktor:ktor-client-darwinに名称変更されました。HttpClientインスタンスを作成するには、Darwinクラスを引数として渡す必要があります。IosClientEngineConfig設定クラスはDarwinClientEngineConfigに名称変更されました。
Darwinエンジンの設定方法については、Darwinセクションを参照してください。
WebSocketsコードは 'websockets' パッケージに移動されました
WebSocketsコードはhttp-cioからwebsocketsパッケージに移動されました。これにより、インポートを以下のように更新する必要があります。
| 1.6.x | 2.0.0 |
|---|---|
import io.ktor.http.cio.websocket.* | import io.ktor.websocket.* |
Default request
DefaultRequestプラグインは、HttpRequestBuilderの代わりにDefaultRequestBuilder設定クラスを使用します。
val client = HttpClient(CIO) {
defaultRequest {
// this: HttpRequestBuilder
}
}val client = HttpClient(CIO) {
defaultRequest {
// this: DefaultRequestBuilder
}
}