From 6184a70ba4d2e3eecff09545a6b4c9db4c96d198 Mon Sep 17 00:00:00 2001 From: Danny Coates Date: Wed, 14 Nov 2018 09:50:12 -0800 Subject: [PATCH] fixes #1005 The upstream gcp aggressively closes the connection once it has received Content-Length bytes. However the @google-cloud/storage module doesn't handle this well and emits no event in this case. We were setting Content-Length because it's slightly more efficient and was important for our download progress bar (not anymore). The download should function fine without setting the Content-Length, and allows the storage stream to finish before closing the upstream socket. --- app/api.js | 6 +++--- app/fileReceiver.js | 4 ++-- server/routes/download.js | 11 +---------- server/storage/gcs.js | 2 +- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/app/api.js b/app/api.js index 99ba8bad..54c6eb9a 100644 --- a/app/api.js +++ b/app/api.js @@ -162,8 +162,8 @@ function download(id, keychain, onprogress, canceller) { }); xhr.addEventListener('progress', function(event) { - if (event.lengthComputable && event.target.status === 200) { - onprogress([event.loaded, event.total]); + if (event.target.status === 200) { + onprogress(event.loaded); } }); const auth = await keychain.authHeader(); @@ -171,7 +171,7 @@ function download(id, keychain, onprogress, canceller) { xhr.setRequestHeader('Authorization', auth); xhr.responseType = 'blob'; xhr.send(); - onprogress([0, 1]); + onprogress(0); }); } diff --git a/app/fileReceiver.js b/app/fileReceiver.js index 27dccf6d..23fc7567 100644 --- a/app/fileReceiver.js +++ b/app/fileReceiver.js @@ -47,7 +47,7 @@ export default class FileReceiver extends Nanobus { this.fileInfo.name = meta.name; this.fileInfo.type = meta.type; this.fileInfo.iv = meta.iv; - this.fileInfo.size = meta.size; + this.fileInfo.size = +meta.size; this.state = 'ready'; } @@ -57,7 +57,7 @@ export default class FileReceiver extends Nanobus { this.fileInfo.id, this.keychain, p => { - this.progress = p; + this.progress = [p, this.fileInfo.size]; this.emit('progress'); } ); diff --git a/server/routes/download.js b/server/routes/download.js index 8e1ecf98..c49c29ec 100644 --- a/server/routes/download.js +++ b/server/routes/download.js @@ -6,13 +6,6 @@ module.exports = async function(req, res) { const id = req.params.id; try { const meta = req.meta; - const contentLength = await storage.length(id); - res.writeHead(200, { - 'Content-Disposition': 'attachment', - 'Content-Type': 'application/octet-stream', - 'Content-Length': contentLength, - 'WWW-Authenticate': `send-v1 ${req.nonce}` - }); const file_stream = storage.get(id); let cancelled = false; @@ -21,7 +14,7 @@ module.exports = async function(req, res) { file_stream.destroy(); }); - file_stream.on('end', async () => { + file_stream.pipe(res).on('finish', async () => { if (cancelled) { return; } @@ -38,8 +31,6 @@ module.exports = async function(req, res) { log.info('StorageError:', id); } }); - - file_stream.pipe(res); } catch (e) { res.sendStatus(404); } diff --git a/server/storage/gcs.js b/server/storage/gcs.js index 8db209e7..1b7d0c5a 100644 --- a/server/storage/gcs.js +++ b/server/storage/gcs.js @@ -13,7 +13,7 @@ class GCSStorage { } getStream(id) { - return this.bucket.file(id).createReadStream(); + return this.bucket.file(id).createReadStream({ validation: false }); } set(id, file) {