雖然 Ktor 官方已經提供了大量的套件,加上許多的第三方提供套件,基本上已經涵蓋了許多的功能。
不過,如果你有某一些需求,是常常會出現在不同專案內,並且現有的套件無法滿足的話。
立基於 Ktor 功能均以套件引入的設計架構,Ktor 也允許你自定義自己的套件,讓管理功能變得更加容易
參考 https://openaidoc.org/zh-Hant/ktor/server-custom-plugins
我們可以用 createApplicationPlugin
建立套件的物件
import io.ktor.server.application.*
val SimplePlugin = createApplicationPlugin(name = "SimplePlugin") {
println("SimplePlugin is installed!")
}
之後我們就可以用前面安裝套件一樣的方式,來安裝這個套件
fun Application.module() {
install(SimplePlugin)
}
作為後端服務的套件,我們可以針對幾個事件進行設定
onCall
:取得請求/回應資訊、修改回應參數。onCallReceive
:取得並轉換從用戶端接收的資料。onCallRespond
:在將資料傳送給用戶端之前進行轉換。這些比較常見的事件都有對應的函式,可以直接呼叫使用
val CustomHeaderPlugin = createApplicationPlugin(name = "CustomHeaderPlugin") {
onCall { call ->
call.response.headers.append("X-Custom-Header", "Hello, world!")
}
}
除了比較基本的這些事件,還有:
這些事件可以透過 on
函式處理
val AuthorizationPlugin = createRouteScopedPlugin(
name = "AuthorizationPlugin",
createConfiguration = ::PluginConfiguration
) {
val roles = pluginConfig.roles
val getRole = pluginConfig.getRole
pluginConfig.apply {
on(AuthenticationChecked) { call ->
val userName = call.principal<UserIdPrincipal>()?.name
val userRole = getRole(userName)
if (userRole !in roles) {
call.respondText("You are not allowed to visit this page", status = HttpStatusCode.Forbidden)
}
}
}
}
class PluginConfiguration {
var roles: Set<String> = emptySet()
lateinit var getRole : (userName: String?) -> String
}
如果需要存取 Application
內的伺服器設定,我們可以使用 applicationConfig
取得
val SimplePlugin = createApplicationPlugin(name = "SimplePlugin") {
val host = applicationConfig?.host
val port = applicationConfig?.port
println("Listening on $host:$port")
}
環境則是由 environment
取得
val SimplePlugin = createApplicationPlugin(name = "SimplePlugin") {
val isDevMode = environment?.developmentMode
onCall { call ->
if (isDevMode == true) {
println("handling request ${call.request.uri}")
}
}
}
今天的部分就到這邊,我們明天見!