Files
anonymous_github/public/script/http.js
T

53 lines
2.6 KiB
JavaScript

// Keep response metadata alongside parsed data for the existing API consumers.
export function createHttp(fetcher = (...args) => fetch(...args)) {
async function request(method, url, data, options = {}) {
const target = new URL(url, window.location.href);
for (const [key, value] of Object.entries(options.params || {})) {
if (value == null) continue;
for (const item of Array.isArray(value) ? value : [value]) target.searchParams.append(key, typeof item === "object" ? JSON.stringify(item) : item);
}
const controller = new AbortController();
let timer;
if (options.timeout?.then) options.timeout.then(() => controller.abort());
else if (options.timeout) timer = setTimeout(() => controller.abort(), options.timeout);
try {
const headers = { Accept: "application/json, text/plain, */*", ...options.headers };
const csrf = document.cookie.match(/(?:^|;\s*)XSRF-TOKEN=([^;]*)/);
if (csrf && target.origin === window.location.origin) headers["X-XSRF-TOKEN"] = decodeURIComponent(csrf[1]);
let body;
if (data !== undefined) {
if (data instanceof FormData) body = data;
else { headers["Content-Type"] ||= "application/json;charset=utf-8"; body = JSON.stringify(data); }
}
const response = await fetcher(target.href, { method, headers, body, credentials: "same-origin", signal: controller.signal });
const raw = await response.text();
let result = raw;
if (options.transformResponse) result = options.transformResponse(raw);
else if (raw && (/json/i.test(response.headers.get("content-type") || "") || /^[\[{]/.test(raw.trim()))) {
try { result = JSON.parse(raw); } catch { /* File content may start with a brace. */ }
}
const value = { data: result, status: response.status, headers: name => response.headers.get(name) };
if (!response.ok) throw value;
return value;
} catch (error) {
if (error.name === "AbortError") throw { status: -1, data: null };
throw error;
} finally { clearTimeout(timer); }
}
const http = {};
for (const method of ["get", "delete", "head"]) http[method] = (url, options) => request(method.toUpperCase(), url, undefined, options);
for (const method of ["post", "put", "patch"]) http[method] = (url, data, options) => request(method.toUpperCase(), url, data, options);
return http;
}
export const promises = {
resolve: value => Promise.resolve(value),
reject: error => Promise.reject(error),
all: values => Promise.all(values),
defer() {
let resolve, reject;
const promise = new Promise((yes, no) => { resolve = yes; reject = no; });
return { promise, resolve, reject };
},
};