fix: resolve CSRF race condition + sync updates

- fetchWithCsrf now awaits token initialization before sending requests
- Sync crawler and worker updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
airano
2026-02-12 16:09:29 +03:30
parent 97b427831a
commit 756432d9de
4 changed files with 22 additions and 152 deletions

View File

@@ -14,6 +14,9 @@ const CSRF_HEADER_NAME = 'x-csrf-token';
// Store the CSRF token in memory (will be populated on first page load)
let csrfToken: string | null = null;
// Pending initialization promise (deduplicates concurrent init calls)
let initPromise: Promise<string | null> | null = null;
/**
* Set the CSRF token (called when receiving a response with the token)
*/
@@ -43,6 +46,20 @@ export function createHeadersWithCsrf(additionalHeaders?: HeadersInit): Headers
return headers;
}
/**
* Ensure the CSRF token is available, initializing if needed.
* Deduplicates concurrent calls so only one GET /api/health fires.
*/
async function ensureCsrfToken(): Promise<string | null> {
if (csrfToken) return csrfToken;
if (!initPromise) {
initPromise = initializeCsrfToken().finally(() => {
initPromise = null;
});
}
return initPromise;
}
/**
* Create a fetch wrapper that automatically includes the CSRF token
* and extracts new tokens from responses
@@ -51,6 +68,9 @@ export async function fetchWithCsrf(
url: string | URL,
options?: RequestInit
): Promise<Response> {
// Wait for token to be ready before sending a protected request
await ensureCsrfToken();
const token = getCsrfToken();
const headers = new Headers(options?.headers);