Adam Papenhausen
11/07/2023, 12:15 AM/** Adds the package name as headers for every request. */
class BuildMetadataMiddleware @Inject constructor(private val packageInfoProvider: PackageInfoProvider) : Interceptor {
companion object {
const val ClientNameHeader = "X-Client-Name"
}
override fun intercept(chain: Interceptor.Chain): Response = chain.proceed(
chain.request().newBuilder()
.addHeader(ClientNameHeader, packageInfoProvider.packageName)
.build()
)
}
I can then create a test client and assert on the intercept
method with a fake PackageInfoProvider
. With Ktor, it doesn't immediately seem that you want to subclass the ClientPlugin
interface but rather provide a plugin config class, which to my understanding requires a default value. I have two questions:
• How can I implement this if I do not want a default value (always have it be provided by the injected dependency)
• How can a plugin fail safely? Would I need to create custom exceptions and handle them or is there an API like request.cancel(reason)
?
This is what the above impl could look like in Ktor:
class BuildMetadataConfig {
val packageName: String? = null
}
val buildMetadataPlugin = createClientPlugin("BuildMetadata", ::BuildMetadataConfig) {
val packageName = pluginConfig.packageName
onRequest { request, _ ->
request.header("X-Client-Name", packageName)
}
}
Aleksei Tirman [JB]
11/07/2023, 8:20 AMX-Client-Name
header on each request?Adam Papenhausen
11/07/2023, 3:21 PMAleksei Tirman [JB]
11/07/2023, 3:23 PMAdam Papenhausen
11/07/2023, 3:24 PMPackageInfoProvider
interface that gets injected where the client is createdval buildMetadataPlugin = fun(packageInfoProvider: PackageInfoProvider) = createClientPlugin(...)
Aleksei Tirman [JB]
11/07/2023, 3:30 PMAdam Papenhausen
11/07/2023, 3:33 PMAleksei Tirman [JB]
11/07/2023, 3:34 PMAdam Papenhausen
11/07/2023, 3:37 PMAleksei Tirman [JB]
11/08/2023, 6:45 AM