diff --git a/test/integration.test.js b/test/integration.test.js new file mode 100644 index 00000000..7aae5dc0 --- /dev/null +++ b/test/integration.test.js @@ -0,0 +1,88 @@ +var net = require('net'); +describe('loopback application', function() { + it('pauses request stream during authentication', function(done) { + // This test reproduces the issue reported in + // https://github.com/strongloop/loopback-storage-service/issues/7 + var app = loopback(); + setupAppWithStreamingMethod(); + + app.listen(0, function() { + sendHttpRequestInOnePacket( + this.address().port, + 'POST /streamers/read HTTP/1.0\n' + + 'Content-Length: 1\n' + + 'Content-Type: application/x-custom-octet-stream\n' + + '\n' + + 'X', + function(err, res) { + if (err) return done(err); + expect(res).to.match(/\nX$/); + done(); + }); + }); + + function setupAppWithStreamingMethod() { + app.dataSource('db', { + connector: loopback.Memory, + defaultForType: 'db' + }); + var db = app.datasources.db; + + loopback.User.attachTo(db); + loopback.AccessToken.attachTo(db); + loopback.Role.attachTo(db); + loopback.ACL.attachTo(db); + loopback.User.hasMany(loopback.AccessToken, { as: 'accessTokens' }); + + var Streamer = app.model('Streamer', { dataSource: 'db' }); + Streamer.read = function(req, res, cb) { + var body = new Buffer(0); + req.on('data', function(chunk) { + body += chunk; + }); + req.on('end', function() { + res.end(body.toString()); + // we must not call the callback here + // because it will attempt to add response headers + }); + req.once('error', function(err) { + cb(err); + }); + }; + loopback.remoteMethod(Streamer.read, { + http: { method: 'post' }, + accepts: [ + { arg: 'req', type: 'Object', http: { source: 'req' } }, + { arg: 'res', type: 'Object', http: { source: 'res' } } + ] + }); + + app.enableAuth(); + app.use(loopback.token({ model: app.models.accessToken })); + app.use(loopback.rest()); + } + + function sendHttpRequestInOnePacket(port, reqString, cb) { + var socket = net.createConnection(port); + var response = new Buffer(0); + + socket.on('data', function(chunk) { + response += chunk; + }); + socket.on('end', function() { + callCb(null, response.toString()); + }); + socket.once('error', function(err) { + callCb(err); + }); + + socket.write(reqString.replace(/\n/g, '\r\n')); + + function callCb(err, res) { + if (!cb) return; + cb(err, res); + cb = null; + } + } + }); +});