常见问题

预计阅读时间: 6 分钟

在本节中,我们(官方)为大家经常问我们的问题提供答案。

你的问题没有找到答案吗?请关注我们(官方)的 #ktor Kotlin Slack 频道, 我们会尽力帮助你。

目录:

ktor 的正确发音是什么?

kay-tor

如何提出问题、报告 bug、与你联系、做出贡献、提供反馈等?

根据具体内容,可以考虑以下几个渠道:

  • GitHub: 功能请求、更改建议/提议、bug 以及 PR。
  • Slack: 问题、疑难解决、指导等。
  • StackOverflow: 问题。

理由:

对于问题或疑难解决,我们强烈建议使用 Slack 或者 StackOverflow。

考虑到使用 GitHub issues 会通知所有可能通过电子邮件订阅的人, 疑难解决通常需要几个问题与答案,这可能会一时产生很多电子邮件,也许订阅的人们希望了解 bug、修复、引入或提出的新功能相关内容,而对其他事情也许并不感兴趣。

如果有足够时间或者并不想加入 Slack,也可以在 StackOverflow 上提问。 鉴于 slack 是聊天与论坛的混合体,我们可以更快地相互联系并且在更短的时间内解决问题。

在进行疑难解决时,如果我们确定存在 bug 或需要改进的地方,可以在 GitHub 上报告。 当然,在 Slack 中进行 bug 报告(一旦确认)并不是一个好主意,因为可能会被遗忘, 所以我们将其放在 GitHub 中。

Pull Requests:

如果有一项你认为值得包含进 Ktor 的功能或者 bug 修复,可以创建 PR。

请记住,我们通常会批量评审与合并 PR,因此该 PR 可能会等待几周。 不过,如果可以,我们仍然鼓励你做出贡献!

如果你有一个需要立即使用的 bug 修复,我们建议你 fork Ktor、 自行编译,然后在自己的 artifactory、bintray 或者类似的地方临时发布打补丁后的版本, 直到它被合并并且随新版本发布(因为时间安排可能不能满足你的需求)。

CIO 是什么意思?

CIO 代表基于协程的 I/O(Coroutine-based I/O)。 通常我们称之为引擎,它使用 Kotlin 以及协程来实现 IETF RFC 或者其他协议的逻辑,而不依赖基于 JVM 的外部库。

Ktor 导入不能解析。导入是红的。

请确保包含了 ktor 构件。例如,对于 gradle 及 Netty 引擎会是:

dependencies {
    compile("io.ktor:ktor-server-netty:$ktor_version")
}

ktor 是否提供了捕获 IPC 信号(如 SIGTERM 或 SIGINT)的方法,以便可以优雅处理服务器关机?

如果运行的是 DevelopmentEngine/EngineMain,那么会自动处理。

否则必须手动处理。 可以使用 JVM 的 Runtime.getRuntime().addShutdownHook 工具。

如何在代理服务器后获取客户端 IP?

如果代理服务器提供了正确的头,并且已安装 XForwardedHeaderSupport 特性, 那么 call.request.origin 属性会提供原始调用者(代理)的连接信息。

出现错误“java.lang.IllegalStateException: No instance for key AttributeKey: Locations”

如果试图使用 location 特性但没有实际安装它,就会出现这个错误。请查阅 location 特性: https://ktor.kotlincn.net/features/locations.html

如何测试 master 上的最新提交?

可以使用 jitpack 从 master 获取尚未发布的版本: https://jitpack.io/#ktorio/ktor 也可以从源代码构建 Ktor 并使用 mavenLocal 仓库提供构件, or to upload your artifacts to your own artifactory/bintray.

如何确定我用的是哪个版本的 Ktor?

可以使用 DefaultHeaders 特性来发送一个包含 Ktor 版本的 Server 头。 所发送的响应头中包含类似这样的内容: Server: ktor-server-core/1.0.0 ktor-server-core/1.0.0

网站辅助技巧与窍门

可以在文档网站的任何页面中使用 s 键(搜索)、t 键(github 文件查找器风格)或者 # 键访问搜索。 # 版限制为只在当前页的各节标题中搜索。

在搜索时,既可以使用鼠标(或者触屏上使用手指)选择选项,也可以使用键盘的箭头 与回车键 转到到当前所选页面。

这项搜索只使用页面标题与关键字搜索。也可以在 ktor.kotlincn.net 域名下使用谷歌搜索对其所有内容进行全文检索。

