mirror of
https://github.com/zotero/zotero.git
synced 2026-11-14 09:21:32 +00:00
Treat dropped download connections as status 0 again
Since HTTP.download() switched to fetch() in 10.0, a connection that
dropped mid-download threw a TypeError ("Error in input stream"), so
ZFS sync no longer retried interrupted S3 downloads and failed the file
sync immediately.
https://forums.zotero.org/discussion/134446/sync-error
(cherry picked from commit d85ec125be)
This commit is contained in:
parent
a4b7102b94
commit
fffea9717c
2 changed files with 44 additions and 2 deletions
|
|
@ -727,6 +727,14 @@ Zotero.HTTP = new function () {
|
|||
}, timeout);
|
||||
}
|
||||
|
||||
// Report a dropped connection as status 0, as request() does, so that callers and
|
||||
// _retryOnServerError() handle it the same way
|
||||
function connectionError(e) {
|
||||
let msg = "HTTP GET " + ctx.dispURL + " failed: " + e;
|
||||
Zotero.debug(msg, 1);
|
||||
return new Zotero.HTTP.UnexpectedStatusException({ status: 0 }, url, msg);
|
||||
}
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(url, fetchOptions);
|
||||
|
|
@ -737,7 +745,7 @@ Zotero.HTTP = new function () {
|
|||
if (controller.signal.aborted) {
|
||||
throw new Zotero.HTTP.TimeoutException(timeout);
|
||||
}
|
||||
throw e;
|
||||
throw connectionError(e);
|
||||
}
|
||||
clearTimeout(connectTimerID);
|
||||
|
||||
|
|
@ -777,7 +785,9 @@ Zotero.HTTP = new function () {
|
|||
await IOUtils.write(path, new Uint8Array());
|
||||
while (true) {
|
||||
resetInactivityTimer();
|
||||
let { done, value } = await reader.read();
|
||||
let { done, value } = await reader.read().catch((e) => {
|
||||
throw connectionError(e);
|
||||
});
|
||||
if (done) break;
|
||||
await IOUtils.write(path, value, { mode: 'append' });
|
||||
totalBytes += value.byteLength;
|
||||
|
|
|
|||
|
|
@ -424,6 +424,20 @@ describe("Zotero.HTTP", function () {
|
|||
}
|
||||
}
|
||||
);
|
||||
httpd.registerPathHandler(
|
||||
'/download/truncated',
|
||||
{
|
||||
handle: function (request, response) {
|
||||
response.seizePower();
|
||||
response.write("HTTP/1.1 200 OK\r\n"
|
||||
+ "Content-Type: application/octet-stream\r\n"
|
||||
+ "Content-Length: 10000\r\n"
|
||||
+ "\r\n"
|
||||
+ "x".repeat(100));
|
||||
response.finish();
|
||||
}
|
||||
}
|
||||
);
|
||||
httpd.registerPathHandler(
|
||||
'/download/redirect-to-file',
|
||||
{
|
||||
|
|
@ -564,6 +578,24 @@ describe("Zotero.HTTP", function () {
|
|||
assert.isFalse(await IOUtils.exists(dest));
|
||||
});
|
||||
|
||||
it("should throw UnexpectedStatusException with status 0 if the connection is refused", async function () {
|
||||
let dest = PathUtils.join(tmpDir, "refused.bin");
|
||||
let e = await getPromiseError(
|
||||
Zotero.HTTP.download("http://127.0.0.1:1/", dest)
|
||||
);
|
||||
assert.instanceOf(e, Zotero.HTTP.UnexpectedStatusException);
|
||||
assert.equal(e.status, 0);
|
||||
});
|
||||
|
||||
it("should throw UnexpectedStatusException with status 0 if the connection drops during the download", async function () {
|
||||
let dest = PathUtils.join(tmpDir, "truncated.bin");
|
||||
let e = await getPromiseError(
|
||||
Zotero.HTTP.download(baseURL + "download/truncated", dest)
|
||||
);
|
||||
assert.instanceOf(e, Zotero.HTTP.UnexpectedStatusException);
|
||||
assert.equal(e.status, 0);
|
||||
});
|
||||
|
||||
it("should allow non-success status with successCodes", async function () {
|
||||
let dest = PathUtils.join(tmpDir, "404.bin");
|
||||
let req = await Zotero.HTTP.download(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue