Andrew Steinmetz
07/28/2022, 4:50 PMHttpReceivePipeline.After
to be able update this old plugin to Ktor 2.0? Looking at the old and new versions of Ktor, it looks as if context.request
is no longer accessible since the type on the receive pipeline is now Unit instead of HttpClientCall
?Andrew Steinmetz
07/28/2022, 4:51 PMclass OAuthFeature(
private val getToken: suspend () -> String,
private val refreshToken: suspend () -> Unit
) {
@KtorDsl
public class Config {
lateinit var getToken: suspend () -> String
lateinit var refreshToken: suspend () -> Unit
}
public companion object Feature : HttpClientPlugin<Config, OAuthFeature> {
override val key: AttributeKey<OAuthFeature> = AttributeKey("OAuth")
override fun prepare(block: Config.() -> Unit): OAuthFeature {
val config = Config().apply(block)
return OAuthFeature(config.getToken, config.refreshToken)
}
private val RefreshKey = "Ktor-OAuth-Refresh"
override fun install(plugin: OAuthFeature, scope: HttpClient) {
scope.requestPipeline.intercept(HttpRequestPipeline.State) {
// Add Refresh Header for handling infinite loop on 401s
context.headers[RefreshKey] = context.headers.contains("Authorization").toString()
// Add Authorization Header
val token = plugin.getToken()
Napier.d("Token: $token")
context.headers["Authorization"] = "Bearer $token"
proceed()
}
scope.receivePipeline.intercept(HttpReceivePipeline.After) {
// Request is unauthorized
if (subject.status == HttpStatusCode.Unauthorized && it.headers[RefreshKey] != true.toString()) {
try {
// Refresh the Token
plugin.refreshToken()
// Retry the request
val call = scope.requestPipeline.execute(
HttpRequestBuilder().takeFrom(context.request), // this is where request is no longer accessible
EmptyContent
) as HttpClientCall
// Proceed with the new request
proceedWith(call.response)
return@intercept
} catch (exception: Exception) {
// If refresh fails, proceed as 401
}
}
// Proceed as normal request
proceedWith(subject)
}
}
}
}
Andrew Steinmetz
07/28/2022, 5:20 PMHttpRequestBuilder().takeFrom(subject.call.request)
Aleksei Tirman [JB]
07/29/2022, 7:01 AMHttpRequestBuilder().takeFrom(it.call.request)
works too.