Ktor迈入3.0,带来哪些变化和改进?

程序员咋不秃头 2024-11-13 04:47:47

此新版本使用 Kotlin 2.0,并切换到 kotlinx-io¹,因此 Ktor 更加现代化,与其他 Kotlin 工具的连接也更好。Ktor 3.0 的运行速度更快,并提供了更多客户端-服务器应用程序构建选项。

如果您刚开始使用 Ktor 或需要了解其运作方式,请阅读我们最新发布的博文 Ktor 101:高效的 JVM HTTP 工具包,其中介绍了它的主要功能。

以下博文将为您全面概述 Ktor 3.0 中的最新变化和改进。

立即使用 Ktor 3.0 进行构建!https://kotl.in/rc94yb

迁移到 kotlinx-io

此新版本中最大的更改是切换到基于 Okio² 的 kotlinx-io 库³。如果您使用 Ktor 的低级IO API,此更改可能会影响您。我们进行此更改是为了标准化各个 Kotlin 库的 IO 功能并提高性能,如我们的基准测试所示。

重大更改

更改主要影响低级 IO API,包括 Input⁴、Output⁵、ByteReadChannel⁶ 和 ByteWriteChannel⁷ 等类。如果您直接使用这些类,将会看到弃用警告。您应更新代码,以使用 kotlinx-io 库提供的替代代码。别担心 – 在 4.0 版本发布之前,我们将一直支持旧 API,让您有充足的时间进行迁移。

新 kotlinx-io 库提供的多平台 API 可以处理各种数据源,并提供多种功能,包括处理文件、使用压缩等。有关详情,请查阅 kotlinx-io API 文档⁸。

性能改进

切换到 kotlinx-io 后,我们减少了 ByteReadChannel、ByteWriteChannel与网络接口之间不必要的字节复制。这样可以更高效地进行字节转换和解析,为未来的性能改进留出了空间。

基于真实 Ktor 应用程序的 IO 基准⁹测试结果令人印象深刻。一些测试显示,性能提高了 90% 以上,并且我们正着手实现更多增强功能。

支持服务器发送事件 (SSE)

在 Ktor 3.0 中,我们同时为服务器和客户端增加了对服务器发送事件 (SSE) 的初步支持。

利用服务器发送事件这项技术,服务器可以通过 HTTP 连接向客户端推送事件。SSE 提供从服务器到客户端的单向通信通道。如果服务器需要发送基于事件的更新,但不需要客户端反复轮询获取新信息,则非常适合使用这种方式。

要在 Ktor 应用程序中实现 SSE 支持,请先将 SSE 依赖项添加到您的项目的构建脚本中:

implementation("io.ktor:ktor-server-sse-jvm")

接下来,在您的 Ktor 应用程序中安装 SSE 插件,并使用sse{}函数创建端点:

import io.ktor.server.application.*import io.ktor.server.engine.*import io.ktor.server.netty.*import io.ktor.server.routing.*import io.ktor.server.sse.*import io.ktor.sse.*import kotlinx.coroutines.delayfun main() { embeddedServer(Netty, port = 8080) { install(SSE) routing { sse { repeat(42) { val name = call.parameters["name"] ?: "World" send(ServerSentEvent(data = "Hello, $name! $it")) delay(1000) } close() } } }.start(wait = true)}

在sse {...}块中,您可以通过以下功能访问ServerSSESession实例。

send():创建ServerSentEvent并将其发送到客户端。call:访问启动会话的关联ApplicationCall。close():结束会话并终止与客户端的连接。

请注意,Ktor 目前不支持对 SSE 响应进行数据压缩。如果您使用 Compression 插件,将默认跳过对 SSE 响应的压缩。

要使用 Ktor 客户端消费事件,在最简单的情况下,只需在客户端实例上调用sse函数即可,具体如下:

import io.ktor.client.*import io.ktor.client.engine.cio.*import io.ktor.client.plugins.sse.*import kotlinx.coroutines.runBlockingfun main() { val client = HttpClient(CIO) { install(SSE) } runBlocking { client.sse(host = "127.0.0.1", port = 8080, path = "/sse") { incoming.collect { event -> println(event) } } }}

在上例中,只要服务器在发送数据,客户端就会消费事件。

通过 ZIP 归档提供静态资源

利用新函数staticZip,用户可以提供 ZIP 归档的内容作为静态内容。

下面给出了该函数使用方法的基本示例:

