Files
proxypin/assets/js/fetch.js
2025-09-12 00:36:22 +08:00

67 lines
2.4 KiB
JavaScript

function fetch(url, options) {
options = options || {};
return new Promise((resolve, reject) => {
const request = new XMLHttpRequest();
const keys = [];
const all = [];
const headers = {};
const response = () => ({
ok: (request.status / 100 | 0) === 2, // 200-299
statusText: request.statusText,
status: request.status,
url: request.responseURL,
body: request.response.body,
text: () => Promise.resolve(request.responseText),
json: () => {
// TODO: review this handle because it may discard \n from json attributes
try {
// console.log('RESPONSE TEXT IN FETCH: ' + request.responseText);
return Promise.resolve(JSON.parse(request.responseText));
} catch (e) {
// console.log('ERROR on fetch parsing JSON: ' + e.message);
return Promise.resolve(request.responseText);
}
},
blob: () => Promise.resolve(request.response.body),
clone: response,
headers: {
...headers,
keys: () => keys,
entries: () => all,
get: n => headers[n.toLowerCase()],
has: n => n.toLowerCase() in headers,
}
});
request.open(options.method || 'get', url, true);
request.onload = () => {
request.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm, (m, key, value) => {
keys.push(key = key.toLowerCase());
all.push([key, value]);
headers[key] = headers[key] ? `${headers[key]},${value}` : value;
});
resolve(response());
};
request.onerror = reject;
request.withCredentials = options.credentials == 'include';
if (options.headers) {
if (options.headers.constructor.name == 'Object') {
for (const i in options.headers) {
request.setRequestHeader(i, options.headers[i]);
}
} else { // if it is some Headers pollyfill, the way to iterate is through for of
for (const header of options.headers) {
request.setRequestHeader(header[0], header[1]);
}
}
}
request.send(options.body || null);
});
}