10. Сессии и Cookies
Remix предоставляет удобные утилиты для работы с сессиями и cookies. Все операции происходят на сервере, что делает их безопасными.
createCookieSessionStorage
Заголовок раздела «createCookieSessionStorage»import { createCookieSessionStorage } from "@remix-run/node";
export const { getSession, commitSession, destroySession } = createCookieSessionStorage({ cookie: { name: "__session", httpOnly: true, // Недоступен из JS path: "/", sameSite: "lax", secrets: [process.env.SESSION_SECRET], secure: process.env.NODE_ENV === "production", }, });Основные операции
Заголовок раздела «Основные операции»Создание сессии (логин)
Заголовок раздела «Создание сессии (логин)»import { getSession, commitSession } from "~/session.server";import { redirect } from "@remix-run/node";
export async function action({ request }) { const formData = await request.formData(); const email = formData.get("email") as string; const password = formData.get("password") as string;
const user = await verifyLogin(email, password); if (!user) { return json({ error: "Неверные данные" }, { status: 400 }); }
const session = await getSession(request.headers.get("Cookie")); session.set("userId", user.id);
return redirect("/dashboard", { headers: { "Set-Cookie": await commitSession(session), }, });}Чтение сессии
Заголовок раздела «Чтение сессии»export async function loader({ request }) { const session = await getSession(request.headers.get("Cookie")); const userId = session.get("userId");
if (!userId) { throw redirect("/login"); }
const user = await db.user.findUnique({ where: { id: userId } }); return json({ user });}Удаление сессии (выход)
Заголовок раздела «Удаление сессии (выход)»export async function action({ request }) { const session = await getSession(request.headers.get("Cookie")); return redirect("/login", { headers: { "Set-Cookie": await destroySession(session), }, });}Flash сообщения
Заголовок раздела «Flash сообщения»Flash — это данные сессии, которые читаются один раз и удаляются:
// В action после создания записиsession.flash("success", "Пользователь создан!");return redirect("/users", { headers: { "Set-Cookie": await commitSession(session) },});
// В loader следующей страницыexport async function loader({ request }) { const session = await getSession(request.headers.get("Cookie")); const message = session.get("success"); // читается и удаляется
return json({ message }, { headers: { "Set-Cookie": await commitSession(session) }, });}Обычные Cookies
Заголовок раздела «Обычные Cookies»import { createCookie } from "@remix-run/node";
export const userPrefs = createCookie("user-prefs", { maxAge: 604_800, // неделя});
// В loaderexport async function loader({ request }) { const cookieHeader = request.headers.get("Cookie"); const cookie = await userPrefs.parse(cookieHeader) || {}; return json({ theme: cookie.theme ?? "light" });}
// В actionexport async function action({ request }) { const cookieHeader = request.headers.get("Cookie"); const cookie = await userPrefs.parse(cookieHeader) || {}; const formData = await request.formData(); cookie.theme = formData.get("theme"); return json({ ok: true }, { headers: { "Set-Cookie": await userPrefs.serialize(cookie) }, });}