bnorm/ktor-retrofit

How to get the call object in ServiceApi

Opened this issue · 3 comments

Or get authention info in ServiceApi

bnorm commented

There is no clean way using this library to access the call object. It is possible though, using io.ktor.util.pipeline.Pipeline#intercept to save and clear a reference to the ApplicationCall. With the ApplicationCall you can get the call principle with is the authentication info I think you are referencing.

routing {
  route("api") {
    val callRef = AtomicReference<ApplicationCall?>(null)
    intercept(ApplicationCallPipeline.ApplicationPhase.Call) {
      callRef.set(call)
      proceed()
      callRef.set(null)
    }
    retrofitService(service = MyService(callRef))
  }
}

It would also be possible to create an CoroutineContext.Element which can be added to the context on intercept.

Context element:

class ApplicationCallElement(val call: ApplicationCall) : CoroutineContext.Element {
  companion object Key : CoroutineContext.Key<ApplicationCallElement>
  override val key = Key
}

Context element access:

private suspend fun call() = coroutineContext[ApplicationCallElement]?.call ?: throw IllegalStateException()

Context element injection:

routing {
  route("api") {
    intercept(ApplicationCallPipeline.ApplicationPhase.Call) {
      withContext(coroutineContext + ApplicationCallElement(call)) {
        proceed()
      }
    }
    retrofitService(service = MyService())
  }
}

This is the direction I would go if adding this functionality to the library. I don't know enough about your use case though. What information are you needing from the ApplicationCall?

Just like get auth-info in ServiceApi.
At your prompt, I can put auth-info to the coroutineContext with interceptor.
Thanks a lot!

bnorm commented

Let's leave this open for now. This could be something the library provides out of the box.