75 lines
1.8 KiB
TypeScript
75 lines
1.8 KiB
TypeScript
import { $fetch } from 'ofetch'
|
|
import { parseCookies } from 'h3'
|
|
|
|
const CSRF_COOKIE = 'XSRF-TOKEN'
|
|
const CSRF_HEADER = 'X-XSRF-TOKEN'
|
|
|
|
export const $larafetch = $fetch.create({
|
|
credentials: 'include',
|
|
async onRequest({ options }) {
|
|
const { backendUrl, frontendUrl } = useRuntimeConfig().public
|
|
const event = process.nitro ? useEvent() : null
|
|
|
|
let token = event
|
|
? parseCookies(event)[CSRF_COOKIE]
|
|
: useCookie(CSRF_COOKIE).value
|
|
|
|
// on client initiate a csrf request and get it from the cookie set by laravel
|
|
if (
|
|
process.client
|
|
&& ['post', 'delete', 'put', 'patch'].includes(
|
|
options?.method?.toLowerCase() ?? '',
|
|
)
|
|
) {
|
|
token = await initCsrf()
|
|
}
|
|
|
|
let headers: any = {
|
|
accept: 'application/json',
|
|
...options?.headers,
|
|
...(token && { [CSRF_HEADER]: token }),
|
|
}
|
|
|
|
if (process.server) {
|
|
const cookieString = event
|
|
? event.headers.get('cookie')
|
|
: useRequestHeaders(['cookie']).cookie
|
|
|
|
headers = {
|
|
...headers,
|
|
...(cookieString && { cookie: cookieString }),
|
|
referer: frontendUrl,
|
|
}
|
|
}
|
|
|
|
options.headers = headers
|
|
options.baseURL = backendUrl
|
|
},
|
|
async onResponseError({ response }) {
|
|
const status = response.status
|
|
|
|
if (status === 419) {
|
|
await initCsrf(true)
|
|
}
|
|
if ([500].includes(status)) {
|
|
console.error('[Laravel Error]', response.statusText, response._data)
|
|
}
|
|
},
|
|
})
|
|
|
|
async function initCsrf(forceRefresh = false) {
|
|
const { backendUrl } = useRuntimeConfig().public
|
|
const existingToken = useCookie(CSRF_COOKIE).value
|
|
|
|
if (existingToken && !forceRefresh) {
|
|
return existingToken
|
|
}
|
|
|
|
await $fetch('/sanctum/csrf-cookie', {
|
|
baseURL: backendUrl,
|
|
credentials: 'include',
|
|
})
|
|
|
|
return useCookie(CSRF_COOKIE).value
|
|
}
|