我有下一个 api 客户端。我用的是ofetch
https://github.com/unjs/ofetch
import { $fetch, FetchContext, FetchOptions, Headers } from 'ohmyfetch'
import AuthModule from '~~/repository/modules/auth'
export interface ApiInstance {
auth: AuthModule
}
export default defineNuxtPlugin((nuxtApp) => {
const refreshTokenCookie = useCookie('refreshToken')
const fetchOptions: FetchOptions = {
baseURL: nuxtApp.$config.public.apiBase,
onRequest(ctx: FetchContext): Promise<void> | void {
const tokenCookie = useCookie('accessToken')
ctx.options.headers = new Headers(
{
'Authorization': `Bearer ${tokenCookie.value}`
}
)
},
async onResponseError({ request, response, options }) {
if (response.status === 401) {
await $fetch('/auth/refresh', {
baseURL: nuxtApp.$config.public.apiBase,
method: 'POST',
body: { refresh_token: refreshTokenCookie.value }
})
}
}
}
const apiFetcher = $fetch.create(fetchOptions)
const modules: ApiInstance = {
auth: new AuthModule(apiFetcher),
}
return {
provide: {
api: modules
}
}
})
在 onResponseError 函数中,如果错误为 401,我会发出刷新请求。 刷新后我需要重复之前的请求。
有人可以告诉我该怎么做吗?
谢谢:)
更新 我刷新了
import { $fetch, FetchContext, FetchOptions, Headers } from 'ohmyfetch'
import { useAuthStore } from "~/store/auth"
import AuthModule from '~~/repository/modules/auth'
import CategoryModule from '~/repository/modules/category'
export interface ApiInstance {
auth: AuthModule
category: CategoryModule
}
export default defineNuxtPlugin((nuxtApp) => {
const refreshTokenCookie = useCookie('refreshToken')
const accessTokenCookie = useCookie('accessToken')
const route = useRoute()
const authStore = useAuthStore()
const fetchOptions: FetchOptions = {
baseURL: nuxtApp.$config.public.apiBase,
onRequest(ctx: FetchContext): Promise<void> | void {
ctx.options.headers = new Headers({
'Authorization': `Bearer ${accessTokenCookie.value}`
})
},
async onResponseError({ request, response, options }) {
if (response.status === 401) {
try {
const newTokens = await modules.auth.refresh({
refreshToken: refreshTokenCookie.value
})
accessTokenCookie.value = newTokens.access_token
refreshTokenCookie.value = newTokens.refresh_token
authStore.setAccessToken(newTokens.access_token)
authStore.setRefreshToken(newTokens.refresh_token)
options.headers = new Headers({
'Authorization': `Bearer ${newTokens.access_token}`
})
return apiFetcher(request, options)
} catch (error) {
if (route.path !== 'auth') {
navigateTo('/auth')
}
}
}
}
}
const apiFetcher = $fetch.create(fetchOptions)
const modules: ApiInstance = {
auth: new AuthModule(apiFetcher),
category: new CategoryModule(apiFetcher),
}
return {
provide: {
api: modules
}
}
})
但是现在我无法从我的页面上的请求获取数据
<script lang="ts" setup>
import type { ApiInstance } from "~/plugins/api"
const { $api }: { $api: ApiInstance } = useNuxtApp()
const categories = ref([])
useAsyncData(async () => {
categories.value = await $api.category.getAll()
})
</script>
我的类别模块
import HttpFactory from '../factory'
import type { Category } from "~/types"
class CategoryModule extends HttpFactory {
private resource = '/backend-category'
async getAll(): Promise<Category[]> {
console.log(1)
return await this.call(this.resource)
}
}
export default CategoryModule
所以函数 getAll() 在刷新之前被调用一次
我不知道这是否相关,但我遇到了同样的问题并找到了解决方案。事实是,你不需要使用 onResponseError,而是使用 onResponse,这个拦截器还捕获 401 状态的消息,整个笑话就是从这个函数中做什么
return
,但你只需要发出一个新的请求并用收到的响应替换前一个,类似这样的内容
async onResponseError(ctx: FetchContext) {
if (ctx.response.status === 401 && !ctx.options.retry) {
try {
const newTokens = await modules.auth.refresh({
refreshToken: refreshTokenCookie.value
})
accessTokenCookie.value = newTokens.access_token
refreshTokenCookie.value = newTokens.refresh_token
authStore.setAccessToken(newTokens.access_token)
authStore.setRefreshToken(newTokens.refresh_token)
ctx.options.headers = new Headers({
'Authorization': `Bearer ${newTokens.access_token}`
})
ctx.options.retry = 1 //to work only once
const response = await apiFetcher(request, options)
// no return, just replace response
ctx.response = response
} catch (error) {
if (route.path !== 'auth') {
navigateTo('/auth')
}
}
}
}