diff --git a/app/composables/useApiFetch.ts b/app/composables/useApiFetch.ts new file mode 100644 index 0000000..ffda4ce --- /dev/null +++ b/app/composables/useApiFetch.ts @@ -0,0 +1,49 @@ +import type { UseFetchOptions } from "#app" +import defu from "defu" + +export function useApiFetch( + url: string | Request | Ref | (() => string | Request), + options: UseFetchOptions = {}, + authorize: boolean = true +) { + const baseUrl = import.meta.env.VITE_PUBLIC_BACKEND + + if (!baseUrl) throw new Error("BACKEND URL not set") + + const { sessionToken, refreshSessionToken } = useAuth() + + const defaults: UseFetchOptions = { + baseURL: baseUrl, + + headers: + authorize && sessionToken.value + ? { Authorization: `Bearer ${sessionToken.value}` } + : {}, + onResponseError: async ({ response, options }) => { + if (response.status == 401 && authorize) { + const newToken = await refreshSessionToken() + + if (!newToken) return + + const newOptions = { + ...options, + headers: { + ...(options.headers || {}), + Authorization: `Bearer ${newToken}`, + }, + } + + // @ts-ignore + return await $fetch(url, newOptions) + } + }, + } + + const config = defu(options || {}, defaults) as UseFetchOptions< + DataT, + ErrorT + > + + // @ts-ignore + return useFetch(url, config) +} diff --git a/app/utils/cfetch.ts b/app/utils/cfetch.ts index 076a190..f5d9245 100644 --- a/app/utils/cfetch.ts +++ b/app/utils/cfetch.ts @@ -10,17 +10,36 @@ export const cfetch = async ( if (!baseUrl) throw new Error("BACKEND URL not set") + const { sessionToken, refreshSessionToken } = useAuth() + const defaults: AxiosRequestConfig = { baseURL: baseUrl, } if (authorize) { - let token = (await cookieStore.get("sessionToken"))?.value + let token = sessionToken.value if (token) defaults.headers = { Authorization: `Bearer ${token}` } + else + defaults.headers = { + Authorization: `Bearer ${await refreshSessionToken()}`, + } } const config: AxiosRequestConfig = defu(options, defaults) - return await axios(url, config) + let response + try { + response = await axios(url, config) + } catch { + if (response?.status == 401) { + if (!config.headers) config.headers = {} + config.headers.Authorization = `Bearer ${await refreshSessionToken()}` + + response = await axios(url, config) + } + } + + if (!response) throw new Error("Something went wrong. Please try again") + return response }