Is there a way to use cookies on server side in Nuxt 3? For example, I want to set cookie in API and then read its data in middleware:
// ~/server/api/testApi.ts
export default defineEventHandler(event => {
/* setCookie('myCookie', 'myValue'); */
});
// ~/middleware/testMw.ts
export default defineNuxtRouteMiddleware((to, from) => {
/* getCookie('myCookie'); */ // ~~> myValue
});
I tried to set cookie with useCookie
in API but it is undefined
in middleware.
I also don't understand how to use getCookie
in middleware because it needs the event
object which is not present in middleware.
Context
I want to create a very simple auth system. In /api/auth.post.ts
I create some kind of token which is saved in cookie. Then, in order to check, whether visitor is logged in I need to somehow retrieve this token back from cookie in /middleware/logged.ts
.
I am open to other suggestions.
You have to define a plugin to initial values from cookies via pinia
, before you use them in middlewares.
For example, there is a value: theme
in cookie
// store/theme.ts
import { defineStore } from 'pinia';
import Cookie from 'js-cookie'; // you can use any Cookie packages you want
export const useThemeStore = defineStore('theme', {
state: () => ({
_theme: {}
}),
getters: {
theme: (state) => stats._theme
},
actions: {
setTheme (value: 'light' | 'dark' | 'system') {
// update the value in both cookie and memory
this._theme = value;
Cookie.set('theme', value);
}
}
});
define a plugin to boot the store
// plugin/initial.ts
import Cookie from 'js-cookie';
import { useThemeStore } from '~/stores/theme';
function cookieFromRequestHeaders (key: string) {
const headers = useRequestHeaders(['cookie']);
if ('cookie' in headers) {
const cookie = headers.cookie?.split(';').find(
c => c.trim().startsWith(`${key}=`)
);
if (cookie) {
return cookie.split('=')[1];
}
}
return undefined;
}
export default defineNuxtPlugin(async (nuxtApp) => {
const theme = cookieFromRequestHeaders('theme') ?? Cookie.get('theme') ?? 'system';
const themeStore = useThemeStore(nuxtApp.$pinia as Pinia);
themeStore.setTheme(theme);
});
Now, you can use it in middlewares
import { useThemeStore } from '~/stores/theme';
export default defineNuxtRouteMiddleware((to) => {
const themeStore = useThemeStore();
if (themeStore.theme === 'dark') {
return navigateTo('/dark-index');
}
});
A js-version full example with auth is here, which is SSR, feel free to star it :)
2024/06/17 update
Using useCookie instead of a custom cookie handler could be a better choice, which is friendly for both client side and server side
// plugin/initial.ts
import { useThemeStore } from '~/stores/theme';
export default defineNuxtPlugin(async (nuxtApp) => {
const theme = useCookie<'system'|'light'|'dark'>('theme', {
default: () => 'system',
});
const themeStore = useThemeStore(nuxtApp.$pinia as Pinia);
themeStore.setTheme(theme);
});