Refactor API fetch functions: implement useApiFetch composable for improved token handling and error management; update cfetch to streamline authorization logic and enhance error handling

This commit is contained in:
lucast committed 2025-12-08 18:19:49 +01:00
1 parent fbf1fcf553
commit 66ebf25b28
2 files changed
+70 -2

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
import type { UseFetchOptions } from "#app"
import defu from "defu"
export function useApiFetch<DataT = any, ErrorT = any>(
url: string | Request | Ref<string | Request> | (() => string | Request),
options: UseFetchOptions<DataT, ErrorT> = {},
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<DataT, ErrorT> = {
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<DataT, ErrorT>(url, newOptions)
}
},
}
const config = defu(options || {}, defaults) as UseFetchOptions<
DataT,
ErrorT
>
// @ts-ignore
return useFetch<DataT, ErrorT>(url, config)
}
+21 -2
View File
@@ -10,17 +10,36 @@ export const cfetch = async (
if (!baseUrl) throw new Error("BACKEND URL not set") if (!baseUrl) throw new Error("BACKEND URL not set")
const { sessionToken, refreshSessionToken } = useAuth()
const defaults: AxiosRequestConfig = { const defaults: AxiosRequestConfig = {
baseURL: baseUrl, baseURL: baseUrl,
} }
if (authorize) { if (authorize) {
let token = (await cookieStore.get("sessionToken"))?.value let token = sessionToken.value
if (token) defaults.headers = { Authorization: `Bearer ${token}` } if (token) defaults.headers = { Authorization: `Bearer ${token}` }
else
defaults.headers = {
Authorization: `Bearer ${await refreshSessionToken()}`,
}
} }
const config: AxiosRequestConfig = defu(options, defaults) 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
} }