Home > Enterprise >  Ktor 2 - How to add thread local data for a request?
Ktor 2 - How to add thread local data for a request?

Time:05-02

Before Ktor 2 it was possible to use withContext(threadLocal.asContextElement(..)) { proceed() } inside an ApplicationFeature to add thread local data to a request, but the new createApplicationPlugin api doesn't seem to provide this option. Is it still possible? It sounds like a pretty common use case...?

CodePudding user response:

Think I figured it out after a lot of digging through Ktors source code. I think the new plugin api in Ktor 2 is an improvement, but it is still ridiculously difficult to do something that would be five-ish lines of code with a ServletFilter...

val ServerTracerPlugin = createApplicationPlugin(
    name = "KtorServerTracerPlugin",
    createConfiguration = ::KtorTracingPluginConfig
) {

    on(TracerHook()) { call, block ->
        // ...

        withContext(threadLocalStorage.asContextElement(..)) {
            block()
        }
    }
}

class TracerHook : Hook<suspend (ApplicationCall, suspend () -> Unit) -> Unit> {
    override fun install(
        pipeline: ApplicationCallPipeline,
        handler: suspend (ApplicationCall, suspend () -> Unit) -> Unit
    ) {
        val phase = ApplicationCallPipeline.Monitoring
        val namedPhase = PipelinePhase("${phase.name}Trace")
        pipeline.insertPhaseBefore(phase, namedPhase)

        pipeline.intercept(namedPhase) {
            handler(call, ::proceed)
        }
    }
}
  • Related