1
-let _extensionsModule = null;
2
-
3
-async function _getExtensions() {
4
- if (!_extensionsModule) _extensionsModule = await import("./extensions.js");
5
- return _extensionsModule;
6
-}
7
-
8
-async function _shouldCallApiExtensions(apiUrl) {
9
- const extensions = await _getExtensions();
10
- const excluded = extensions.API_EXTENSION_EXCLUDED_ENDPOINTS;
11
- return !(excluded instanceof Set && excluded.has(apiUrl));
12
-}
13
-
14
-function _normalizeApiUrl(url) {
15
- return url.startsWith("/api/") || url.startsWith("api/")
16
- ? `/${url.replace(/^\/+/, "")}`
17
- : `/api/${url.replace(/^\/+/, "")}`;
18
-}
19
-
1
/**
2
* Call a JSON-in JSON-out API endpoint
3
* Data is automatically serialized
42
}
43
44
if (ctx.error) throw ctx.error;
64
-
45
+
46
return ctx.result;
47
}
48
109
// retry the request with new token
110
csrfToken = null;
111
return await _wrap(false);
131
- } else if (finalResponse.redirected && finalResponse.url.endsWith("/login")) {
132
- // redirect to login (origin check prevents open redirect)
133
- const _redirectUrl = new URL(finalResponse.url);
134
- if (_redirectUrl.origin === window.location.origin) {
135
- window.location.href = finalResponse.url;
136
- }
137
- return;
112
}
113
114
+ if (redirect(finalResponse)) return;
115
+
116
// return the response
117
return finalResponse;
118
}
196
}
197
}
198
223
- if (response.redirected && response.url.endsWith("/login")) {
224
- // redirect to login (origin check prevents open redirect)
225
- const _redirectUrl = new URL(response.url);
226
- if (_redirectUrl.origin === window.location.origin) {
227
- window.location.href = response.url;
228
- }
229
- return;
230
- }
199
+ if (redirect(response)) return;
200
+
201
const json = await response.json();
202
if (json.ok) {
203
const runtimeId =
217
: null;
218
const cookieRuntimeId = runtimeId || injectedRuntimeId;
219
if (cookieRuntimeId) {
250
- const _secureFlag = window.location.protocol === 'https:' ? '; Secure' : '';
220
+ const _secureFlag =
221
+ window.location.protocol === "https:" ? "; Secure" : "";
222
document.cookie = `csrf_token_${cookieRuntimeId}=${csrfToken}; SameSite=Strict; Path=/${_secureFlag}`;
223
} else {
224
console.warn("CSRF runtime id missing; skipping cookie name binding.");
225
}
226
const elapsedMs = Date.now() - startedAt;
256
- if (elapsedMs > CSRF_SLOW_WARN_MS && globalThis.runtimeInfo?.isDevelopment) {
227
+ if (
228
+ elapsedMs > CSRF_SLOW_WARN_MS &&
229
+ globalThis.runtimeInfo?.isDevelopment
230
+ ) {
231
console.warn(`CSRF token request took ${elapsedMs}ms`);
232
}
233
return csrfToken;
243
csrfTokenPromise = null;
244
}
245
}
246
+
247
+
248
+
249
+let _extensionsModule = null;
250
+
251
+async function _getExtensions() {
252
+ if (!_extensionsModule) _extensionsModule = await import("./extensions.js");
253
+ return _extensionsModule;
254
+}
255
+
256
+async function _shouldCallApiExtensions(apiUrl) {
257
+ const extensions = await _getExtensions();
258
+ const excluded = extensions.API_EXTENSION_EXCLUDED_ENDPOINTS;
259
+ return !(excluded instanceof Set && excluded.has(apiUrl));
260
+}
261
+
262
+function _normalizeApiUrl(url) {
263
+ return url.startsWith("/api/") || url.startsWith("api/")
264
+ ? `/${url.replace(/^\/+/, "")}`
265
+ : `/api/${url.replace(/^\/+/, "")}`;
266
+}
267
+
268
+function redirect(response) {
269
+ if (!(response.redirected && response.url.endsWith("/login"))) return false;
270
+ const _redirectUrl = new URL(response.url);
271
+ if (_redirectUrl.origin === window.location.origin) {
272
+ window.location.href = response.url;
273
+ }
274
+ return true;
275
+}
\ No newline at end of file