use a separate loadTimeout for the actual data transfer (#931)

This commit is contained in:
tophf 2020-05-16 22:50:04 +03:00 committed by GitHub
parent 7ab0651e4d
commit 43f6bdf4ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -381,7 +381,8 @@ function download(url, {
body, body,
responseType = 'text', responseType = 'text',
requiredStatusCode = 200, requiredStatusCode = 200,
timeout = 10e3, timeout = 10e3, // connection timeout
loadTimeout = 2 * 60e3, // data transfer timeout (counted from the first remote response)
headers = { headers = {
'Content-type': 'application/x-www-form-urlencoded', 'Content-type': 'application/x-www-form-urlencoded',
}, },
@ -398,23 +399,41 @@ function download(url, {
const usoVars = []; const usoVars = [];
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let xhr;
const u = new URL(collapseUsoVars(url)); const u = new URL(collapseUsoVars(url));
if (u.protocol === 'file:' && FIREFOX) { const onTimeout = () => {
if (xhr) xhr.abort();
reject(new Error('Timeout fetching ' + u.href));
};
let timer = setTimeout(onTimeout, timeout);
const switchTimer = () => {
clearTimeout(timer);
timer = loadTimeout && setTimeout(onTimeout, loadTimeout);
};
if (u.protocol === 'file:' && FIREFOX) { // TODO: maybe remove this since FF68+ can't do it anymore
// https://stackoverflow.com/questions/42108782/firefox-webextensions-get-local-files-content-by-path // https://stackoverflow.com/questions/42108782/firefox-webextensions-get-local-files-content-by-path
// FIXME: add FetchController when it is available. // FIXME: add FetchController when it is available.
const timer = setTimeout(reject, timeout, new Error('Timeout fetching ' + u.href));
fetch(u.href, {mode: 'same-origin'}) fetch(u.href, {mode: 'same-origin'})
.then(r => { .then(r => {
clearTimeout(timer); switchTimer();
return r.status === 200 ? r.text() : Promise.reject(r.status); return r.status === 200 ? r.text() : Promise.reject(r.status);
}) })
.catch(reject) .catch(reject)
.then(resolve); .then(text => {
clearTimeout(timer);
resolve(text);
});
return; return;
} }
const xhr = new XMLHttpRequest(); xhr = new XMLHttpRequest();
xhr.timeout = timeout; xhr.onreadystatechange = () => {
if (xhr.readyState >= XMLHttpRequest.HEADERS_RECEIVED) {
xhr.onreadystatechange = null;
switchTimer();
}
};
xhr.onloadend = event => { xhr.onloadend = event => {
clearTimeout(timer);
if (event.type !== 'error' && ( if (event.type !== 'error' && (
xhr.status === requiredStatusCode || !requiredStatusCode || xhr.status === requiredStatusCode || !requiredStatusCode ||
u.protocol === 'file:')) { u.protocol === 'file:')) {