u
This commit is contained in:
@@ -21,25 +21,39 @@ function readableHeaders(headers) {
|
||||
return out;
|
||||
}
|
||||
|
||||
const SSE_CLIENT_ID_KEY = 'sse.cid';
|
||||
const CLIENT_ID_HEADER = 'X-Client-Id';
|
||||
|
||||
function getStoredClientId() {
|
||||
try {
|
||||
if (typeof window === 'undefined') return null;
|
||||
return window.sessionStorage.getItem(SSE_CLIENT_ID_KEY);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function clientIdHeaders() {
|
||||
const cid = getStoredClientId();
|
||||
return cid ? { [CLIENT_ID_HEADER]: cid } : {};
|
||||
}
|
||||
|
||||
function isMutatingMethod(method) {
|
||||
const upper = String(method || 'GET').toUpperCase();
|
||||
return upper !== 'GET' && upper !== 'HEAD';
|
||||
}
|
||||
|
||||
async function http(path, { method = 'GET', body } = {}) {
|
||||
const isFormData = typeof FormData !== 'undefined' && body instanceof FormData;
|
||||
const headers = {};
|
||||
if (!isFormData) {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
if (isMutatingMethod(method)) {
|
||||
Object.assign(headers, clientIdHeaders());
|
||||
}
|
||||
const url = new URL(path, window.location.origin).href;
|
||||
|
||||
logApi('request', {
|
||||
method,
|
||||
path,
|
||||
url,
|
||||
origin: window.location.origin,
|
||||
credentials: 'include',
|
||||
// HttpOnly cookies are invisible here; this only shows JS-readable cookies.
|
||||
documentCookie: document.cookie || '(empty)',
|
||||
hasBody: Boolean(body),
|
||||
});
|
||||
|
||||
const res = await fetch(path, {
|
||||
method,
|
||||
headers,
|
||||
@@ -47,18 +61,6 @@ async function http(path, { method = 'GET', body } = {}) {
|
||||
body: isFormData ? body : (body ? JSON.stringify(body) : undefined),
|
||||
});
|
||||
|
||||
const responseHeaders = readableHeaders(res.headers);
|
||||
// Browsers hide Set-Cookie from JS; if it's missing here that proves nothing.
|
||||
logApi('response', {
|
||||
method,
|
||||
path,
|
||||
status: res.status,
|
||||
statusText: res.statusText,
|
||||
ok: res.ok,
|
||||
responseHeaders,
|
||||
documentCookieAfter: document.cookie || '(empty)',
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
let message = res.statusText;
|
||||
let data;
|
||||
@@ -78,12 +80,6 @@ async function http(path, { method = 'GET', body } = {}) {
|
||||
}
|
||||
if (res.status === 204) return null;
|
||||
const json = await res.json();
|
||||
logApi('ok-body', {
|
||||
method,
|
||||
path,
|
||||
keys: json && typeof json === 'object' ? Object.keys(json) : typeof json,
|
||||
hasUser: Boolean(json?.user),
|
||||
});
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -102,7 +98,7 @@ async function httpBinary(path, { method = 'POST', body, contentType, headers: e
|
||||
|
||||
const res = await fetch(path, {
|
||||
method,
|
||||
headers: { 'Content-Type': contentType, ...(extraHeaders || {}) },
|
||||
headers: { 'Content-Type': contentType, ...clientIdHeaders(), ...(extraHeaders || {}) },
|
||||
credentials: 'include',
|
||||
body,
|
||||
});
|
||||
@@ -851,13 +847,22 @@ export const brand = {
|
||||
},
|
||||
|
||||
/**
|
||||
* PUT /api/brand
|
||||
* Body: { name, gsprpinfo? } — upsert by name for the selected company.
|
||||
* Same name ⇒ update, otherwise create. Empty name ⇒ 400 Invalid brand.
|
||||
* → 200 { brand: Brand }
|
||||
* POST /api/brand
|
||||
* Body: { name, gsprpinfo? } — insert for the selected company.
|
||||
* Empty name ⇒ 400 Invalid brand.
|
||||
* → 201 { brand: Brand } · 409 Brand already exists
|
||||
*/
|
||||
upsert(body) {
|
||||
return http('/api/brand', { method: 'PUT', body });
|
||||
create(body) {
|
||||
return http('/api/brand', { method: 'POST', body });
|
||||
},
|
||||
|
||||
/**
|
||||
* PATCH /api/brand/:id
|
||||
* Body: { name, gsprpinfo? } — rename / update info.
|
||||
* → 200 { id, name, gsprpinfo, touchedArticleCount } · 404 Brand not found
|
||||
*/
|
||||
rename(id, body) {
|
||||
return http(`/api/brand/${encodeURIComponent(id)}`, { method: 'PATCH', body });
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1170,6 +1175,7 @@ export const delivery = {
|
||||
formData.append('file', file, file.name);
|
||||
const res = await fetch('/api/delivery/parse', {
|
||||
method: 'POST',
|
||||
headers: { ...clientIdHeaders() },
|
||||
credentials: 'include',
|
||||
body: formData,
|
||||
signal,
|
||||
@@ -1264,6 +1270,7 @@ export const serper = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...clientIdHeaders(),
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ q, gl, hl, num, preferSource }),
|
||||
@@ -1355,6 +1362,7 @@ export const serper = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...clientIdHeaders(),
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ url }),
|
||||
@@ -2165,6 +2173,7 @@ export const vfs = {
|
||||
}
|
||||
const res = await fetch('/api/vfs/upload', {
|
||||
method: 'POST',
|
||||
headers: { ...clientIdHeaders() },
|
||||
credentials: 'include',
|
||||
body: formData,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user