Skip to content

Commit

Permalink
feat: migrate to ktor 3 (#459)
Browse files Browse the repository at this point in the history
  • Loading branch information
darkxanter authored Dec 1, 2024
1 parent b3cc6a9 commit e1960a2
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package org.kodein.di.ktor
import io.ktor.server.application.*
import io.ktor.server.routing.*
import io.ktor.util.*
import io.ktor.util.pipeline.*
import org.kodein.di.DI
import org.kodein.di.LazyDI

Expand Down Expand Up @@ -50,7 +49,6 @@ public fun Route.closestDI(): LazyDI {
/**
* Getting the global [DI] container from the [ApplicationCall]
*/
public fun PipelineContext<*, ApplicationCall>.closestDI(): LazyDI {
val routingCall = (this.call as RoutingApplicationCall)
return routingCall.route.closestDI()
public fun RoutingContext.closestDI(): LazyDI {
return call.route.closestDI()
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.kodein.di.ktor

import io.ktor.server.application.*
import io.ktor.server.routing.RoutingCall
import io.ktor.server.sessions.*
import org.kodein.di.bindings.Scope
import org.kodein.di.bindings.ScopeRegistry
Expand Down Expand Up @@ -68,5 +69,13 @@ public inline fun <reified T : Any> CurrentSession.clearSessionScope() {
}
//endregion
//region Request scope
public object CallScope : WeakContextScope<ApplicationCall>()
public object CallScope : WeakContextScope<ApplicationCall>() {
override fun getRegistry(context: ApplicationCall): ScopeRegistry {
val actualContext = when (context) {
is RoutingCall -> context.pipelineCall
else -> context
}
return super.getRegistry(actualContext)
}
}
//endregion
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ package org.kodein.di.ktor
import io.ktor.server.application.Application
import io.ktor.server.application.ApplicationCall
import io.ktor.server.application.ApplicationCallPipeline
import io.ktor.server.application.application
import io.ktor.server.application.Hook
import io.ktor.server.application.call
import io.ktor.server.application.createRouteScopedPlugin
import io.ktor.server.application.install
import io.ktor.server.application.log
import io.ktor.server.plugins.defaultheaders.DefaultHeaders
import io.ktor.server.request.httpMethod
import io.ktor.server.request.uri
import io.ktor.server.response.respondText
import io.ktor.server.routing.application
import io.ktor.server.routing.get
import io.ktor.server.routing.post
import io.ktor.server.routing.route
Expand All @@ -19,8 +21,10 @@ import io.ktor.server.sessions.SessionStorageMemory
import io.ktor.server.sessions.Sessions
import io.ktor.server.sessions.cookie
import io.ktor.server.sessions.get
import io.ktor.server.sessions.reflectionSessionSerializer
import io.ktor.server.sessions.sessions
import io.ktor.server.sessions.set
import io.ktor.util.pipeline.PipelinePhase
import org.kodein.di.DI
import org.kodein.di.bind
import org.kodein.di.instance
Expand Down Expand Up @@ -73,6 +77,7 @@ private fun Application.sessionModule() {
install(Sessions) {
cookie<MockSession>("SESSION_FEATURE_SESSION_ID", SessionStorageMemory()) {
cookie.path = "/" // Specify cookie's path '/' so it can be used in the whole site
serializer = reflectionSessionSerializer()
}
}

Expand Down Expand Up @@ -116,37 +121,51 @@ fun Application.requestModule() {
routing {
route(ROUTE_REQUEST) {
suspend fun logPhase(
phase: String,
applicationCall: ApplicationCall,
proceed: suspend () -> Unit
phase: String,
applicationCall: ApplicationCall,
proceed: suspend () -> Unit
) {
val random by closestDI().on(applicationCall).instance<Random>()
randomDto.randomInstances.add(phase to "$random")
this@requestModule.log.info("Context $applicationCall / DI ${closestDI().container} / $phase Random instance: $random")
proceed()
}

intercept(ApplicationCallPipeline.Setup) {
randomDto.randomInstances.clear()
logPhase("[Setup]", context) { proceed() }
}
intercept(ApplicationCallPipeline.Monitoring) {
logPhase("[Monitoring]", context) { proceed() }
}
intercept(ApplicationCallPipeline.Plugins) {
logPhase("[Features]", context) { proceed() }
}
intercept(ApplicationCallPipeline.Call) {
logPhase("[Call]", context) { proceed() }
}
intercept(ApplicationCallPipeline.Fallback) {
logPhase("[Fallback]", context) { proceed() }
val interceptor = createRouteScopedPlugin("Interceptor") {
class PhaseHook(val phase: PipelinePhase) : Hook<suspend (ApplicationCall) -> Unit> {
override fun install(
pipeline: ApplicationCallPipeline,
handler: suspend (ApplicationCall) -> Unit
) {
pipeline.intercept(phase) {
handler(call)
proceed()
}
}
}
on(PhaseHook(ApplicationCallPipeline.Setup)) {
randomDto.randomInstances.clear()
logPhase("[Setup]", it) { }
}
on(PhaseHook(ApplicationCallPipeline.Monitoring)) {
logPhase("[Monitoring]", it) { }
}
on(PhaseHook(ApplicationCallPipeline.Plugins)) {
logPhase("[Plugins]", it) { }
}
on(PhaseHook(ApplicationCallPipeline.Call)) {
logPhase("[Call]", it) { }
}
on(PhaseHook(ApplicationCallPipeline.Fallback)) {
logPhase("[Fallback]", it) { }
}
}
install(interceptor)

get {
val random by closestDI().on(context).instance<Random>()
val random by closestDI().on(call).instance<Random>()
application.log.info("DI ${closestDI().container} / Random instance: $random")
logPhase("[GET]", context) {
logPhase("[GET]", call) {
call.respondText(randomDto.randomInstances.joinToString { "${it.first}=${it.second}" })
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class KtorTests {
keyValue.first() to keyValue.last()
}

assertEquals(5, pairs.size) // Ensure we pass through 5 phases (Setup, Monitoring, Features, Call, GET)
assertEquals(5, pairs.size) // Ensure we pass through 5 phases (Setup, Monitoring, Plugins, Call, GET)
assertEquals(1, pairs.map { it.second }.distinct().count()) // For all the phases we only have 1 Random instance
}

Expand Down
5 changes: 2 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ compose-bom = "2024.05.00"
kotlinpoet = "1.14.2"
ksp = "1.9.20-1.0.14"
# Ktor
ktor = "2.3.6"
ktor = "3.0.1"
# JxInject
javax-inject = "1"
# TornadoFX
Expand Down Expand Up @@ -52,8 +52,7 @@ ksp-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.re
# Ktor
ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
ktor-server-sessions = { module = "io.ktor:ktor-server-sessions", version.ref = "ktor" }
ktor-test-server-host = { module = "io.ktor:ktor-server-test-host", version.ref = "ktor" }
ktor-test-server = { module = "io.ktor:ktor-server-tests", version.ref = "ktor" }
ktor-test-server = { module = "io.ktor:ktor-server-test-host", version.ref = "ktor" }
ktor-test-server-default-headers = { module = "io.ktor:ktor-server-default-headers", version.ref = "ktor" }
# JxInject
javax-inject = { module = "javax.inject:javax.inject", version.ref = "javax-inject" }
Expand Down

0 comments on commit e1960a2

Please sign in to comment.