2020-08-05 22:29:16 +05:30
|
|
|
/*
|
|
|
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2020-08-05 21:07:37 +05:30
|
|
|
import {
|
|
|
|
AbortError,
|
|
|
|
ConnectionError
|
2020-10-26 20:14:11 +05:30
|
|
|
} from "../../../../matrix/error.js";
|
|
|
|
import {addCacheBuster} from "./common.js";
|
2020-08-05 21:07:37 +05:30
|
|
|
|
|
|
|
class RequestResult {
|
|
|
|
constructor(promise, xhr) {
|
|
|
|
this._promise = promise;
|
|
|
|
this._xhr = xhr;
|
|
|
|
}
|
|
|
|
|
|
|
|
abort() {
|
|
|
|
this._xhr.abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
response() {
|
|
|
|
return this._promise;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-16 15:15:46 +05:30
|
|
|
function createXhr(url, {method, headers, timeout, format, uploadProgress}) {
|
2020-08-05 21:07:37 +05:30
|
|
|
const xhr = new XMLHttpRequest();
|
2020-10-27 18:19:36 +05:30
|
|
|
xhr.open(method, url);
|
2020-10-27 18:21:40 +05:30
|
|
|
|
2020-10-26 22:07:32 +05:30
|
|
|
if (format === "buffer") {
|
2020-10-27 18:19:36 +05:30
|
|
|
// important to call this after calling open
|
2020-10-26 22:07:32 +05:30
|
|
|
xhr.responseType = "arraybuffer";
|
|
|
|
}
|
|
|
|
if (headers) {
|
|
|
|
for(const [name, value] of headers.entries()) {
|
2020-11-16 19:40:25 +05:30
|
|
|
try {
|
|
|
|
xhr.setRequestHeader(name, value);
|
|
|
|
} catch (err) {
|
|
|
|
console.info(`Could not set ${name} header: ${err.message}`);
|
|
|
|
}
|
2020-08-05 21:07:37 +05:30
|
|
|
}
|
|
|
|
}
|
2020-10-26 22:07:32 +05:30
|
|
|
if (timeout) {
|
|
|
|
xhr.timeout = timeout;
|
2020-08-05 21:07:37 +05:30
|
|
|
}
|
|
|
|
|
2020-11-16 15:15:46 +05:30
|
|
|
if (uploadProgress) {
|
|
|
|
xhr.upload.addEventListener("progress", evt => uploadProgress(evt.loaded));
|
2020-11-11 15:15:23 +05:30
|
|
|
}
|
2020-08-05 21:07:37 +05:30
|
|
|
|
|
|
|
return xhr;
|
|
|
|
}
|
|
|
|
|
|
|
|
function xhrAsPromise(xhr, method, url) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
xhr.addEventListener("load", () => resolve(xhr));
|
|
|
|
xhr.addEventListener("abort", () => reject(new AbortError()));
|
|
|
|
xhr.addEventListener("error", () => reject(new ConnectionError(`Error ${method} ${url}`)));
|
|
|
|
xhr.addEventListener("timeout", () => reject(new ConnectionError(`Timeout ${method} ${url}`, true)));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export function xhrRequest(url, options) {
|
2020-11-16 15:15:46 +05:30
|
|
|
let {cache, format, body, method} = options;
|
2020-10-26 22:07:32 +05:30
|
|
|
if (!cache) {
|
|
|
|
url = addCacheBuster(url);
|
|
|
|
}
|
2020-11-16 15:15:46 +05:30
|
|
|
const xhr = createXhr(url, options);
|
|
|
|
const promise = xhrAsPromise(xhr, method, url).then(xhr => {
|
2020-08-05 21:07:37 +05:30
|
|
|
const {status} = xhr;
|
2020-10-05 20:48:05 +05:30
|
|
|
let body = null;
|
2020-10-26 22:07:32 +05:30
|
|
|
if (format === "buffer") {
|
|
|
|
body = xhr.response;
|
|
|
|
} else if (xhr.getResponseHeader("Content-Type") === "application/json") {
|
2020-10-06 16:32:18 +05:30
|
|
|
body = JSON.parse(xhr.responseText);
|
2020-08-05 21:07:37 +05:30
|
|
|
}
|
|
|
|
return {status, body};
|
|
|
|
});
|
2020-11-16 15:15:46 +05:30
|
|
|
|
|
|
|
// if a BlobHandle, take native blob
|
|
|
|
if (body?.nativeBlob) {
|
|
|
|
body = body.nativeBlob;
|
|
|
|
}
|
|
|
|
xhr.send(body || null);
|
|
|
|
|
2020-08-05 21:07:37 +05:30
|
|
|
return new RequestResult(promise, xhr);
|
|
|
|
}
|