Add blobs.turbowarp.xyz fallback when fetching large assets
similar situation to cloud variables this should be more reliable in filtered environments https://github.com/TurboWarp/desktop/discussions/355#discussioncomment-2448055
This commit is contained in:
1 parent
8576a34ba1
commit
6969a07f2a
3 files changed
+105
-73
No files matched your search
+78
-59
@@ -1,71 +1,90 @@
|
||||
const clampProgress = (n) => Math.max(0, Math.min(1, n));
|
||||
|
||||
const request = ({
|
||||
url,
|
||||
type,
|
||||
progressCallback,
|
||||
timeout,
|
||||
estimatedSize,
|
||||
abortTarget
|
||||
}) => new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.onload = () => {
|
||||
cleanup();
|
||||
if (xhr.status === 200) {
|
||||
resolve(xhr.response);
|
||||
} else {
|
||||
reject(new Error(`Couldn't fetch ${url}: status code ${xhr.status}`));
|
||||
}
|
||||
};
|
||||
xhr.onerror = () => {
|
||||
cleanup();
|
||||
reject(new Error(`Couldn't fetch ${url}, are you offline?`));
|
||||
};
|
||||
const request = async (options) => {
|
||||
const {
|
||||
type,
|
||||
progressCallback,
|
||||
timeout,
|
||||
estimatedSize,
|
||||
abortTarget
|
||||
} = options;
|
||||
|
||||
if (progressCallback) {
|
||||
xhr.onprogress = (e) => {
|
||||
if (e.lengthComputable) {
|
||||
progressCallback(clampProgress(e.loaded / e.total));
|
||||
} else if (estimatedSize) {
|
||||
progressCallback(clampProgress(e.loaded / estimatedSize));
|
||||
const requestURL = (url) => new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.onload = () => {
|
||||
cleanup();
|
||||
if (xhr.status === 200) {
|
||||
resolve(xhr.response);
|
||||
} else {
|
||||
reject(new Error(`Couldn't fetch ${url}: status code ${xhr.status}`));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
xhr.responseType = type;
|
||||
xhr.open('GET', url);
|
||||
xhr.send();
|
||||
|
||||
const cleanup = () => {
|
||||
if (cleanupAbortCallback) {
|
||||
cleanupAbortCallback();
|
||||
}
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
};
|
||||
|
||||
let cleanupAbortCallback;
|
||||
if (abortTarget) {
|
||||
const abortCallback = () => {
|
||||
xhr.abort();
|
||||
xhr.onerror = () => {
|
||||
cleanup();
|
||||
reject(new Error(`Couldn't fetch ${url}: aborted`));
|
||||
reject(new Error(`Couldn't fetch ${url}, are you offline?`));
|
||||
};
|
||||
abortTarget.addEventListener('abort', abortCallback);
|
||||
cleanupAbortCallback = () => {
|
||||
abortTarget.removeEventListener('abort', abortCallback);
|
||||
|
||||
if (progressCallback) {
|
||||
xhr.onprogress = (e) => {
|
||||
if (e.lengthComputable) {
|
||||
progressCallback(clampProgress(e.loaded / e.total));
|
||||
} else if (estimatedSize) {
|
||||
progressCallback(clampProgress(e.loaded / estimatedSize));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
xhr.responseType = type;
|
||||
xhr.open('GET', url);
|
||||
xhr.send();
|
||||
|
||||
const cleanup = () => {
|
||||
if (cleanupAbortCallback) {
|
||||
cleanupAbortCallback();
|
||||
}
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let cleanupAbortCallback;
|
||||
if (abortTarget) {
|
||||
const abortCallback = () => {
|
||||
xhr.abort();
|
||||
cleanup();
|
||||
reject(new Error(`Couldn't fetch ${url}: aborted`));
|
||||
};
|
||||
abortTarget.addEventListener('abort', abortCallback);
|
||||
cleanupAbortCallback = () => {
|
||||
abortTarget.removeEventListener('abort', abortCallback);
|
||||
};
|
||||
}
|
||||
|
||||
let timeoutId;
|
||||
if (timeout) {
|
||||
timeoutId = setTimeout(() => {
|
||||
xhr.abort();
|
||||
cleanup();
|
||||
reject(new Error(`Couldn't fetch ${url}: timed out`));
|
||||
}, timeout);
|
||||
}
|
||||
});
|
||||
|
||||
let timeoutId;
|
||||
if (timeout) {
|
||||
timeoutId = setTimeout(() => {
|
||||
xhr.abort();
|
||||
cleanup();
|
||||
reject(new Error(`Couldn't fetch ${url}: timed out`));
|
||||
}, timeout);
|
||||
const urls = Array.isArray(options.url) ? options.url : [options.url];
|
||||
if (urls.length === 0) {
|
||||
throw new Error('no URLs');
|
||||
}
|
||||
});
|
||||
let errorToThrow;
|
||||
for (const url of urls) {
|
||||
try {
|
||||
return await requestURL(url);
|
||||
} catch (e) {
|
||||
if (!errorToThrow) {
|
||||
errorToThrow = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw errorToThrow;
|
||||
};
|
||||
|
||||
export default request;
|
||||
@@ -1,61 +1,72 @@
|
||||
const LARGE_ASSET_BASE = 'https://packagerdata.turbowarp.org/';
|
||||
const SCAFFOLDING_ROOT = 'scaffolding/';
|
||||
// This defines where files are fetched from when the packager needs to download files.
|
||||
// Files fetched from an external server have a SHA-256 checksum used to validate the download.
|
||||
// src is the URL that will be fetched to download the asset. If it's an array of URLs, each URL
|
||||
// will be tried in succession if the previous one fails, perhaps because it's blocked by a school
|
||||
// network filter.
|
||||
|
||||
const externalFile = (name) => [
|
||||
// Hopefully one of these URLs will not be blocked.
|
||||
`https://packagerdata.turbowarp.org/${name}`,
|
||||
`https://blobs.turbowarp.xyz/${name}`
|
||||
];
|
||||
|
||||
const relativeScaffolding = (name) => `scaffolding/${name}`;
|
||||
|
||||
export default {
|
||||
'nwjs-win64': {
|
||||
src: LARGE_ASSET_BASE + 'nwjs-v0.54.0-win-x64.zip',
|
||||
src: externalFile('nwjs-v0.54.0-win-x64.zip'),
|
||||
sha256: '0f082671b67b711f783d98cc989cf5aebacfc9bce3bef78875b57d08fc2a6e86',
|
||||
type: 'arraybuffer'
|
||||
},
|
||||
'nwjs-win32': {
|
||||
src: LARGE_ASSET_BASE + 'nwjs-v0.54.0-win-ia32.zip',
|
||||
src: externalFile('nwjs-v0.54.0-win-ia32.zip'),
|
||||
sha256: '7a1ed3a6a51b8cdf9280761b90cb4723cf9ee8050e3ed0b58451e8e4e694b203',
|
||||
type: 'arraybuffer'
|
||||
},
|
||||
'nwjs-mac': {
|
||||
src: LARGE_ASSET_BASE + 'nwjs-v0.54.0-osx-x64.zip',
|
||||
src: externalFile('nwjs-v0.54.0-osx-x64.zip'),
|
||||
sha256: '498c97a264f8feac504c4c2396c1fddc8290c15573aee2fc692e59ff9803cc40',
|
||||
type: 'arraybuffer'
|
||||
},
|
||||
'nwjs-linux-x64': {
|
||||
src: LARGE_ASSET_BASE + 'nwjs-v0.54.0-linux-x64.zip',
|
||||
src: externalFile('nwjs-v0.54.0-linux-x64.zip'),
|
||||
sha256: '53651a3a12d29ad096cff5b44d9f1e3aa09e9fad970bdcfe8bda07ea23d960d8',
|
||||
type: 'arraybuffer'
|
||||
},
|
||||
'electron-win32': {
|
||||
src: LARGE_ASSET_BASE + 'electron-v15.0.0-win32-ia32.zip',
|
||||
src: externalFile('electron-v15.0.0-win32-ia32.zip'),
|
||||
sha256: '5b69112b91010d78abf6012f387ea3fe5c0e36657c5f386a4c2bb42138aa1a8e',
|
||||
type: 'arraybuffer'
|
||||
},
|
||||
'electron-win64': {
|
||||
src: LARGE_ASSET_BASE + 'electron-v15.0.0-win32-x64.zip',
|
||||
src: externalFile('electron-v15.0.0-win32-x64.zip'),
|
||||
sha256: '3d95422d9f2fccb07b745b31007548231d80ff63e3640f49a5f8591498a3afa2',
|
||||
type: 'arraybuffer'
|
||||
},
|
||||
'electron-linux64': {
|
||||
src: LARGE_ASSET_BASE + 'electron-v15.1.1-linux-x64.zip',
|
||||
src: externalFile('electron-v15.1.1-linux-x64.zip'),
|
||||
sha256: '70de2da51c6a8591b88f08366c82166a51b1719243f67ef1a14eddbb806a115f',
|
||||
type: 'arraybuffer'
|
||||
},
|
||||
'webview-mac': {
|
||||
src: LARGE_ASSET_BASE + 'WebView-macos-3.zip',
|
||||
src: externalFile('WebView-macos-3.zip'),
|
||||
sha256: '5d4086894f10549c61c20e5f770c808afc25c2e4793da75b5b1cede294449fac',
|
||||
type: 'arraybuffer'
|
||||
},
|
||||
scaffolding: {
|
||||
src: SCAFFOLDING_ROOT + 'scaffolding.js',
|
||||
src: relativeScaffolding('scaffolding.js'),
|
||||
estimatedSize: 4775503,
|
||||
useBuildId: true,
|
||||
type: 'text'
|
||||
},
|
||||
'scaffolding-min': {
|
||||
src: SCAFFOLDING_ROOT + 'scaffolding-min.js',
|
||||
src: relativeScaffolding('scaffolding-min.js'),
|
||||
estimatedSize: 2540321,
|
||||
useBuildId: true,
|
||||
type: 'text'
|
||||
},
|
||||
addons: {
|
||||
src: SCAFFOLDING_ROOT + 'addons.js',
|
||||
src: relativeScaffolding('addons.js'),
|
||||
estimatedSize: 14339,
|
||||
useBuildId: true,
|
||||
type: 'text'
|
||||
|
||||
@@ -9,7 +9,9 @@ const STORE_NAME = 'assets';
|
||||
const db = new Database(DATABASE_NAME, DATABASE_VERSION, STORE_NAME);
|
||||
|
||||
const getAssetId = (asset) => {
|
||||
return `${asset.src}-${asset.type}-${asset.sha256 || buildId}`;
|
||||
const urls = asset.src;
|
||||
const firstURL = Array.isArray(urls) ? urls[0] : urls;
|
||||
return `${firstURL}-${asset.type}-${asset.sha256 || buildId}`;
|
||||
};
|
||||
|
||||
const removeExtraneous = async () => {
|
||||
|
||||
Reference in new issue
Block a user