折叠的大段代码,既可以在移动设备上可以通过点击一直出现在左上角的 '+'/'-' 号来展开 、在有鼠标的设备通过鼠标悬停展开(译者注:实测不可行)。 也可以双击代码片段来展开。 除了展开之外,这一操作还会选中这段文本,于是可以轻松复制该代码段: 在 mac 上使用 cmd + c,而在其他操作系统中使用 ctrl + c

可以点击标题以及一些注记来获取对应节的锚点链接。 点击后,可以在浏览器中复制包含 # 链向该页中指定节的新 url。

我的路由没有执行到,该如何调试?

Ktor 为路由功能提供了跟踪机制以帮助解决路由决策问题。请查阅路由页的追踪路由决策一节。

出现报错 io.ktor.pipeline.InvalidPhaseException: Phase Phase('YourPhase') was not registered for this pipeline.

这意味着正在试图使用一个未注册为另一阶段(phase)引用的阶段。 例如,这可能发生在路由功能中,当尝试在一个节点内部注册阶段关系, 但是所引用的阶段在另一个祖先 Route 节点中定义。 由于路由阶段与拦截器稍后才合并,因此应该能生效,不过需要在 Route 节点中注册:

route.addPhase(PhaseDefinedInAncestor)
route.insertPhaseAfter(PhaseDefinedInAncestor, MyNodePhase)

出现报错 io.ktor.server.engine.BaseApplicationResponse$ResponseAlreadySentException: Response has already been sent

这意味着你或者一个特性或拦截器已经调用了 call.respond* 函数,而你又再次调用了它

如何订阅 Ktor 事件?

这里有一个解释 Ktor 应用级事件系统的页面。

出现 Exception in thread "main" com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'ktor' 异常

这意味着 Ktor 无法找到 application.conf 文件。请重新检查它是否在 resources 文件夹中并且该资源文件夹已正确标记。 可以考虑使用项目生成器或者 IntelliJ 插件搭建项目作为工作项目的基础。

可以在 Android 上使用 ktor 吗?

已知 Ktor 适用于 Android 7 或更高版本(API 24)。会在 Android 5 等较低版本中失败。

在不支持的版本中会失败并出现类似以下异常:

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.mypackage.example, PID: 4028 java.lang.NoClassDefFoundError:
io.ktor.application.ApplicationEvents$subscribe$1 at io.ktor.application.ApplicationEvents.subscribe(ApplicationEvents.kt:18) at
io.ktor.server.engine.BaseApplicationEngine.<init>(BaseApplicationEngine.kt:29) at
io.ktor.server.engine.BaseApplicationEngine.<init>(BaseApplicationEngine.kt:15) at
io.ktor.server.netty.NettyApplicationEngine.<init>(NettyApplicationEngine.kt:17) at io.ktor.server.netty.Netty.create(Embedded.kt:10) at
io.ktor.server.netty.Netty.create(Embedded.kt:8) at io.ktor.server.engine.EmbeddedServerKt.embeddedServer(EmbeddedServer.kt:50) at
io.ktor.server.engine.EmbeddedServerKt.embeddedServer(EmbeddedServer.kt:40) at
io.ktor.server.engine.EmbeddedServerKt.embeddedServer$default(EmbeddedServer.kt:27)

更多相关信息,请查阅问题 #495 以及 StackOverflow 上的问题

CURL -I 返回 404 Not Found

CURL -I 是执行 HEAD 请求的 CURL --head 的别名。 默认情况下,Ktor 不会处理对 GET 处理程序的 HEAD 请求,因此可能会遇到类似这样的内容:

curl -I http://localhost:8080
HTTP/1.1 404 Not Found
Content-Length: 0

对于:

routing {
    get("/") { call.respondText("HELLO") }
}

Ktor 可以自动处理 HEAD 请求,不过需要先安装 AutoHeadResponse 特性

install(AutoHeadResponse)

我在使用 HttpsRedirect 特性时出现了无限重定向

最可能的原因是你的后端服务位于反向代理或者负载均衡之后,而这些间接层正在向你的后端服务发出正常的 HTTP 请求,因此你的 Ktor 后端服务内部的 HttpsRedirect 特性认为它是正常 HTTP 请求并以重定向进行响应。

通常,反向代理会发送一些描述原始请求的头(例如它是 HTTPS,或者原始 IP 地址), 并且有一个特性 XForwardedHeaderSupport 会解析这些头,所以 HttpsRedirect 特性知道原始请求是 HTTPS。