From 5ff92c64529de99ed19858ec3e7eb06db4700710 Mon Sep 17 00:00:00 2001 From: Emily Date: Thu, 12 Jul 2018 14:00:22 -0700 Subject: [PATCH 1/2] fix cancelled downloads increasing count --- server/routes/download.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/server/routes/download.js b/server/routes/download.js index b320d899..8fe177c7 100644 --- a/server/routes/download.js +++ b/server/routes/download.js @@ -15,9 +15,14 @@ module.exports = async function(req, res) { }); const file_stream = storage.get(id); let sentBytes = 0; + let cancelled = false; + + req.on('close', () => (cancelled = true)); + file_stream.on('data', c => (sentBytes += c.length)); + file_stream.on('end', async () => { - if (sentBytes < contentLength) { + if (cancelled) { return; } const dl = meta.dl + 1; @@ -32,6 +37,7 @@ module.exports = async function(req, res) { log.info('StorageError:', id); } }); + file_stream.pipe(res); } catch (e) { res.sendStatus(404); From 527e9f09c9b83f9cdac868bf9fc100d06042db94 Mon Sep 17 00:00:00 2001 From: Emily Date: Thu, 12 Jul 2018 16:07:18 -0700 Subject: [PATCH 2/2] add a test --- app/api.js | 3 +++ server/routes/download.js | 10 +++++----- test/frontend/tests/workflow-tests.js | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/app/api.js b/app/api.js index e314657d..7d9fb394 100644 --- a/app/api.js +++ b/app/api.js @@ -160,6 +160,7 @@ function download(id, keychain, onprogress, canceller) { resolve(this.result); }; }); + xhr.addEventListener('progress', function(event) { if (event.lengthComputable && event.target.status === 200) { onprogress([event.loaded, event.total]); @@ -168,8 +169,10 @@ function download(id, keychain, onprogress, canceller) { const auth = await keychain.authHeader(); xhr.open('get', `/api/download/${id}`); xhr.setRequestHeader('Authorization', auth); + xhr.setRequestHeader('Connection', 'close'); xhr.responseType = 'blob'; xhr.send(); + onprogress([0, 1]); }); } diff --git a/server/routes/download.js b/server/routes/download.js index 8fe177c7..84ba715d 100644 --- a/server/routes/download.js +++ b/server/routes/download.js @@ -14,14 +14,14 @@ module.exports = async function(req, res) { 'WWW-Authenticate': `send-v1 ${req.nonce}` }); const file_stream = storage.get(id); - let sentBytes = 0; let cancelled = false; - req.on('close', () => (cancelled = true)); + req.on('close', () => { + cancelled = true; + file_stream.destroy(); + }); - file_stream.on('data', c => (sentBytes += c.length)); - - file_stream.on('end', async () => { + file_stream.on('close', async () => { if (cancelled) { return; } diff --git a/test/frontend/tests/workflow-tests.js b/test/frontend/tests/workflow-tests.js index 23bc8efc..69eba9dd 100644 --- a/test/frontend/tests/workflow-tests.js +++ b/test/frontend/tests/workflow-tests.js @@ -134,6 +134,27 @@ describe('Upload / Download flow', function() { } }); + it('can cancel and not increase download count', async function() { + const fs = new FileSender(blob); + const file = await fs.upload(); + const fr = new FileReceiver({ + secretKey: file.toJSON().secretKey, + id: file.id, + nonce: file.keychain.nonce, + requiresPassword: false + }); + await fr.getMetadata(); + fr.once('progress', () => fr.cancel()); + + try { + await fr.download(noSave); + assert.fail('not cancelled'); + } catch (e) { + await file.updateDownloadCount(); + assert.equal(file.dtotal, 0); + } + }); + it('can allow multiple downloads', async function() { const fs = new FileSender(blob); const file = await fs.upload();