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)
}
}
}