Overhauled XHR API.
This commit is contained in:
parent
12bb564613
commit
8083ad6a20
7 changed files with 135 additions and 139 deletions
src/mami.js
|
@ -1,4 +1,4 @@
|
|||
#include utility.js
|
||||
#include xhr.js
|
||||
#include audio/source.js
|
||||
|
||||
const MamiAudioContext = function() {
|
||||
|
@ -63,7 +63,7 @@ const MamiAudioContext = function() {
|
|||
return undefined;
|
||||
|
||||
const result = await $x.get(url, { type: 'arraybuffer' });
|
||||
return await ctx.decodeAudioData(result.body());
|
||||
return await ctx.decodeAudioData(result.body);
|
||||
},
|
||||
|
||||
createSource: (buffer, reverse) => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include utility.js
|
||||
#include xhr.js
|
||||
|
||||
const FutamiCommon = function(vars) {
|
||||
vars = vars || {};
|
||||
|
@ -15,14 +15,14 @@ const FutamiCommon = function(vars) {
|
|||
if(noCache)
|
||||
options.headers = { 'Cache-Control': 'no-cache' };
|
||||
|
||||
return (await $x.get(get(name), options)).body();
|
||||
return (await $x.get(get(name), options)).body;
|
||||
},
|
||||
getApiJson: async (path, noCache) => {
|
||||
const options = { type: 'json' };
|
||||
if(noCache)
|
||||
options.headers = { 'Cache-Control': 'no-cache' };
|
||||
|
||||
return (await $x.get(get('api') + path, options)).body();
|
||||
return (await $x.get(get('api') + path, options)).body;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -31,12 +31,12 @@ FutamiCommon.load = async url => {
|
|||
if(typeof url !== 'string' && 'FUTAMI_URL' in window)
|
||||
url = window.FUTAMI_URL + '?t=' + Date.now().toString();
|
||||
|
||||
const resp = await $x.get(url, {
|
||||
const { body } = await $x.get(url, {
|
||||
type: 'json',
|
||||
headers: {
|
||||
'Cache-Control': 'no-cache'
|
||||
}
|
||||
});
|
||||
|
||||
return new FutamiCommon(resp.body());
|
||||
return new FutamiCommon(body);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include utility.js
|
||||
#include xhr.js
|
||||
|
||||
const MamiEEPROM = function(endPoint, getAuthLine) {
|
||||
if(typeof endPoint !== 'string')
|
||||
|
@ -47,7 +47,7 @@ const MamiEEPROM = function(endPoint, getAuthLine) {
|
|||
formData.append('src', appId);
|
||||
formData.append('file', fileInput);
|
||||
|
||||
const result = await $x.post(`${endPoint}/uploads`, {
|
||||
const { status, body } = await $x.post(`${endPoint}/uploads`, {
|
||||
type: 'json',
|
||||
headers: {
|
||||
Authorization: getAuthLine(),
|
||||
|
@ -55,13 +55,11 @@ const MamiEEPROM = function(endPoint, getAuthLine) {
|
|||
upload: reportProgress,
|
||||
abort: handler => abortHandler = handler,
|
||||
}, formData);
|
||||
const body = result.body();
|
||||
console.log(body);
|
||||
if(body === null)
|
||||
throw "The upload server didn't return the metadata for some reason.";
|
||||
|
||||
if(result.status !== 201)
|
||||
throw body.english ?? body.error ?? `Upload failed with status code ${result.status}`;
|
||||
if(status !== 201)
|
||||
throw body.english ?? body.error ?? `Upload failed with status code ${status}`;
|
||||
|
||||
body.isImage = () => body.type.startsWith('image/');
|
||||
body.isVideo = () => body.type.startsWith('video/');
|
||||
|
@ -86,19 +84,18 @@ const MamiEEPROM = function(endPoint, getAuthLine) {
|
|||
if(typeof fileInfo.urlf !== 'string')
|
||||
throw 'fileInfo.urlf must be a string';
|
||||
|
||||
const result = await $x.delete(fileInfo.urlf, {
|
||||
const { status, body } = await $x.delete(fileInfo.urlf, {
|
||||
type: 'json',
|
||||
headers: {
|
||||
Authorization: getAuthLine(),
|
||||
},
|
||||
});
|
||||
|
||||
if(result.status !== 204) {
|
||||
const body = result.body();
|
||||
if(status !== 204) {
|
||||
if(body === null)
|
||||
throw `Delete failed with status code ${result.status}`;
|
||||
throw `Delete failed with status code ${status}`;
|
||||
|
||||
throw body.english ?? body.error ?? `Delete failed with status code ${result.status}`;
|
||||
throw body.english ?? body.error ?? `Delete failed with status code ${status}`;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include common.js
|
||||
#include utility.js
|
||||
#include xhr.js
|
||||
|
||||
const MamiMisuzuAuth = (() => {
|
||||
let userId = null;
|
||||
|
@ -18,9 +18,7 @@ const MamiMisuzuAuth = (() => {
|
|||
};
|
||||
},
|
||||
update: async () => {
|
||||
const resp = await $x.get(futami.get('token'), { authed: true, type: 'json' });
|
||||
|
||||
const body = resp.body();
|
||||
const { body } = await $x.get(futami.get('token'), { authed: true, type: 'json' });
|
||||
if(body.ok) {
|
||||
userId = body.usr.toString();
|
||||
authToken = body.tkn;
|
||||
|
|
|
@ -168,118 +168,3 @@ const $as = function(array) {
|
|||
array[j] = tmp;
|
||||
}
|
||||
};
|
||||
|
||||
const $x = (function() {
|
||||
const send = function(method, url, options, body) {
|
||||
if(options === undefined)
|
||||
options = {};
|
||||
else if(typeof options !== 'object')
|
||||
throw 'options must be undefined or an object';
|
||||
|
||||
const xhr = new XMLHttpRequest;
|
||||
const requestHeaders = new Map;
|
||||
|
||||
if('headers' in options && typeof options.headers === 'object')
|
||||
for(const name in options.headers)
|
||||
if(options.headers.hasOwnProperty(name))
|
||||
requestHeaders.set(name.toLowerCase(), options.headers[name]);
|
||||
|
||||
if(typeof options.download === 'function') {
|
||||
xhr.onloadstart = ev => options.download(ev);
|
||||
xhr.onprogress = ev => options.download(ev);
|
||||
xhr.onloadend = ev => options.download(ev);
|
||||
}
|
||||
|
||||
if(typeof options.upload === 'function') {
|
||||
xhr.upload.onloadstart = ev => options.upload(ev);
|
||||
xhr.upload.onprogress = ev => options.upload(ev);
|
||||
xhr.upload.onloadend = ev => options.upload(ev);
|
||||
}
|
||||
|
||||
if(options.authed)
|
||||
xhr.withCredentials = true;
|
||||
|
||||
if(typeof options.timeout === 'number')
|
||||
xhr.timeout = options.timeout;
|
||||
|
||||
if(typeof options.type === 'string')
|
||||
xhr.responseType = options.type;
|
||||
|
||||
if(typeof options.abort === 'function')
|
||||
options.abort(() => xhr.abort());
|
||||
|
||||
if(typeof options.xhr === 'function')
|
||||
options.xhr(() => xhr);
|
||||
|
||||
if(typeof body === 'object') {
|
||||
if(body instanceof URLSearchParams) {
|
||||
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
|
||||
} else if(body instanceof FormData) {
|
||||
// content-type is implicitly set
|
||||
} else if(body instanceof Blob || body instanceof ArrayBuffer || body instanceof DataView) {
|
||||
if(!requestHeaders.has('content-type'))
|
||||
requestHeaders.set('content-type', 'application/octet-stream');
|
||||
} else if(!requestHeaders.has('content-type')) {
|
||||
const bodyParts = [];
|
||||
for(const name in body)
|
||||
if(body.hasOwnProperty(name))
|
||||
bodyParts.push(encodeURIComponent(name) + '=' + encodeURIComponent(body[name]));
|
||||
body = bodyParts.join('&');
|
||||
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
|
||||
}
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let responseHeaders = undefined;
|
||||
|
||||
xhr.onload = ev => resolve({
|
||||
status: xhr.status,
|
||||
body: () => xhr.response,
|
||||
text: () => xhr.responseText,
|
||||
headers: () => {
|
||||
if(responseHeaders !== undefined)
|
||||
return responseHeaders;
|
||||
|
||||
responseHeaders = new Map;
|
||||
|
||||
const raw = xhr.getAllResponseHeaders().trim().split(/[\r\n]+/);
|
||||
for(const name in raw)
|
||||
if(raw.hasOwnProperty(name)) {
|
||||
const parts = raw[name].split(': ');
|
||||
responseHeaders.set(parts.shift(), parts.join(': '));
|
||||
}
|
||||
|
||||
return responseHeaders;
|
||||
},
|
||||
xhr: xhr,
|
||||
ev: ev,
|
||||
});
|
||||
|
||||
xhr.onabort = ev => reject({
|
||||
abort: true,
|
||||
xhr: xhr,
|
||||
ev: ev,
|
||||
});
|
||||
|
||||
xhr.onerror = ev => reject({
|
||||
abort: false,
|
||||
xhr: xhr,
|
||||
ev: ev,
|
||||
});
|
||||
|
||||
xhr.open(method, url);
|
||||
for(const [name, value] of requestHeaders)
|
||||
xhr.setRequestHeader(name, value);
|
||||
xhr.send(body);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
send: send,
|
||||
get: (url, options, body) => send('GET', url, options, body),
|
||||
post: (url, options, body) => send('POST', url, options, body),
|
||||
delete: (url, options, body) => send('DELETE', url, options, body),
|
||||
patch: (url, options, body) => send('PATCH', url, options, body),
|
||||
put: (url, options, body) => send('PUT', url, options, body),
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include common.js
|
||||
#include rng.js
|
||||
#include utility.js
|
||||
#include xhr.js
|
||||
|
||||
const Weeaboo = (function() {
|
||||
let kaomoji = [];
|
||||
|
@ -17,7 +17,7 @@ const Weeaboo = (function() {
|
|||
return;
|
||||
|
||||
$x.get(futami.get('kaomoji'))
|
||||
.then(resp => kaomoji = resp.text().split("\n"));
|
||||
.then(resp => kaomoji = resp.text.split("\n"));
|
||||
};
|
||||
|
||||
pub.getRandomKaomoji = function(allowEmpty, message) {
|
||||
|
|
116
src/mami.js/xhr.js
Normal file
116
src/mami.js/xhr.js
Normal file
|
@ -0,0 +1,116 @@
|
|||
const $x = (function() {
|
||||
const send = function(method, url, options, body) {
|
||||
if(options === undefined)
|
||||
options = {};
|
||||
else if(typeof options !== 'object')
|
||||
throw 'options must be undefined or an object';
|
||||
|
||||
Object.freeze(options);
|
||||
|
||||
const xhr = new XMLHttpRequest;
|
||||
const requestHeaders = new Map;
|
||||
|
||||
if('headers' in options && typeof options.headers === 'object')
|
||||
for(const name in options.headers)
|
||||
if(options.headers.hasOwnProperty(name))
|
||||
requestHeaders.set(name.toLowerCase(), options.headers[name]);
|
||||
|
||||
if(typeof options.download === 'function') {
|
||||
xhr.onloadstart = ev => options.download(ev);
|
||||
xhr.onprogress = ev => options.download(ev);
|
||||
xhr.onloadend = ev => options.download(ev);
|
||||
}
|
||||
|
||||
if(typeof options.upload === 'function') {
|
||||
xhr.upload.onloadstart = ev => options.upload(ev);
|
||||
xhr.upload.onprogress = ev => options.upload(ev);
|
||||
xhr.upload.onloadend = ev => options.upload(ev);
|
||||
}
|
||||
|
||||
if(options.authed)
|
||||
xhr.withCredentials = true;
|
||||
|
||||
if(typeof options.timeout === 'number')
|
||||
xhr.timeout = options.timeout;
|
||||
|
||||
if(typeof options.type === 'string')
|
||||
xhr.responseType = options.type;
|
||||
|
||||
if(typeof options.abort === 'function')
|
||||
options.abort(() => xhr.abort());
|
||||
|
||||
if(typeof options.xhr === 'function')
|
||||
options.xhr(() => xhr);
|
||||
|
||||
if(typeof body === 'object') {
|
||||
if(body instanceof URLSearchParams) {
|
||||
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
|
||||
} else if(body instanceof FormData) {
|
||||
// content-type is implicitly set
|
||||
} else if(body instanceof Blob || body instanceof ArrayBuffer || body instanceof DataView) {
|
||||
if(!requestHeaders.has('content-type'))
|
||||
requestHeaders.set('content-type', 'application/octet-stream');
|
||||
} else if(!requestHeaders.has('content-type')) {
|
||||
const bodyParts = [];
|
||||
for(const name in body)
|
||||
if(body.hasOwnProperty(name))
|
||||
bodyParts.push(encodeURIComponent(name) + '=' + encodeURIComponent(body[name]));
|
||||
body = bodyParts.join('&');
|
||||
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
|
||||
}
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
xhr.onload = ev => {
|
||||
const headers = (headersString => {
|
||||
const headers = new Map;
|
||||
|
||||
const raw = headersString.trim().split(/[\r\n]+/);
|
||||
for(const name in raw)
|
||||
if(raw.hasOwnProperty(name)) {
|
||||
const parts = raw[name].split(': ');
|
||||
headers.set(parts.shift(), parts.join(': '));
|
||||
}
|
||||
|
||||
return headers;
|
||||
})(xhr.getAllResponseHeaders());
|
||||
|
||||
resolve({
|
||||
get ev() { return ev; },
|
||||
get xhr() { return xhr; },
|
||||
|
||||
get status() { return xhr.status; },
|
||||
get headers() { return headers; },
|
||||
get body() { return xhr.response; },
|
||||
get text() { return xhr.responseText; },
|
||||
});
|
||||
};
|
||||
|
||||
xhr.onabort = ev => reject({
|
||||
abort: true,
|
||||
xhr: xhr,
|
||||
ev: ev,
|
||||
});
|
||||
|
||||
xhr.onerror = ev => reject({
|
||||
abort: false,
|
||||
xhr: xhr,
|
||||
ev: ev,
|
||||
});
|
||||
|
||||
xhr.open(method, url);
|
||||
for(const [name, value] of requestHeaders)
|
||||
xhr.setRequestHeader(name, value);
|
||||
xhr.send(body);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
send: send,
|
||||
get: (url, options, body) => send('GET', url, options, body),
|
||||
post: (url, options, body) => send('POST', url, options, body),
|
||||
delete: (url, options, body) => send('DELETE', url, options, body),
|
||||
patch: (url, options, body) => send('PATCH', url, options, body),
|
||||
put: (url, options, body) => send('PUT', url, options, body),
|
||||
};
|
||||
})();
|
Loading…
Add table
Add a link
Reference in a new issue