diff --git a/lib/http.js b/lib/http.js index 98a9ab9c87..8cc37ed47c 100644 --- a/lib/http.js +++ b/lib/http.js @@ -1289,8 +1289,10 @@ Agent.prototype._establishNewConnection = function() { // All that should be required for keep-alive is to not reconnect, // but outgoingFlush instead. if (!req.shouldKeepAlive) { - debug('AGENT socket.end()'); - if (socket.writable) socket.end(); + if (socket.writable) { + debug('AGENT socket.destroySoon()'); + socket.destroySoon(); + } assert(!socket.writable); } else { debug('AGENT socket keep-alive'); diff --git a/test/fixtures/person.jpg b/test/fixtures/person.jpg new file mode 100644 index 0000000000..4f71881c55 Binary files /dev/null and b/test/fixtures/person.jpg differ diff --git a/test/simple/test-http-get-pipeline-problem.js b/test/simple/test-http-get-pipeline-problem.js new file mode 100644 index 0000000000..5742372fec --- /dev/null +++ b/test/simple/test-http-get-pipeline-problem.js @@ -0,0 +1,87 @@ +// We are demonstrating a problem with http.get when queueing up many +// transfers. The server simply introduces some delay and sends a file. +// Note this is demonstarted with connection: close. +var common = require('../common'); +var assert = require('assert'); +var http = require('http'); +var fs = require('fs'); + +var image = fs.readFileSync(common.fixturesDir + '/person.jpg'); + +console.log("image.length = " + image.length); + +var total = 100; +var requests = 0, responses = 0; + +var server = http.Server(function(req, res) { + if (++requests == total) { + server.close(); + } + + setTimeout(function() { + res.writeHead(200, { + 'content-type': 'image/jpeg', + 'connection': 'close', + 'content-length': image.length + }); + res.end(image); + }, 1); +}); + + +server.listen(common.PORT, function() { + for (var i = 0; i < total; i++) { + (function() { + var x = i; + + var opts = { + port: common.PORT, + headers: { connection: 'close' } + }; + + http.get(opts, function(res) { + console.error("recv " + x); + var s = fs.createWriteStream(common.tmpDir + '/' + x + ".jpg"); + res.pipe(s); + + // TODO there should be a callback to pipe() that will allow + // us to get a callback when the pipe is finished. + res.on('end', function() { + console.error("done " + x); + if (++responses == total) { + s.on('close', checkFiles); + } + }); + }).on('error', function(e) { + console.error('error! ', e.message) + throw e; + }); + })(); + } +}); + + +var checkedFiles = false; +function checkFiles() { + // Should see 1.jpg, 2.jpg, ..., 100.jpg in tmpDir + var files = fs.readdirSync(common.tmpDir); + assert.equal(total, files.length); + + for (var i = 0; i < total; i++) { + var fn = i + '.jpg'; + assert.ok(files.indexOf(fn) >= 0, "couldn't find '" + fn + "'"); + var stat = fs.statSync(common.tmpDir + '/' + fn); + assert.equal(image.length, stat.size, + "size doesn't match on '" + fn + + "'. Got " + stat.size + " bytes"); + } + + checkedFiles = true; +} + + +process.on('exit', function() { + assert.equal(total, requests); + assert.equal(total, responses); + assert.ok(checkedFiles); +});