Ktor offers an Attributes
class that acts as a small typed instance container/dependency injector.
For the server, the ApplicationCall
contains an attributes
property including an instance of this class (call.attributes
).
The lifespan of this container is the call: beginning when the request has started and ending when the response has been sent.
You can set as many attributes as required per call on an interceptor and retrieve them later in another interceptor.
In the case of the client, the HttpRequest
also contains an attributes
property.
So from a HttpClientCall
instance, you can access the attributes with call.request.attributes
.
It is possible to define your own typed attributes by creating instances of the AttributeKey
class like this:
// Declared as a global property
val MyAttributeKey = AttributeKey<Int>("MyAttributeKey")
You can later set the attributes with:
attributes.put(MyAttributeKey, 10)
And retrieve them in another interceptor by calling:
attributes.get(MyAttributeKey)
The full interface for this class looks like:
interface Attributes {
operator fun <T : Any> get(key: AttributeKey<T>): T
fun <T : Any> getOrNull(key: AttributeKey<T>): T?
operator fun contains(key: AttributeKey<*>): Boolean
fun <T : Any> put(key: AttributeKey<T>, value: T)
fun <T : Any> remove(key: AttributeKey<T>)
fun <T : Any> take(key: AttributeKey<T>): T = get(key).also { remove(key) }
fun <T : Any> takeOrNull(key: AttributeKey<T>): T? = getOrNull(key).also { remove(key) }
fun <T : Any> computeIfAbsent(key: AttributeKey<T>, block: () -> T): T
val allKeys: List<AttributeKey<*>>
}