1.6.x から 2.0.x へのマイグレーション
このガイドでは、Ktorアプリケーションを1.6.xバージョンから2.0.xバージョンへ移行する方法について説明します。
Ktorサーバー
サーバーコードは 'io.ktor.server.*' パッケージに移動されました
サーバーとクライアントの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
->allowHost
header
->allowHeader
method
->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) 関数は削除されました
2.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
}
}