0.9.2 → 1.0.0-beta-3 迁移

预计阅读时间: 25 分钟

目录:

1.0.0-beta-3

这是 Ktor 的第三个 beta 版。也是第一个使用 Kotlin 1.3.0 与kotlinx.coroutines 1.0.0 最终版的的 Ktor 版本!

发布于 2018-10-29

版本升级:

  • Kotlin: 1.3.0-rc-146 -> 1.3.0
  • Kotlinx IO: 0.1.0-alpha-25-rc13 -> 0.1.0-beta-1
  • Kotlinx Coroutines: 1.0.0-RC1 -> 1.0.0
  • Kotlinx Serialization: 0.8.2-rc13 -> 0.9.0
  • AtomicFU: 0.11.11 -> 0.11.12

改进:

  • kotlinx.serialization 特性中添加 js 支持(提交记录)(关闭了 #666
  • 避免阻塞 PRNG(提交记录
  • 为令牌获取失败改进 OAuth2 诊断(#550
  • 使用 .serializer 查找序列化器(提交记录
  • 添加了一系列 KDocs 并阐明了一些旧版 KDocs

修复:

  • 修复处理身份认证错误(#676

小改动:

  • 删除了 ApacheHttpRequest 中的冗余标志(提交记录

如何试用

需要使用 Kotlin 1.3.0 或更高版本。该版本应该已经在 Maven Central 与 jcenter 上提供:

buildscript {
    ext.kotlin_version = '1.3.0'
}

还需要在 IntelliJ IDEA 内使用 Kotlin 1.3。

1.0.0-beta-2

这是 Ktor 的第二个 beta 版。

发布于 2018-10-24

版本升级:

  • Kotlin: 1.3.0-rc-131 -> 1.3.0-rc-146
  • Kotlinx IO: 0.1.0-alpha-19-rc13 -> 0.1.0-alpha-25-rc13
  • Kotlinx Coroutines: 0.30.2-eap13 -> 1.0.0-RC1
  • AtomicFU: 0.11.10-eap13 -> 0.11.11

主要变更:

标记为实验性:

  • 将 location API 标记为实验性的(提交记录
  • 引入 stopServerOnCancellation 取代取消助手(提交记录

弃用:

  • 将 nextNonce 重命名为 generateNonce(提交记录

新增:

  • 引入应用程序级协程作用域(提交记录
  • 为嵌入式服务器引入指定协程作用域的能力(提交记录
  • ktor-client:将 HttpsURLConnection 配置添加到 AndroidEngineConfig (提交记录
  • ktor-client:AndroidEngineConfig 中添加代理(提交记录
  • 添加带有显式 KSerializer 参数的 KotlinxSerializer.register()(提交记录
  • 向 KotlinxSerializer 添加默认序列化器(提交记录
  • 向 KotlinxSerializer 添加使用具体化的翻来来设置 mapper 的 register()(提交记录
  • 为 Location 特性引入 href 扩展函数(#597

小改动:

  • 限制 Location 注解目标,允许在类型别名上标注(#539
  • 删除在 80 端口上的默认连接器(#670
  • 解禁 Kotlin Native 反虚拟化(提交记录

改进:

  • 改进 JWT 诊断(#664
  • 为令牌获取失败改进 OAuth2 诊断(#550
  • 替换阻塞 servlet 实现中的 Unconfined(提交记录
  • 提高 nextNonce 强度(现在称为 generateNonce)(提交记录
  • 改进 KotlinxSerializer 的错误处理(提交记录

修复:

  • 修复 Windows 上 multipart 的 part 处理(提交记录
  • 修复 Jetty 上 websocket IDLE 超时(提交记录
  • 修复导致通道过早关闭的损毁压缩(提交记录
  • 在 JS 引擎中正确构造请求头(#665
  • 修复引擎套件的套接字连接超时(提交记录
  • 修复嵌入式 tomcat 引擎停止(提交记录
  • 消除使用 Unconfined 从文件中读取(修复选择器无限循环)(提交记录
  • 修复 StatusPage 以处理子作业失败(#646

删除:

  • 修复在基准测试中的实验性注解(提交记录

如何试用

需要包含 kotlin-eap 仓库并使用 Kotlin 1.3.0-rc-146 或更高版本:

buildscript {
    ext.kotlin_version = '1.3.0-rc-146'

    repositories {
        // ……
        maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
    }
}

repositories {
    // ……
    maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
    maven { url 'https://dl.bintray.com/kotlin/kotlinx' }
    maven { url 'https://dl.bintray.com/kotlin/ktor' }
    jcenter()
}

还需要在 IntelliJ IDEA 内使用 Early Access Preview 1.3。

可这样做:打开 Tools -> Kotlin -> Configure Kotlin Updates,Update Channel 选择 Early Access Preview 1.3 并安装该版本的插件。

DevelopmentEngine 改为 EngineMain

我们已将 DevelopmentEngine 类重命名为 EngineMain,你必须更新 application.conf 配置文件。

DevelopmentEngine 类常用作 Ktor 应用程序的入口。除了创建嵌入式服务器并加载指定的模块之外, 它还加载了 application.conf 并解析了命令行参数。

DevelopmentEngine 的问题在于它令人困惑,因为有些人认为 Development 是生产(Production)的反义词。

新名称反映了它作为应用程序的入口使用并且与环境无关,同时适用于开发环境与生产环境。

1.0.0-beta-1

这是 Ktor 的第一个 beta 版!本页包含 alpha-2、alpha-3 与 beta-1 的变更。

发布于 2018-10-15

版本升级:

  • Kotlinx IO: 0.1.0-alpha-17-rc13 -> 0.1.0-alpha-19-rc13

新增:

改进:

  • URLBuilder 现在区分未指定端口与回退到协议 defaultPort 的情况(#561
  • 在客户端响应配置中使用 UTF-8 编码作为回退备选(提交记录
  • 默认情况下,在客户端构建器中使用默认端口(端口 0 现在表示协议的默认端口)
  • 提供用户自定义函数来配置 Netty 的 HttpServerCodec(#629)修复 [#580](https://github.com/ktorio/ktor/issues/580)
  • 添加缺失的 HttpClient 构造函数(提交记录
  • 添加 MockEngine 内容测试(提交记录
  • 为 WebSockets API 添加便捷方法(提交记录
  • 准备迁移到协程 1.0.0-RC(#642
  • 使用引擎响应中的客户端状态消息(提交记录

修复:

  • 修复 TLS 解密器循环 bug 并减少垃圾(提交记录
  • 修复 escapeHTML 工具函数(提交记录
  • 修复客户端 HttpSend 循环,如果调用已更改就不退出(提交记录
  • 修复损坏的 normalizeAndRelativize,并添加文档(提交记录
  • 修复 cookie 区分大小写(提交记录
  • 修复 cookie 与参数重复(提交记录

性能提升:

文档:

  • 改进文档、API 清理、引入实验性注解(提交记录

小改动与清理:

如何试用

需要包含 kotlin-eap 仓库并使用 Kotlin 1.3.0-rc-131 或更高版本:

buildscript {
    ext.kotlin_version = '1.3.0-rc-131'

    repositories {
        // ……
        maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
    }
}

repositories {
    // ……
    maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
    maven { url 'https://dl.bintray.com/kotlin/kotlinx' }
    maven { url 'https://dl.bintray.com/kotlin/ktor' }
    jcenter()
}

还需要在 IntelliJ IDEA 内使用 Early Access Preview 1.3。

可这样做:打开 Tools -> Kotlin -> Configure Kotlin Updates,Update Channel 选择 Early Access Preview 1.3 并安装该版本的插件。

1.0.0-alpha-1

Ktor 1.0.0-alpha-1 是 1.0 发布前的第一个预览版。 这个版本是第一个使用 Kotlin 1.3.0-rc-131 的版本,并且将 kotlinx.coroutines 版本升级到 0.30.2-eap13。 一个重要的变化是,Ktor 现在使用 kotlinx.coroutines结构化并发。 此外还添加了

发布于 2018-10-09

版本升级:

  • Kotlin: 1.2.70 -> 1.3.0-rc-131
  • Kotlinx IO: 0.1.0-alpha-4 -> 0.1.0-alpha-17-rc13
  • Kotlinx Coroutines: 0.25.0 -> 0.30.2-eap13
  • Atomic FU: 0.11.3 -> 0.11.10-eap13

主要变更:

弃用、重命名以及 API 变更:

  • 将一些旧的弃用项提升到了 DeprecationLevel.ERROR 级别
  • 弃用了 ByteBufferBuilder
  • 重命名了 RoutingException -> LocationRoutingException
  • HttpMessageBuilder.contentLength()HttpMessage.contentLength() 现在返回 Long
  • 删除一些弃用项并更改为实验性的内部 API。(例如 WebSocketInternalAPI
  • AndroidClientEngine 现在是 @UseExperimental(InternalAPI::class)
  • 弃用了 Apache 的类型别名 ApacheBackend

修复:

  • 使默认调用流水线丢弃请求正文内容(修复 #609#574
  • 修复 url 路径编码
  • 修复释放后的服务端响应日志记录
  • 使 Cookie.matches 忽略域名中的前导点

新增:

API 改进:

  • 统一 mimetype + 使用 Kotlin 1.3 stdlib 的随机数
  • 在 MacOS 上测试 Kotlin/Native

小改动:

  • 一些 API 文档
  • 为外部编辑器添加 editorconfig
  • 使用 kotlin.code.style=official

新版协程

自 1.0.0-alpha-1 起,Ktor 使用最新版的 kotlinx.coroutines,该版本使用结构化并发。 现在每个请求都有自己的 CoroutineScope,你也可以使用 GlobalScope

更多信息请参见: https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/basics.md#structured-concurrency

0.9.5

Ktor 0.9.5 是一个小更新,修复了一些 bug、升级了一些版本,并添加了一些小功能。

发布于 2018-09-19

版本升级:

  • Kotlin: 1.2.61 -> 1.2.70

潜在的轻微破坏性变更:

  • 客户端的 CookiesStorage.getCookiesStorage.addCookie 以及 HttpCookies.get 现在接受 requestUrl 而不是主机名作为参数。现在 get 会返回一个 cookie 的列表。
  • 使 HTTP 客户端扩展方法 HttpRequest.takeFrom(builder: HttpRequestBuilder): HttpRequestBuilder 现在还将 builder 中的的类型化调用属性设置为成员方法。当使用星号导入 * 时不会有兼容性问题,因为它在相同的包内。

修复:

  • HttpClient.config 未保留基础配置(#559
  • 修复了路径与查询转义并使其与 URLBuilder 一致(#577)。
  • 修复了非文本内容类型设置字符编码的问题

新增:

  • 引入了 CallId 特性
  • CallLogging 特性添加了 MDC 支持

API 改进:

  • HEADOPTIONSPATCH 以及 DELETE 方法添加了简写客户端函数(#562
  • HTTP 客户端:添加了快捷方式 List<Cookie>.get(name: String): Cookie?
  • HTTP 客户端:向 FORM DSL 添加了 fun FormBuilder.append(key: String, filename: String, block: BytePacketBuilder.() -> Unit)
  • 改进了 URLBuilder 的解析器(#553#567
  • 添加了 respondOutputStream { } 响应函数
  • Infrastructure 阶段拆分为 MonitoringFeatures 阶段

内部变更:

  • 使 AcceptAllCookiesStorage 对所有实现都相同。
  • 改进了客户端的 cookie 匹配与处理

HTTP 客户端的新的 http 方法快捷方式

在 0.9.5 之前,当使用 HTTP 客户端并希望创建 HEADOPTIONSPATCH 或者 DELETE 请求时, 必须使用 HttpClient.requestHttpClient.call

而对于 0.9.5,除了 HttpClient.getHttpClient.post 之外,现在还有四个便利的方法 HttpClient.headHttpClient.optionsHttpClient.patch 以及 HttpClient.delete HTTP 动词。

Infrastructure 阶段拆分为 MonitoringFeatures 阶段

在大多数情况下,应该使用 Features 阶段取代 Infrastructure 阶段:

intercept(ApplicationCallPipeline.Infrastructure) {
    // ……
}

会成为:

intercept(ApplicationCallPipeline.Features) {
    // ……
}

CallId 与 CallLogging 中的 MDC 支持

CallLogging 特性已更新,允许指定与特定调用/请求关联而无需考虑 ThreadScheduler 的 MDC(已映射诊断上下文,Mapped Diagnostic Context)键 + 提供者。 该特性使用 kotlinx.coroutines 的 ThreadContextElement 实现, 因此它是透明的,并且适用于 slf4j。

0.9.5 包含一个新的 CallId 特性,该特性允许识别来自一个 ID 的调用。它提供了多种用来接收或者生成调用标识符(CallId Identifier)的方法,还可以选择将 id 包含为响应的一部分, 例如作为响应头。CallId 还与调用的 MDC 相关联,因此可以识别指定调用的日志并将其分组在一起。

0.9.4

Ktor 0.9.4 修复了一些 bug、升级了一些版本、移动了一些类、提高了服务器的整体性能。 这个版本弃用了一些 API、引入了一些新的 API,并且包含一个新版多平台 HTTP 客户端(初始支持 JVM、iOS 与 Android)。

这个版本预计与除了废弃的 API 之外的大部分 0.9.3 代码兼容。

https://github.com/ktorio/ktor/compare/0.9.3...0.9.4

发布于 2018-08-29

版本升级:

  • Kotlin: 1.2.50 -> 1.2.61
  • kotlin-native -> 0.8.2
  • jetty_alpn_boot_version: 8.1.11.v20170118 -> 8.1.12.v20180117
  • coroutines_version: 0.23.3 -> 0.25.0
  • atomic_fu_version: -> 0.11.3
  • kotlinx_io_version: -> 0.1.0-alpha-4

弃用:

潜在的轻微破坏性变更:

  • URL 构建:更改协议时也设置默认端口
  • 禁止向请求头中追加不安全的头
  • 客户端:io.ktor:ktor-client-json 构件已重命名为 io.ktor:io.ktor:ktor-client-gson(以支持新的 JacksonSerializer)
  • 现在所有与客户端 JSON 相关的(ktor-client-jsonktor-client-gsonktor-client-jackson)构件都需要 kotlinx.serialization,因此需要包含 maven { url "https://kotlin.bintray.com/kotlinx" } 仓库
  • 在一些指定的内部位置已将 Date 变更为 GMTDate
  • 内部客户端 HttpRequestHttpResponseHttpRequestData 变更
  • io.ktor.content 包已移动到 io.ktor.http.content
  • 顶层的 encodeURLQueryComponent 方法现在是 String 的一个扩展方法 fun String.encodeURLQueryComponent()
  • PartData.FileItem 现在需要返回 Input 而不是 InputStream 的 lambda 表达式参数
  • 现在 PartData 有一个新元素 PartData.BinaryItem,因此在表达式中使用时可能需要额外的分支或者 else 来全面覆盖

修复:

  • Netty:修复写入流水线避免过早丢弃连接。使用“Connection: close”无法完整发送很大的响应(#534
  • 修复 CharBufferBuilder 问题:响应头超过 2048 个字符的 CIO 响应会导致 IndexOutOfBoundsException#419
  • 修复使用 Netty 与 HTTP/2 时推送承诺资源头的顺序
  • 使用 Netty 与 HTTP/2 发送时消除发送 transfer-encoding
  • 修复了在 TestApplicationRequest.setBody 中使用二进制数据的编码问题
  • 修复原生 Deflater 泄露(#489
  • 修复 resourceResource 检查常规文件以防之后使用文件夹失败(#490
  • 修复静态资源解析中的 StringIndexOutOfBoundsException#493
  • 修复:当通过 -config=<filename> 传入配置时,不会解析环境变量(#374
  • 修复了流水线中的客户端连接关闭
  • TLS:修复预期通道关闭时的异常
  • 修复 Jetty 客户端引擎响应取消
  • 压缩:使用预定义的 identity 编码修复消息
  • 修复 HTTP 417 状态消息
  • 修复缺少 keyId 或损坏令牌的 JWT 错误处理
  • CIO:修复头处理中重复的 content-length
  • 修复 CIO 流水线不中断写入流水线。这导致流水线被取消,而 400 Bad Request 响应丢失
  • 修复 WriteChannelContent 的关闭字节通道错误处理
  • 修复 CIO 客户端 joining
  • 修复与 Netty 相关的导致空响应的竞争响应字节的问题 #350
  • 即使出现错误也避免关闭 ServletOutputStream
  • 抑制已完成的 AsyncContext 错误
  • 处理 Jetty 客户端引擎中的响应取消
  • 使 SessionTransportTransformerEncrypt 在失败时返回 null
  • 修复客户端属性求值

优化:

  • 在 Netty 中使用无垃圾的头 API
  • 避免在 Pipeline#merge 进行不必要的分配
  • 改进 ApplicationEngineEnvironmentReloading 中最佳函数选择
  • 不要在每个 HttpClient 实例化时扫描类路径,提供更好的错误消息

已有 API 改进:

  • JWK:以可选的颁发者添加验证配置
  • Url 与 URLBuilder 改进
  • 使 TypeInfo 成为一个数据类(#459)(#471
  • 测试:添加高级测试异常日志记录

  • 添加客户端表单数据与 multipart 支持(#500
  • 为 RFC 2518(WebDAV)中定义的状态代码添加 HttpStatusCode 常量

  • 添加 jetty 服务器引擎失败的回调处理程序(http2)
  • 将 Jetty 通道失败包装到 ChannelIOException
  • 使用 request 与 typeInfo 包装来自响应流水线的客户端异常

  • 添加追加头取值(例如 content type)的实用工具

  • 改进 HTTP/2 场景中的 netty 响应流水线
  • 根据系统所提供的随机算法设置默认随机算法

新特性:

  • 新版多平台 HTTP 客户端:
  • 添加初始 webjars 特性(#498
  • 添加 EngineAPI 标记注解
  • JacksonSerializer 添加到 HTTP 客户端
  • 客户端:添加 HttpResponse.receive 方法
  • 客户端:添加默认请求配置器
  • 客户端:配置或重新配置 HttpClient 引擎的新方法

内部变更:

  • 内部:更新模块布局

新版多平台 HTTP 客户端

自 Ktor 0.9.4 起,Ktor 附带了一个 MPP HTTP 客户端。

在 0.9.4 中,已为 JVM、 Android 与 iOS 实现该客户端。

我们提供了这个特性的样例作为 ktor-samples 版本库的一部分: ktor-samples/client-mpp

可以在多平台 HTTP 客户端页阅读关于这个特性的更多内容。

重新配置 HttpClientEngineConfig

在 0.9.4 之前,必须通过以下方式配置 HttpClient 引擎:

HttpClient(MyEngine.config {
    // …… 配置 ……
}) {
    install {
    }
}

自 0.9.4 起,HttpClientConfig 提供了一个 engine 方法来重新配置或配置 HttpClientEngineConfig

HttpClient(MyEngine) {
    engine {
        // …… 配置 ……
    }
    install {
    }
}

UnsafeHeaderException

经过一段时间的弃用,自 0.9.4 起,Ktor 开始完全禁止直接设置 contentTypecontentLength 头。 这是因为他们已绑定到 OutgoingContent 实例(即描述响应体的对象)上。

respondTextrespondBytes 以及一些其他方法允许设置作为可选参数的 Content-Type。 而当使用任何 OutgoingContent 的子类型时,可以在其中设置 contentType

关于这一主题的更多信息,请参见生成 HTTP 响应页。

GMTDate

在某些地方(如客户端 HttpResponse)我们之前使用了 Java 的 Date 类。现在我们改用 GMTDate 了。

客户端 HttpRequestHttpResponseHttpRequestData 变更

以前 HttpRequestData 有一个属性方法从其他 Attributes 实例构建一个 Attributes 实例。 现在它是一个属性。Attributes().apply { data.attributes(this) } 会成为 data.attributes

例如,这一变更会影响当实现 HttpRequest 时:

override val attributes: Attributes = Attributes().apply { data.attributes(this) }
// -->
//override val attributes: Attributes = data.attributes

并且 HttpResponse 已将它的 requestTimeresponseTime 由 java 的 Date 变更为 io.ktor.util.date.GMTDate

0.9.3

Ktor 0.9.3 修复了一些 bug、升级了一些版本、提高了服务器的整体性能, 而且引入了一些新的 API 并更改了一些 API。

这个版本预计与大部分 0.9.2 代码兼容, 与 kotlinx.coroutines 及 Ktor 原始套接字相关的高级使用场景除外。

https://github.com/ktorio/ktor/compare/0.9.2...0.9.3

发布于 2018-06-26

  • 改进 WebSocket API
  • Websocket 头 Sec-WebSocket-Key 现在是可选的
  • 修复了客户端 cookie 渲染以避免 x-enc
  • 修复了纯文本客户端读取器(#392
  • 在 CIO TLS 中添加了 EC 支持(#394:ECDHE_RSA_AES256_SHA384、 ECDHE_RSA_AES128_SHA256)
  • 修复客户端证书校验
  • 引入了可选的身份认证
  • 添加了 ApplicationCall 作为 auth 验证函数的接收者
  • 引入 call.respondBytes(#395
  • 改进 JWT 支持:多模式、 可空的发行者
  • 转换服务枚举类型诊断得到改进(#403
  • 避免了在 HTML 转义中使用 apos 实体因为 IE 不支持(#400
  • 转换器支持 java big number
  • 热添加 auth 方法到已有特性的能力
  • 改进了 auth 头模式与内容验证(#415
  • BasicAuth 的默认字符集现在是 UTF-8(#420
  • 添加了 ByteArrayContent.contentLength(#421
  • 修正了 headersOf 不区分大小写的问题(#426
  • 客户端通过使用类型 token 改进了反序列化
  • 禁用客户端默认变换器的能力
  • 客户端请求中的显式 Accept 头
  • 打开客户端 websocket 中的掩码(#423
  • 修复反转的 PartialContent.Configuration.maxRangeCount 校验(#440
  • 修复在 receiveOrNull() 中未捕获的 UnsupportedMediaTypeException(#442
  • 修复 multipart 边界头解析
  • 升级了 jwks/jwt,如果未指定,默认应用 RSA256(#434#435
  • 将 kotlinx.coroutines 升级到 0.23.3
  • 将 Jetty 版本升级到 9.4.11.v20180605
  • 添加 client-mock-engine 用于测试目的
  • HttpClient 允许使用默认的可用引擎(如果没有提供的话)
  • 将 kotlin 升级到 1.2.50
  • 将 ktor-samples 移动到独立的版本库(#340)。 https://github.com/ktorio/ktor-samples
  • 添加客户端重定向特性 *

客户端

WebSocket 改进

目前 webSocketSessionwebSocketRawSession 返回 DefaultClientWebSocketSession, 且 webSocketwswss 方法也接收 DefaultClientWebSocketSession 而其他方法返回 ClientWebSocketSession

这可以防止必须类型转换才能访问客户端会话中的某些属性:

var DefaultWebSocketSession.pingInterval: Duration?
var DefaultWebSocketSession.timeout: Duration
val DefaultWebSocketSession.closeReason: Deferred<CloseReason?>
var DefaultClientWebSocketSession.masking: Boolean

HttpClient MockEngine

我们(官方)有一个内部可用的 MockEngine 可用于测试时创建 HttpClient,能够通过代码以编程方式响应而无需执行任何请求。

现在我们已经在 io.ktor:ktor-client-mock 构件中公开了它。

例如:

val mockEngine = MockEngine { call -> // suspend HttpRequest.(call: HttpClientCall) -> MockHttpResponse
    assertEquals("*/*", headers[HttpHeaders.Accept])

    MockHttpResponse(call, HttpStatusCode.OK, writer(ioCoroutineDispatcher) { channel.writeStringUtf8("HELLO") }.channel, headersOf(
        "X-Custom-Header" to listOf("value")
    ))
}

val client = HttpClient(mockEngine)

MockEngine 块内部,可以断言来自请求的内容, 或者根据请求决定如何生成响应。

HttpClient 默认引擎

现在可以只通过 HttpClient() 而无需提供引擎来实例化一个 HttpClient。 在这种情况下会使用 ServiceLoader` 根据已包含的构件来查找合适的实现。

HttpClient 的 HttpRedirect 特性

现在,可以使用新版客户端的 HttpRedirect 特性来跟随基于 HTTP Location 的重定向。 更多信息请参阅其文档

HttpClient bug 修复

现在,HttpClient 使用单个头以标准的方式发送 cookie,每个 cookie 以 ; 分隔。

以前使用 Httpclient 将一个空正文作为 String 读取会引发 No transformation found: class io.ktor.client.engine.apache.ApacheHttpResponse -> class kotlin.String 异常:

HttpClientEngine 变更

HttpClientEngine 现在有一个 config 字段。因此如果自定义引擎必须提供这个字段。

HttpClient 变更

现在 HttpClient 会发送 Accept 头。如果有测试检测所有的头,那么需要更新该测试。

Socket

TLS 改进

Ktor 使用 CIO 实现了安全套接字,而在 0.9.3 之前可用的 TLS 中缺少了一些密钥算法套件与加密方法。现在我们(官方)更新了它以支持更多必要的东西。

你可能遇到的一些错误现在可能已修复:

  • Exception in thread "io-thread-1" io.ktor.network.tls.TLSException: Received alert during handshake. Level: FATAL, code: HandshakeFailure
  • Exception in thread "io-thread-2" io.ktor.network.tls.TLSException: Unsupported TLS handshake type CertificateRequest

aSocket 破坏性变更

现在需要提供 SelectorManager 给 aSocket

例如:

aSocket(ActorSelectorManager(ioCoroutineDispatcher))

当然,可以复用 SelectorManager:

val mySocketSelector = ActorSelectorManager(ioCoroutineDispatcher)
val socket = aSocket(mySocketSelector).tcp()

服务器

WebSocket 改进

在 0.9.3 之前,当一个 WS 请求没有 Sec-WebSocket-Key 头时, 会抛出 IllegalArgumentException 异常。现在这个头是可选的了。

可选的身份认证

现在可以定义一组提供可选身份认证的路由:

authenticate("method", optional = true) {
    // 路由
}


其认证行为:

  • 未提供认证:
    • optional=false:执行质疑
    • optional=true:以 principal=null 执行路由 handler
  • Wrong credentials: Unauthorized
  • Valid credentials: 以认证方法生成的 principal 执行路由 handler

缺失 call.respondBytes

在 0.9.3 之前我们有 call.respondText 但没有 call.respondBytes。现在解决了这个问题。

版本升级

Ktor 现在使用 Kotlin 1.2.50kotlinx.coroutines 0.23.3

对于一些高级使用场景,kotlinx.coroutines 有一些破坏性变更

generateCertificate

我们(官方)已经将用于生成自签名证书的 generateCertificate 函数移动到了 ktor-network-tls 构件中: compile("io.ktor:ktor-network-tls:$ktor_version")

新的 ktor-samples 版本库

在 0.9.3 之前,我们(官方)有多个样例项目直接集成在 ktor 版本库中。 由于样例的增长,我们已将其移动到其自身的版本库:https://github.com/ktorio/ktor-samples

0.9.2

Ktor 0.9.2 修复了一些 bug、提高了服务器的整体性能、开始部分支持 JVM 9, 而且引入了一些新的 API 并更改了一些 API。

在本节中,我们会讨论如何将现有代码从 0.9.1 迁移到 0.9.2。

  • 新版 auth DSL、更多可挂起函数(例如 verify/validate)
  • RoutingResolveTrace 用于自省路由解析过程
  • HTTP 客户端改进与 bug 修复(DSL、 重连、 重定向、 cookie、 websocket 等等)
  • CIO http 客户端流水线支持、分块等等
  • CIO 初步 TLS 支持
  • 会话认证提供者
  • OAuth2: 引入了生成和验证状态字段的能力
  • OAuth: 修复作用域参数以符合 RFC(#329
  • OAuth2: 修复双重作用域编码 bug(#370
  • OAuth2: 添加拦截重定向 URL 的能力
  • CORS: 引入了 allowSameOrigin 选项
  • Auth: 提供应用调用作为验证函数的接收者(#375 及相关问题)
  • 测试主机重写,handleRequest 可正确读取正文及重定向异常
  • Servlets: 修复 inputStream 获取,修复错误处理
  • Java 9 兼容性改进(还未支持模块化)
  • Digest auth 修复(#380
  • 记录运行连接器的详细信息以获得更好的开发体验(#318
  • Last-Modified 头及相关功能可用于正常的 GMT 时区(#344
  • IncomingContent 已弃用
  • URLBuilder 修复与改进
  • 文档改进
  • 性能优化(Netty、 CIO 服务端)
  • CIO 服务端提高稳定性
  • 加密会话支持(SessionTransportTransformerEncrypt)
  • 用于 freemarker 的空(null)模型(#291
  • 内容协商缺少 Accept 头支持(#317

身份认证

这一版本自 0.9.1 以来最大的变化就是身份认证。已经重新设计:

在以前版本中,必须在应用或者路由块内部定义 authentication 块, 将该认证应用于与该块匹配的所有子路由。

这迫使你重复定义多个身份认证提供者,或者在某些情况下会强制你在不需要的路由中包含身份认证。

authentication {
    basicAuthentication("ktor") { credentials ->
        if (credentials.password == "${credentials.name}123") UserIdPrincipal(credentials.name) else null
    }
}

在 0.9.2 中,所有认证机制都是在应用级定义的,并且有一个与其关联的可选的名称。 此外,用于定义不同机制的方法名称也已更改。现在,身份认证机制的新名称是函数调用的一部分,而所有其旧参数现在都使用 DSL 定义。

例如,如需定义一个基本身份认证 myauth1,应将以下代码添加到应用配置中:

install(Authentication) {
    basic(name = "myauth1") {
        realm = "Ktor Server"
        validate { credentials ->
            if (credentials.password == "${credentials.name}123") UserIdPrincipal(credentials.name) else null
        }
    }
}

现在,可以使用 authenticate 方法创建一个路由节点,将已定义的身份认证应用到多个路由:

routing {
    authenticate("myauth1") {
        get("/authenticated/route1") {
            // ……
        }
        get("/other/route2") {
            // ……
        }
    }
    get("/") {
        // ……
    }
}

认证方法名称变更:

  • basicAuthenticationbasic
  • formAuthenticationform
  • digestAuthenticationdigest
  • jwtAuthenticationjwt
  • oauthAuthenticationoauth

可以阅读新版身份认证页以详细了解如何使用新方法。

测试主机重写,handleRequest 可正确读取正文及重定向异常

TestApplicationRequest 构建器中的 body 属性已经更改为挂起的 setBody 方法:

handleRequest(HttpMethod.Post, "/") {
    addHeader("Accept", "text/plain")
    addHeader("Content-Type", "application/json")
    //body = """{"id":1,"title":"Hello, World!"}"""
    setBody("""{"id":1,"title":"Hello, World!"}""")
}.response.let { response ->
    // ……
}

在 0.9.2 之前,在请求不是同步生成响应主体的情况下, 必须在响应中调用方法 awaitCompletion。 在 0.9.2 中,awaitCompletion 方法不存在了, 并且在返回响应之前会自动等待完成。

IncomingContent 已弃用

如果你使用 call.request.receiveContent().readChannel()call.request.receiveContent().multiPartData() 或者 call.request.receiveContent().inputStream(),那么你应该考虑将其更改为 call.receive<ByteReadChannel>()call.receive<MultiPartData>() 与/或 call.receive<InputStream>(), 因其已弃用并会在未来版本的 Ktor 中移除。

另外,请记住 InputStream 是同步 API,所以如果可能的话尽量避免使用。

WebSocket

为了在客户端支持 WebSocket,我们(官方)更改了一些传递依赖关系并移动了一些类:现在有一个名为 ktor-http-cio 的传递依赖,它还包含了公共的 WebSocket 代码,而 ktor-websockets 服务端特性依赖于它。 但是由于它是传递依赖,所有对你来说应该是透明的。

WebSocketSessionFrame 这些类已经从 io.ktor.websocket 包移动到 io.ktor.http.cio.websocket 包中。

import io.ktor.websocket.*

import io.ktor.http.cio.websocket.*

HttpClient

在构建新版 CIO HttpClient 配置端点时 (它已从 endpointConfig 重命名为 endpoint,并且现在该属性是不可变的, 所以必须修改其内容):

在 0.9.2 之前:

val client = HttpClient(CIO.config {
    endpointConfig = EndpointConfig().apply {
    }
})

在 0.9.2 之后:

val client = HttpClient(CIO.config {
    endpoint.apply {
        // ……
    }
})