gpt4 book ai didi

axios - 使用多个请求刷新访问 token

转载 作者:行者123 更新时间:2023-12-03 17:30:01 24 4
gpt4 key购买 nike

我正在努力让 axios 拦截器工作。

当我的 token 过期时,我需要它来刷新访问 token 并在 token 刷新后重试原始请求。
我有这部分工作。

问题是如果我有并发的 api 调用,它只会在 token 第一次无效时重试第一个请求。

这是我的拦截器代码:

    export default function execute() {
let isRefreshing = false

// Request
axios.interceptors.request.use(
config => {
var token = Storage.getAccessToken() //localStorage.getItem("token");
if (token) {
console.log('Bearer ' + token)
config.headers['Authorization'] = 'Bearer ' + token
}
return config
},
error => {
return Promise.reject(error)
}
)

// Response
axios.interceptors.response.use(
response => {
return response
},
error => {
const originalRequest = error.config
// token expired
if (error.response.status === 401) {
console.log('401 Error need to reresh')

originalRequest._retry = true

let tokenModel = {
accessToken: Storage.getAccessToken(),
client: 'Web',
refreshToken: Storage.getRefreshToken()
}
//Storage.destroyTokens();
var refreshPath = Actions.REFRESH

if (!isRefreshing) {
isRefreshing = true

return store
.dispatch(refreshPath, { tokenModel })
.then(response => {
isRefreshing = false
console.log(response)
return axios(originalRequest)
})
.catch(error => {
isRefreshing = false
console.log(error)
// Logout
})
} else {
console.log('XXXXX')
console.log('SOME PROBLEM HERE') // <------------------
console.log('XXXXX')
}
} else {
store.commit(Mutations.SET_ERROR, error.response.data.error)
}
return Promise.reject(error)
}
)
}

我不确定在上面突出显示的 else 块中需要什么。

编辑:

当我做
return axios(originalRequest)

在 else 块中它有效,但是我对这些行为不满意。它基本上一次又一次地重试所有请求,直到刷新 token 。
我宁愿在 token 刷新后重试一次
有任何想法吗

谢谢

最佳答案

您可以拥有额外的拦截器,它可以刷新 token 并执行您的待处理请求。

在此,countDownLatch类可以提供帮助。
这是示例拦截器代码,

class AutoRefreshTokenRequestInterceptorSample() : Interceptor {

companion object {
var countDownLatch = CountDownLatch(0)
var previousAuthToken = ""

const val SKIP_AUTH_TOKEN = "SkipAccessTokenHeader"
const val AUTHORIZATION_HEADER = "AUTHORIZATION_HEADER_KEY"
}

@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response? {
val request = chain.request()

if (shouldExecuteRequest(request)) {

// Execute Request
val response = chain.proceed(request)

if (!response.isSuccessful) {
// Failed Case
val errorBody = response.peekBody(java.lang.Long.MAX_VALUE).string()
val error = parseErrorModel(errorBody)

// Gives Signal to HOLD the Request Queue
countDownLatch = CountDownLatch(1)

handleError(error!!)

// After updating token values, execute same request with updated values.
val updatedRequest = getUpdatedRequest(request)

// Gives Signal to RELEASE Request Queue
countDownLatch.countDown()

//Execute updated request
return chain.proceed(updatedRequest)
} else {
// success case
return response
}
}

// Change updated token values in pending request objects and execute them!
// If Auth header exists, and skip header not found then hold the request
if (shouldHoldRequest(request)) {
try {
// Make this request to WAIT till countdown latch has been set to zero.
countDownLatch.await()
} catch (e: Exception) {
e.printStackTrace()
}

// Once token is Updated, then update values in request model.
if (previousAuthToken.isNotEmpty() && previousAuthToken != "newAccessToken") {
val updatedRequest = getUpdatedRequest(request)
return chain.proceed(updatedRequest)
}
}

return chain.proceed(request)
}

private fun handleError(error: ErrorDto) {
// update your token as per your error code logic
//Here it will make new API call to update tokens and store it in your local preference.
}

/***
* returns Request object with updated token values.
*/
private fun getUpdatedRequest(request: Request): Request {
var updateAuthReqBuilder: Request.Builder = request.newBuilder()
var url = request.url().toString()

if (url.contains(previousAuthToken.trim()) && previousAuthToken.trim().isNotEmpty()) {
url = url.replace(previousAuthToken, "newAccessToken")
}
updateAuthReqBuilder = updateAuthReqBuilder.url(url)
// change headers if needed
return updateAuthReqBuilder.build()
}

private fun shouldExecuteRequest(request: Request) =
shouldHoldRequest(request) && isSharedHoldSignalDisabled()

/**
* If count down latch has any value then it is reported by previous request's error signal to hold the whole pending chain.
*/
private fun isSharedHoldSignalDisabled() = countDownLatch.count == 0L

private fun shouldHoldRequest(request: Request) = !hasSkipFlag(request) && hasAuthorizationValues(request)

private fun hasAuthorizationValues(request: Request) = isHeaderExist(request, AUTHORIZATION_HEADER)

private fun hasSkipFlag(request: Request) = isHeaderExist(request, SKIP_AUTH_TOKEN)


private fun isHeaderExist(request: Request, headerName: String): Boolean {
return request.header(headerName) != null
}

private fun parseErrorModel(errorBody: String): Error? {
val parser = JsonParser()

// Change this logic according to your requirement.
val jsonObject = parser.parse(errorBody).asJsonObject
if (jsonObject.has("Error") && jsonObject.get("Error") != null) {
val errorJsonObj = jsonObject.get("Error").asJsonObject
return decodeErrorModel(errorJsonObj)
}
return null
}

private fun decodeErrorModel(jsonObject: JsonObject): Error {
val error = Error()
// decode your error object here
return error
}
}

关于axios - 使用多个请求刷新访问 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56327800/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com