我如何在ofetch中重复之前的请求

问题描述 投票:0回答:1

我有下一个 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() 在刷新之前被调用一次

authentication nuxt.js fetch refresh refresh-token
1个回答
0
投票

我不知道这是否相关,但我遇到了同样的问题并找到了解决方案。事实是,你不需要使用 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')
      }
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.