目录:
这是 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
改进:
修复:
小改动:
需要使用 Kotlin 1.3.0
或更高版本。该版本应该已经在 Maven Central 与 jcenter 上提供:
buildscript {
ext.kotlin_version = '1.3.0'
}
还需要在 IntelliJ IDEA 内使用 Kotlin 1.3。
这是 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
主要变更:
标记为实验性:
弃用:
新增:
小改动:
改进:
修复:
删除:
需要包含 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
)的反义词。
新名称反映了它作为应用程序的入口使用并且与环境无关,同时适用于开发环境与生产环境。
这是 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
新增:
改进:
修复:
性能提升:
文档:
小改动与清理:
需要包含 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
并安装该版本的插件。
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 变更:
ByteBufferBuilder
RoutingException
-> LocationRoutingException
HttpMessageBuilder.contentLength()
与 HttpMessage.contentLength()
现在返回 LongWebSocketInternalAPI
)AndroidClientEngine
现在是 @UseExperimental(InternalAPI::class)
Apache
的类型别名 ApacheBackend
修复:
新增:
TestApplicationEngine.cookiesSession
https://github.com/ktorio/ktor/commit/1af97b8fcb3096cb390480508c4abd49c13a34deContentTypes.CSV
#613IosClientEngineConfig
添加了 call.responseConfig.defaultCharset |
HttpResponseConfig |
API 改进:
小改动:
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
Ktor 0.9.5 是一个小更新,修复了一些 bug、升级了一些版本,并添加了一些小功能。
发布于 2018-09-19
版本升级:
Kotlin: 1.2.61 -> 1.2.70
潜在的轻微破坏性变更:
CookiesStorage.get
、 CookiesStorage.addCookie
以及 HttpCookies.get
现在接受 requestUrl
而不是主机名作为参数。现在 get 会返回一个 cookie 的列表。HttpRequest.takeFrom(builder: HttpRequestBuilder): HttpRequestBuilder
现在还将 builder
中的的类型化调用属性设置为成员方法。当使用星号导入 *
时不会有兼容性问题,因为它在相同的包内。修复:
新增:
CallId
特性CallLogging
特性添加了 MDC
支持API 改进:
HEAD
、 OPTIONS
、 PATCH
以及 DELETE
方法添加了简写客户端函数(#562)List<Cookie>.get(name: String): Cookie?
。fun FormBuilder.append(key: String, filename: String, block: BytePacketBuilder.() -> Unit)
。respondOutputStream { }
响应函数Infrastructure
阶段拆分为 Monitoring
与 Features
阶段内部变更:
AcceptAllCookiesStorage
对所有实现都相同。在 0.9.5 之前,当使用 HTTP 客户端并希望创建 HEAD
、 OPTIONS
、 PATCH
或者 DELETE
请求时,
必须使用 HttpClient.request
或 HttpClient.call
。
而对于 0.9.5,除了 HttpClient.get
与 HttpClient.post
之外,现在还有四个便利的方法
HttpClient.head
、 HttpClient.options
、 HttpClient.patch
以及 HttpClient.delete
HTTP 动词。
Infrastructure
阶段拆分为 Monitoring
与 Features
阶段在大多数情况下,应该使用 Features
阶段取代 Infrastructure
阶段:
intercept(ApplicationCallPipeline.Infrastructure) {
// ……
}
会成为:
intercept(ApplicationCallPipeline.Features) {
// ……
}
CallLogging 特性已更新,允许指定与特定调用/请求关联而无需考虑 ThreadScheduler 的 MDC(已映射诊断上下文,Mapped Diagnostic Context)键 + 提供者。 该特性使用 kotlinx.coroutines 的 ThreadContextElement 实现, 因此它是透明的,并且适用于 slf4j。
0.9.5 包含一个新的 CallId
特性,该特性允许识别来自一个 ID 的调用。它提供了多种用来接收或者生成调用标识符(CallId Identifier)的方法,还可以选择将 id 包含为响应的一部分,
例如作为响应头。CallId 还与调用的 MDC 相关联,因此可以识别指定调用的日志并将其分组在一起。
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
弃用:
response.contentType
与 response.contentLength
扩展(UnsafeHeaderException: Header Content is controlled by the engine and cannot be set explicitly
)IncomingContent
弃用,准备完全删除XForwardedHeadersSupport
重命名为 XForwardedHeaderSupport
(#547)潜在的轻微破坏性变更:
io.ktor:ktor-client-json
构件已重命名为 io.ktor:io.ktor:ktor-client-gson
(以支持新的 JacksonSerializer)ktor-client-json
、 ktor-client-gson
与 ktor-client-jackson
)构件都需要 kotlinx.serialization
,因此需要包含 maven { url "https://kotlin.bintray.com/kotlinx" }
仓库Date
变更为 GMTDate
HttpRequest
、 HttpResponse
与 HttpRequestData
变更io.ktor.content
包已移动到 io.ktor.http.content
encodeURLQueryComponent
方法现在是 String 的一个扩展方法 fun String.encodeURLQueryComponent()
PartData.FileItem
现在需要返回 Input
而不是 InputStream
的 lambda 表达式参数PartData
有一个新元素 PartData.BinaryItem
,因此在表达式中使用时可能需要额外的分支或者 else 来全面覆盖修复:
CharBufferBuilder
问题:响应头超过 2048 个字符的 CIO 响应会导致 IndexOutOfBoundsException
(#419)TestApplicationRequest.setBody
中使用二进制数据的编码问题StringIndexOutOfBoundsException
(#493)-config=<filename>
传入配置时,不会解析环境变量(#374)AsyncContext
错误SessionTransportTransformerEncrypt
在失败时返回 null优化:
HttpClient
实例化时扫描类路径,提供更好的错误消息已有 API 改进:
测试:添加高级测试异常日志记录
为 RFC 2518(WebDAV)中定义的状态代码添加 HttpStatusCode
常量
ChannelIOException
内使用 request 与 typeInfo 包装来自响应流水线的客户端异常
添加追加头取值(例如 content type)的实用工具
新特性:
EngineAPI
标记注解JacksonSerializer
添加到 HTTP 客户端HttpResponse.receive
方法内部变更:
自 Ktor 0.9.4 起,Ktor 附带了一个 MPP HTTP 客户端。
在 0.9.4 中,已为 JVM、 Android 与 iOS 实现该客户端。
我们提供了这个特性的样例作为 ktor-samples 版本库的一部分: ktor-samples/client-mpp
可以在多平台 HTTP 客户端页阅读关于这个特性的更多内容。
在 0.9.4 之前,必须通过以下方式配置 HttpClient 引擎:
HttpClient(MyEngine.config {
// …… 配置 ……
}) {
install {
}
}
自 0.9.4 起,HttpClientConfig
提供了一个 engine
方法来重新配置或配置 HttpClientEngineConfig
:
HttpClient(MyEngine) {
engine {
// …… 配置 ……
}
install {
}
}
经过一段时间的弃用,自 0.9.4 起,Ktor 开始完全禁止直接设置 contentType
与 contentLength
头。
这是因为他们已绑定到 OutgoingContent
实例(即描述响应体的对象)上。
respondText
、 respondBytes
以及一些其他方法允许设置作为可选参数的 Content-Type。
而当使用任何 OutgoingContent
的子类型时,可以在其中设置 contentType
。
关于这一主题的更多信息,请参见生成 HTTP 响应页。
在某些地方(如客户端 HttpResponse
)我们之前使用了 Java 的 Date
类。现在我们改用 GMTDate
了。
HttpRequest
、 HttpResponse
与 HttpRequestData
变更以前 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
已将它的 requestTime
与 responseTime
由 java 的 Date
变更为 io.ktor.util.date.GMTDate
。
Ktor 0.9.3 修复了一些 bug、升级了一些版本、提高了服务器的整体性能, 而且引入了一些新的 API 并更改了一些 API。
这个版本预计与大部分 0.9.2 代码兼容,
与 kotlinx.coroutines
及 Ktor 原始套接字相关的高级使用场景除外。
kotlinx.coroutines
的破坏性变更。ktor 原始套接字
的破坏性变更。https://github.com/ktorio/ktor/compare/0.9.2...0.9.3
发布于 2018-06-26
目前 webSocketSession
与 webSocketRawSession
返回 DefaultClientWebSocketSession
,
且 webSocket
、 ws
与 wss
方法也接收 DefaultClientWebSocketSession
而其他方法返回 ClientWebSocketSession
。
这可以防止必须类型转换才能访问客户端会话中的某些属性:
var DefaultWebSocketSession.pingInterval: Duration?
var DefaultWebSocketSession.timeout: Duration
val DefaultWebSocketSession.closeReason: Deferred<CloseReason?>
var DefaultClientWebSocketSession.masking: Boolean
我们(官方)有一个内部可用的 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。
在这种情况下会使用 ServiceLoader` 根据已包含的构件来查找合适的实现。
现在,可以使用新版客户端的 HttpRedirect 特性来跟随基于 HTTP Location
的重定向。
更多信息请参阅其文档。
现在,HttpClient 使用单个头以标准的方式发送 cookie,每个 cookie 以 ;
分隔。
以前使用 Httpclient 将一个空正文作为 String 读取会引发
No transformation found: class io.ktor.client.engine.apache.ApacheHttpResponse -> class kotlin.String
异常:
HttpClientEngine 现在有一个 config
字段。因此如果自定义引擎必须提供这个字段。
现在 HttpClient 会发送 Accept
头。如果有测试检测所有的头,那么需要更新该测试。
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
现在需要提供 SelectorManager 给 aSocket
。
例如:
aSocket(ActorSelectorManager(ioCoroutineDispatcher))
当然,可以复用 SelectorManager:
val mySocketSelector = ActorSelectorManager(ioCoroutineDispatcher)
val socket = aSocket(mySocketSelector).tcp()
在 0.9.3 之前,当一个 WS 请求没有 Sec-WebSocket-Key
头时,
会抛出 IllegalArgumentException
异常。现在这个头是可选的了。
现在可以定义一组提供可选身份认证的路由:
authenticate("method", optional = true) {
// 路由
}
其认证行为:
optional=false
:执行质疑optional=true
:以 principal=null 执行路由 handler在 0.9.3 之前我们有 call.respondText
但没有 call.respondBytes
。现在解决了这个问题。
Ktor 现在使用 Kotlin 1.2.50
与 kotlinx.coroutines 0.23.3
。
对于一些高级使用场景,kotlinx.coroutines 有一些破坏性变更。
我们(官方)已经将用于生成自签名证书的 generateCertificate
函数移动到了 ktor-network-tls
构件中:
compile("io.ktor:ktor-network-tls:$ktor_version")
在 0.9.3 之前,我们(官方)有多个样例项目直接集成在 ktor 版本库中。 由于样例的增长,我们已将其移动到其自身的版本库:https://github.com/ktorio/ktor-samples
Ktor 0.9.2 修复了一些 bug、提高了服务器的整体性能、开始部分支持 JVM 9, 而且引入了一些新的 API 并更改了一些 API。
在本节中,我们会讨论如何将现有代码从 0.9.1 迁移到 0.9.2。
这一版本自 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("/") {
// ……
}
}
认证方法名称变更:
basicAuthentication
→ basic
formAuthentication
→ form
digestAuthentication
→ digest
jwtAuthentication
→ jwt
oauthAuthentication
→ oauth
可以阅读新版身份认证页以详细了解如何使用新方法。
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
方法不存在了,
并且在返回响应之前会自动等待完成。
如果你使用 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,我们(官方)更改了一些传递依赖关系并移动了一些类:现在有一个名为 ktor-http-cio
的传递依赖,它还包含了公共的
WebSocket 代码,而 ktor-websockets
服务端特性依赖于它。
但是由于它是传递依赖,所有对你来说应该是透明的。
像 WebSocketSession
与 Frame
这些类已经从 io.ktor.websocket
包移动到
io.ktor.http.cio.websocket
包中。
import io.ktor.websocket.*
→
import io.ktor.http.cio.websocket.*
在构建新版 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 {
// ……
}
})