routing { staticZip( remotePath = "/", basePath = "base", Path("files/text-files.zip") ) { default("file.txt") //modify the response by adding the HTTP Etag header modify { path, call -> call.response.headers.append(HttpHeaders.ETag, path.fileName.toString()) } }}

我们将示例分解为几个主要部分:

remotePath– 基本 URL 路径,可以在该路径中访问 ZIP 内容。basePath– 您希望提供的 ZIP 文件内的基本路径。在我们的示例中,假定 ZIP 归档包含base目录。指定basePath内的所有路径均可在remotePath/path/to/resource中进行递归访问。这意味着您可以使用子文件夹组织 ZIP 文件,这些子文件夹将反映在 URL 结构中。Path("files/text-files.zip")– 您要提供的 ZIP 文件的路径。default()函数 – 用于指定在未请求特定文件时提供的默认文件。modify 块 – 用于自定义响应。在本例中,我们将基于文件名添加 ETag 标头。

访问 GitHub 上的 Ktor 示例仓库¹⁰获取完整示例。

支持 CSRF

通过新插件增加了对 CSRF(跨站请求伪造¹¹)防护的支持。为更改状态的操作(包括 POST、PUT 和 DELETE)启用了防护。

一般来讲,CSRF 防护仅适用于使用会话 Cookie 和表单的项目,因为启用 CSRF 防护会导致应用程序复杂性不必要地提高。

要在 Ktor 应用程序中启用 CSRF 支持,请先将以下依赖项添加到您的项目的构建脚本中:

implementation("io.ktor:ktor-server-csrf-jvm")

接下来,您可以为应用程序中的所选例程启用 CSRF 防护,如下所示:

route("/csrf") { install(CSRF) { allowOrigin("https://localhost:8080") originMatchesHost() checkHeader("X-CSRF") { csrfHeader -> request.headers[HttpHeaders.Origin]?.let { origin -> csrfHeader == origin.hashCode().toString(32) // 1ndrgg9 } == true } onFailure { respondText("Access denied!", status = HttpStatusCode.Forbidden) } } post { call.respondText("CSRF check was successful") }}

在配置块中,插件提供了几种方法来验证请求:

allowOrigin指定仅允许来自预定义来源的请求。在我们的示例中,预定义来源是https://localhost:8080。originMatchesHost强制要求请求的来源必须与应用程序的主机匹配。checkHeader可以实现任意标头验证。

如果您使用以上代码运行应用程序,并使用 curl命令向/csrf端点发送 POST 请求,您将看到以下结果:

curl -X POST -H "Content-Type: application/json" --data '{}' http://localhost:8080/csrfAccess denied!

添加所需标头可使其通过检查:

curl -X POST -H "X-CSRF: 1ndrgg9" -H "Origin: http://localhost:8080" -H "Content-Type: application/json" --data '{}' http://localhost:8080/csrfCSRF check passed!适用于 Wasm 的 Ktor 客户端

Ktor 客户端现在支持 WebAssembly (Wasm) 作为构建目标。虽然 Kotlin/Wasm¹² 仍处于早期阶段 (Alpha),但向 Ktor 客户端添加对 Wasm 的支持是扩展 Kotlin Multiplatform 生态系统的重要一步。为了展示这一新功能,我们创建了一个示例 Compose Multiplatform 项目¹³,该项目将 Ktor 客户端与 WebAssembly (wasmJs) 目标结合使用。

要使用 Ktor 客户端,您需要将相应依赖项添加到项目的构建脚本中:

implementation("io.ktor:ktor-client-core:$ktor_version")迁移指南

Ktor 3.0 带来了一些重要变化。我们准备了迁移指南¹⁴来帮助您轻松实现过渡。在本文中,我们重点介绍最显著的变化。

无论您是否将现有项目升级到 Ktor 3.0,都可以立即开始使用 Ktor 3.0 构建新项目!

使用 Ktor 3.0 启动新项目:https://kotl.in/mx6tmq

在TestApplication中显式加载模块

从现在起,TestApplication¹⁵ 类需要显式加载模块。以下测试将启动一个空应用程序,且不会加载任何模块:

@Test fun testRoot() = testApplication {// TestApplication scope client.get("/").apply { assertEquals(HttpStatusCode.OK, status) assertEquals("Hello World!", bodyAsText()) } }

相反,您必须在 testApplication¹⁶ 函数中显式加载模块,或手动加载配置文件。

@Test fun testRoot() = testApplication { application { configureRouting() } client.get("/").apply { assertEquals(HttpStatusCode.OK, status) assertEquals("Hello World!", bodyAsText()) } }

插件更新

CallLogging插件软件包已重命名,修正了一处拼写错误:

Locations插件已被替换为¹⁷新的Resources插件,用于实现类型安全路由。

这些变动旨在改善 Ktor 的架构、安全和开发者体验。从 Ktor 2.x 升级的用户应参考详细的迁移指南,以确保顺利过渡至新版本。

相关链接:

1. kotlinx-io:

http://kotlinx.io/

2. Okio:

https://github.com/square/okio

3. kotlinx-io 库:

https://github.com/Kotlin/kotlinx-io/

4. Input:

https://github.com/ktorio/ktor/blob/main/ktor-io/common/src/io/ktor/utils/io/core/Input.kt

5. Output:

https://github.com/ktorio/ktor/blob/main/ktor-io/common/src/io/ktor/utils/io/core/Output.kt

6. ByteReadChannel:

https://github.com/ktorio/ktor/blob/main/ktor-io/common/src/io/ktor/utils/io/ByteReadChannel.kt

7. ByteWriteChannel:

https://github.com/ktorio/ktor/blob/main/ktor-io/common/src/io/ktor/utils/io/ByteWriteChannel.kt

8. API 文档:

https://kotlin.github.io/kotlinx-io/

9. IO 基准:

https://github.com/ktorio/ktor-benchmarks/tree/main/io-benchmarks

10. GitHub 上的 Ktor 示例仓库:

https://github.com/ktorio/ktor-documentation/tree/3.0.0-beta-2/codeSnippets/snippets/static-zip

11. 跨站请求伪造:

https://owasp.org/www-community/attacks/csrf

12. Kotlin/Wasm:

https://kotlinlang.org/docs/wasm-overview.html

13. 示例 Compose Multiplatform 项目:

https://github.com/antonarhipov/ktor-samples-fork/tree/main/ktor-client-wasm

14. 迁移指南:

https://ktor.io/docs/migrating-3.html

15. TestApplication:

https://api.ktor.io/ktor-server/ktor-server-test-host/io.ktor.server.testing/-test-application/index.html

16. testApplication:

https://api.ktor.io/ktor-server/ktor-server-test-host/io.ktor.server.testing/test-application.html

17. 已被替换为:

https://ktor.io/docs/3.0.0-beta-2/migrating-3.html#locations-plugin-has-been-removed

0 阅读:0