Open JoniLieh opened 2 months ago
// pinia store
const GetOrganizations = async () => {
try {
return $csrfFetch<Organization[]>('/api/organizations')
} catch (e: any) {
throw e
}
}
// somewhere in setup page function
const { GetOrganizations } = useOrganizationStore();
const { data, refresh, status, error } = await useAsyncData("organizations", () =>
GetOrganizations()
); // Error: [GET] "/api/organizations": <no response> Failed to parse URL from /api/organizations
const { data, refresh, status, error } = await useCsrfFetch<Organization[]>("/api/organizations");
Same with composable, inside a composable you can't use $csrfFetch while hydration/ssr, but inside a setup function useCsrfFetch works.
So I thought it's a initialization issue here, but wrapping it inside a function etc. and logging useCsrf()
works, since $csrfFetch only adds the token to the header I'm using a custom fetch function from here https://nuxt.com/docs/guide/recipes/custom-usefetch and adding the csrf token there
const {
csrf,
headerName
} = useCsrf();
...
onRequest({ request, options, error }) {
const headers: HeadersInit = options.headers ||= {}
// Add CSRF token
if (csrf) {
if (Array.isArray(headers)) {
headers.push([headerName, csrf])
} else if (headers instanceof Headers) {
headers.set(headerName, csrf)
} else {
headers[headerName] = csrf
}
}
},
...
解决方法
所以我认为这是一个初始化问题,但是将其包装在函数等中并进行日志记录有效,因为$csrfFetch仅将令牌添加到标头中,我正在使用自定义获取函数从这里 https://nuxt.com/docs/guide/recipes/custom-usefetch 并在那里添加 csrf 令牌
useCsrf()
const { csrf, headerName } = useCsrf(); ... onRequest({ request, options, error }) { const headers: HeadersInit = options.headers ||= {} // Add CSRF token if (csrf) { if (Array.isArray(headers)) { headers.push([headerName, csrf]) } else if (headers instanceof Headers) { headers.set(headerName, csrf) } else { headers[headerName] = csrf } } }, ...
I used your method, but still reported 403 because the server did not have a cookie and failed to parse the “headerName”
我的解决方案:
// plugins/request.ts
import {useCsrf, defineNuxtPlugin, useCookie,} from "#imports";
export default defineNuxtPlugin((nuxtApp) => {
const mySsrFetch = $fetch.create({
onRequest({request, options, error}) {
const {
csrf,
headerName
} = useCsrf();
if (csrf) {
const headers:any = {}
headers[headerName] = csrf
options.headers = headers
headers.Cookie = nuxtApp.ssrContext?.event.req.headers.cookie
}
},
})
// Expose to useNuxtApp().$api
return {
provide: {
mySsrFetch
}
}
})
In which context are you using your plugin? This is my final file:
export default defineNuxtPlugin({
name: 'apiFetch',
parallel: true,
setup(nuxtApp) {
const {
accessToken
} = useUserStore();
const {
csrf,
headerName
} = useCsrf();
const apiFetch = $fetch.create({
baseURL: '/api',
onRequest({ request, options, error }) {
const headers: HeadersInit = options.headers ||= {}
// Add Authorization header
if (accessToken) {
if (Array.isArray(headers)) {
headers.push(['Authorization', `Bearer ${accessToken}`])
} else if (headers instanceof Headers) {
headers.set('Authorization', `Bearer ${accessToken}`)
} else {
headers.Authorization = `Bearer ${accessToken}`
}
}
// cache control
if (!options.cache) {
// Handle different header types
if (Array.isArray(headers)) {
// Check if cache-control header is already present in the array
const hasCacheControl = headers.some(([key]) => key.toLowerCase() === 'cache-control');
if (!hasCacheControl) {
headers.push(['cache-control', 'default']);
}
} else if (headers instanceof Headers) {
// Check if cache-control is already set
if (!headers.has('cache-control')) {
headers.set('cache-control', 'default');
}
} else if (typeof headers === 'object') {
// Treat headers as a plain object
if (headers['cache-control'] === undefined) {
headers['cache-control'] = 'default';
}
}
}
// Add CSRF token
if (csrf) {
if (Array.isArray(headers)) {
headers.push([headerName, csrf])
} else if (headers instanceof Headers) {
headers.set(headerName, csrf)
} else {
headers[headerName] = csrf
}
}
},
})
// Add the fetch method to the context
return {
provide: {
apiFetch
}
}
},
})
are you still facing difficulties with the latest version (fetch management has changed on my side)?
Hey there, im trying to do a request via a proxy with SSR, the normal
$fetch
from nuxt is working:I've been logging the csrf token, apparently on the server the token is undefined
My setup: