From 9ff1203688eb50410c25bb93396e00b1885435c1 Mon Sep 17 00:00:00 2001 From: Alex Kocharin Date: Fri, 7 Mar 2014 19:48:24 +0000 Subject: [PATCH] throw away incomplete downloads --- lib/storage.js | 1 - lib/up-storage.js | 13 ++++++- test/functional/incomplete.js | 68 +++++++++++++++++++++++++++++++++++ test/functional/index.js | 1 + test/functional/racycrash.js | 23 ++++++++++-- 5 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 test/functional/incomplete.js diff --git a/lib/storage.js b/lib/storage.js index 25836fc07..2d7776615 100644 --- a/lib/storage.js +++ b/lib/storage.js @@ -265,7 +265,6 @@ Storage.prototype.get_tarball = function(name, filename) { }) rstream2.on('content-length', function(v) { -console.log('!!!!!!!!!!!!!!!!!!!!!!!', v) stream.emit('content-length', v) savestream.emit('content-length', v) }) diff --git a/lib/up-storage.js b/lib/up-storage.js index cdebd8e8e..a2ff7ab9c 100644 --- a/lib/up-storage.js +++ b/lib/up-storage.js @@ -241,6 +241,7 @@ Storage.prototype.get_tarball = function(name, options, filename) { Storage.prototype.get_url = function(url) { var stream = new mystreams.ReadTarballStream() stream.abort = function() {} + var current_length = 0, expected_length var rstream = this.request({ uri_full: url, @@ -263,8 +264,10 @@ Storage.prototype.get_url = function(url) { status: 500, })) } - if (res.headers['content-length']) + if (res.headers['content-length']) { + expected_length = res.headers['content-length'] stream.emit('content-length', res.headers['content-length']) + } rstream.pipe(stream) }) @@ -272,6 +275,14 @@ Storage.prototype.get_url = function(url) { rstream.on('error', function(err) { stream.emit('error', err) }) + rstream.on('data', function(d) { + current_length += d.length + }) + rstream.on('end', function(d) { + if (d) current_length += d.length + if (expected_length && current_length != expected_length) + stream.emit('error', new Error('content length mismatch')) + }) return stream } diff --git a/test/functional/incomplete.js b/test/functional/incomplete.js new file mode 100644 index 000000000..c111d76cc --- /dev/null +++ b/test/functional/incomplete.js @@ -0,0 +1,68 @@ +var assert = require('assert') + , ex = module.exports + +module.exports = function() { + var server = process.server + var express = process.express + + describe('Incomplete', function() { + var on_tarball + + before(function() { + express.get('/testexp-incomplete', function(_, res) { + res.send({ + "name": "testexp-incomplete", + "versions": { + "0.1.0": { + "name": "testexp_tags", + "version": "0.1.0", + "dist": { + "shasum": "fake", + "tarball": "http://localhost:55550/testexp-incomplete/-/content-length.tar.gz" + } + }, + "0.1.1": { + "name": "testexp_tags", + "version": "0.1.1", + "dist": { + "shasum": "fake", + "tarball": "http://localhost:55550/testexp-incomplete/-/chunked.tar.gz" + } + } + } + }) + }) + }) + + ;['content-length', 'chunked'].forEach(function(type) { + it('should not store tarballs / ' + type, function(_cb) { + var called + express.get('/testexp-incomplete/-/'+type+'.tar.gz', function(_, res) { + if (called) return res.socket.destroy() + called = true + if (type !== 'chunked') res.header('content-length', 1e6) + res.write('test test test\n') + setTimeout(function() { + res.socket.write('200\nsss\n') + res.socket.destroy() + cb() + }, 10) + }) + + server.request({uri:'/testexp-incomplete/-/'+type+'.tar.gz'}, function(err, res, body) { + if (type !== 'chunked') assert.equal(res.headers['content-length'], 1e6) + assert(body.match(/test test test/)) + }) + + function cb() { + server.request({uri:'/testexp-incomplete/-/'+type+'.tar.gz'}, function(err, res, body) { +console.log(err, body) + assert.equal(body.error, 'internal server error') + _cb() + }) + } + }) + }) + }) +} + diff --git a/test/functional/index.js b/test/functional/index.js index 2a8c2247a..eb2162ed0 100644 --- a/test/functional/index.js +++ b/test/functional/index.js @@ -39,6 +39,7 @@ describe('Func', function() { require('./basic')() require('./gh29')() require('./tags')() + require('./incomplete')() require('./mirror')() require('./race')() require('./racycrash')() diff --git a/test/functional/racycrash.js b/test/functional/racycrash.js index 8ed4d0dec..d803be5c4 100644 --- a/test/functional/racycrash.js +++ b/test/functional/racycrash.js @@ -6,7 +6,9 @@ module.exports = function() { var express = process.express describe('Racy', function() { - it('should not crash on error if client disconnects', function(_cb) { + var on_tarball + + before(function() { express.get('/testexp-racycrash', function(_, res) { res.send({ "name": "testexp-racycrash", @@ -24,6 +26,12 @@ module.exports = function() { }) express.get('/testexp-racycrash/-/test.tar.gz', function(_, res) { + on_tarball(res) + }) + }) + + it('should not crash on error if client disconnects', function(_cb) { + on_tarball = function(res) { res.header('content-length', 1e6) res.write('test test test\n') setTimeout(function() { @@ -31,7 +39,7 @@ module.exports = function() { res.socket.destroy() cb() }, 200) - }) + } server.request({uri:'/testexp-racycrash/-/test.tar.gz'}, function(err, res, body) { assert.equal(body, 'test test test\n') @@ -45,6 +53,17 @@ module.exports = function() { }) } }) + + it('should not store tarball', function(cb) { + on_tarball = function(res) { + res.socket.destroy() + } + + server.request({uri:'/testexp-racycrash/-/test.tar.gz'}, function(err, res, body) { + assert.equal(body.error, 'internal server error') + cb() + }) + }) }) }