All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.com.apollographql.apollo3.interceptor.BearerTokenInterceptor.kt Maven / Gradle / Ivy

package com.apollographql.apollo3.interceptor

import com.apollographql.apollo3.ApolloRequest
import com.apollographql.apollo3.exception.ApolloHttpException
import com.apollographql.apollo3.exception.ApolloBearerTokenException
import com.apollographql.apollo3.api.Operation
import com.apollographql.apollo3.api.ApolloResponse
import com.apollographql.apollo3.network.http.HttpRequestParameters
import com.apollographql.apollo3.network.http.withHeader
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.retry
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

class BearerTokenInterceptor(private val tokenProvider: TokenProvider) : ApolloRequestInterceptor {
  private val mutex = Mutex()

  private fun  ApolloRequest.withHeader(name: String, value: String): ApolloRequest {
    return withExecutionContext(executionContext[HttpRequestParameters].withHeader(name, value))
  }

  private fun  proceedWithToken(
      request: ApolloRequest,
      interceptorChain: ApolloInterceptorChain,
      token: String
  ): Flow> {
    val newRequest = request.withHeader("Authorization", "Bearer $token")
    return interceptorChain.proceed(newRequest)
  }

  @FlowPreview
  @ExperimentalCoroutinesApi
  override fun  intercept(request: ApolloRequest, chain: ApolloInterceptorChain): Flow> {
    return flow {
      val token = mutex.withLock { tokenProvider.currentToken() }
      emit(token)
    }.flatMapConcat { token ->
      proceedWithToken(request, chain, token).catch { exception ->
        if (exception is ApolloHttpException && exception.statusCode == 401) {
          throw ApolloBearerTokenException(message = "Request failed with status code `401`", cause = exception, token = token)
        } else {
          throw exception
        }
      }
    }.retry(retries = 1) { error ->
      if (error is ApolloBearerTokenException) {
        tokenProvider.refreshToken(error.token)
        true
      } else {
        false
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy