it worked
This commit is contained in:
@@ -4,6 +4,15 @@
|
||||
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:3001";
|
||||
|
||||
const STATE_CHANGING_METHODS = ["POST", "PATCH", "PUT", "DELETE"];
|
||||
|
||||
// ─── Read csrfToken cookie in the browser ─────────────────────────────────────
|
||||
function getClientCsrfToken(): string {
|
||||
if (typeof document === "undefined") return "";
|
||||
const match = document.cookie.match(/(?:^|;\s*)csrfToken=([^;]+)/);
|
||||
return match ? decodeURIComponent(match[1]) : "";
|
||||
}
|
||||
|
||||
// ─── Server-side fetch (use in Server Components / Route Handlers) ─────────────
|
||||
|
||||
export async function apiFetch<T = unknown>(
|
||||
@@ -13,6 +22,7 @@ export async function apiFetch<T = unknown>(
|
||||
// Dynamic import so this module can also be imported in client components
|
||||
// The `cookies` call only runs on the server side
|
||||
let cookieHeader = "";
|
||||
let csrfToken = "";
|
||||
try {
|
||||
const { cookies } = await import("next/headers");
|
||||
const store = await cookies();
|
||||
@@ -20,16 +30,22 @@ export async function apiFetch<T = unknown>(
|
||||
.getAll()
|
||||
.map((c) => `${c.name}=${c.value}`)
|
||||
.join("; ");
|
||||
// Forward the CSRF token from the cookie store for mutating server-side calls
|
||||
csrfToken = store.get("csrfToken")?.value ?? "";
|
||||
} catch {
|
||||
// We're on the client — skip cookie forwarding
|
||||
}
|
||||
|
||||
const method = (init?.method ?? "GET").toUpperCase();
|
||||
const needsCsrf = STATE_CHANGING_METHODS.includes(method);
|
||||
|
||||
const res = await fetch(`${API_URL}${path}`, {
|
||||
...init,
|
||||
cache: "no-store",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...(cookieHeader ? { Cookie: cookieHeader } : {}),
|
||||
...(needsCsrf && csrfToken ? { "x-csrf-token": csrfToken } : {}),
|
||||
...(init?.headers as Record<string, string> | undefined),
|
||||
},
|
||||
});
|
||||
@@ -57,11 +73,16 @@ export async function clientFetch<T = unknown>(
|
||||
path: string,
|
||||
init?: RequestInit
|
||||
): Promise<T> {
|
||||
const method = (init?.method ?? "GET").toUpperCase();
|
||||
const needsCsrf = STATE_CHANGING_METHODS.includes(method);
|
||||
const csrfToken = needsCsrf ? getClientCsrfToken() : "";
|
||||
|
||||
const res = await fetch(`${API_URL}${path}`, {
|
||||
...init,
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...(needsCsrf && csrfToken ? { "x-csrf-token": csrfToken } : {}),
|
||||
...(init?.headers as Record<string, string> | undefined),
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user