Skip to content

Commit

Permalink
Merge branch 'satazor-request-promise'
Browse files Browse the repository at this point in the history
  • Loading branch information
pgte committed Mar 20, 2016
2 parents cd62565 477f159 commit e8459fc
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 83 deletions.
92 changes: 13 additions & 79 deletions lib/recorder.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,89 296,23 @@ function record(rec_options) {
return setEncoding.apply(this, arguments);
};

// Give the actual client a chance to setup its listeners.
// We will use the listener information to figure out
// how we need to feed the intercepted data back to the client.
if (callback) {
callback(res, options, callback);
}

// Handle clients that listen to 'readable' by intercepting them
// and feeding them the data manually.
var readableListeners = res.listeners('readable');
if (!_.isEmpty(readableListeners)) {

debug('handle readable listeners');

// We will replace the client's listeners with our own and manually
// invoke them.
_.each(readableListeners, function(listener) {
res.removeListener('readable', listener);
});

// Repleace the actual Stream.Readable prototype 'read' function
// so that we can control what the client listener will be reading.
var prototypeRead = Stream.Readable.prototype.read;
var currentReadIndex = 0;
res.read = function() {

debug(thisRecordingId, 'client reading data on', proto, dataChunks.length);

// Feed the data to the client through from our collected data chunks.
if (currentReadIndex < dataChunks.length) {
debug('chunk', chunk, 'read');
var chunk = dataChunks[currentReadIndex];
currentReadIndex;
return chunk;
} else {
debug('no more chunks to read');
return null;
}

};

// Put our own listener instead of the removed client listener.
var onReadable = function(data) {
debug(thisRecordingId, 'new readable data on', proto);
var chunk;
// Use the prototypeRead function to actually read the data.
while (null !== (chunk = prototypeRead.call(res))) {
debug('read', chunk);
dataChunks.push(chunk);
}
// Manually invoke the user listeners emulating 'readable' event.
_.each(readableListeners, function(listener) {
listener();
});
};

res.on('readable', onReadable);

} else {

// In all other cases we (for now at least) fall back on intercepting
// 'data' events.
debug('fall back on our original implementation');

// Since we gave client the chance to setup its listeners
// before us, we need to remove them and setup our own.
var dataListeners = res.listeners('data');
_.each(dataListeners, function(listener) {
res.removeListener('data', listener);
});

var onData = function(data) {
debug(thisRecordingId, 'new data chunk on', proto);
// Replace res.push with our own implementation that stores chunks
var origResPush = res.push;
res.push = function(data) {
if (data) {
if (encoding) {
data = new Buffer(data, encoding);
}
dataChunks.push(data);
// Manually invoke the user listeners emulating 'data' event.
_.each(dataListeners, function(listener) {
listener(data);
});
};
res.on('data', onData);
}

return origResPush.call(res, data);
}

if (callback) {
callback(res, options, callback);
} else {
res.resume();
}

debug('finished setting up intercepting');
Expand Down
2 changes: 1 addition & 1 deletion lib/scope.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 322,7 @@ function define(nockDefs) {
} else {
nock = startScope(nscope, options);
// If request headers were specified filter by them.
if (reqheaders !== {}) {
if (_.size(reqheaders) > 0) {
for (var k in reqheaders) {
nock.matchHeader(k, reqheaders[k]);
}
Expand Down
51 changes: 48 additions & 3 deletions tests/test_recorder.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 279,7 @@ tap.test('records nonstandard ports', function(t) {
var RESPONSE_BODY = '012345';

// Create test http server and perform the tests while it's up.
var testServer = http.createServer(function (req, res) {
var testServer = http.createServer(function(req, res) {
res.write(RESPONSE_BODY);
res.end();
}).listen(8081, function(err) {
Expand Down Expand Up @@ -474,7 474,7 @@ tap.test('records and replays gzipped nocks correctly when gzip is returned as a
t.ok(false);
t.end();
})
.on('error', function (error, response){
.on('error', function(error, response) {
t.ok(false);
t.end();
})
Expand Down Expand Up @@ -733,7 733,7 @@ tap.test('works with clients listening for readable', function(t) {
var RESPONSE_BODY = '012345';

// Create test http server and perform the tests while it's up.
var testServer = http.createServer(function (req, res) {
var testServer = http.createServer(function(req, res) {
res.write(RESPONSE_BODY);
res.end();
}).listen(8081, function(err) {
Expand Down Expand Up @@ -842,6 842,51 @@ tap.test('removes query params from from that path and puts them in query()', fu
req.end('ABCDEF');
});

tap.test("respects http.request() consumers", function(t) {
// Create test http server and perform the tests while it's up.
var testServer = http.createServer(function(req, res) {
res.write('foo');
setTimeout(function() {
res.end('bar');
}, 25);
}).listen(8082, function(err) {
t.equal(err, undefined);

nock.restore();
nock.recorder.clear();
nock.recorder.rec({
dont_print: true,
output_objects: true
});


var options = { host:'localhost'
, port:testServer.address().port
, path:'/' }
;
var req = http.request(options, function (res) {
var buffer = new Buffer('');

setTimeout(function () {
res
.on('data', function(data) {
buffer = Buffer.concat([buffer, data]);
})
.on('end', function() {
nock.restore();
t.equal(buffer.toString(), 'foobar');
t.end();

// Close the test server, we are done with it.
testServer.close();
});
});
}, 50);

req.end();
});
});

tap.test("teardown", function(t) {
var leaks = Object.keys(global)
.splice(globalCount, Number.MAX_VALUE);
Expand Down

0 comments on commit e8459fc

Please sign in to comment.