What is the expected behavior?
When an interceptor does not match the body of the request, and allowUnmocked is true, the request should return the actual response.
What is the actual behavior?
The response object is somehow not getting the data from the request and just returns an undefined body.
Possible solution
I am a little bit stumped as to what is happening, but I did find that changing this line to add listeners on newReq that will propagate the event back to req will make the response return correctly. I have no idea why this works, and have been playing around with different possibilities, but none of them work except this one.
// propagate(newReq, req);
newReq.on('prefinish', function() {
req.emit('prefinish');
});
newReq.on('socket', function(socket) {
req.emit('socket', socket);
});
newReq.on('finish', function() {
req.emit('finish');
});
newReq.on('response', function(incomingMessage) {
req.emit('response', incomingMessage);
});
newReq.on('close', function() {
req.emit('close');
});
How to reproduce the issue
Runkit: _Example link_
Ran in Runkit.
const http = require('http')
const nock = require('[email protected]')
const data = {bar: 'baz'}
const request1 = http.request({
hostname: 'cat-fact.herokuapp.com',
path: '/facts/random',
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Content-Length': JSON.stringify(data).length
}
})
request1.on('response', response => {
response.on('data', data => console.log('real response:' + data.toString('utf8')));
});
request1.write(JSON.stringify(data))
request1.end()
// now we mock
nock('http://cat-fact.herokuapp.com')
.get("/facts/random", { bar: 'baz' }, { allowUnmocked: true })
.reply(200, { data: true })
.persist();
const request2 = http.request({
hostname: 'cat-fact.herokuapp.com',
path: '/facts/random',
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Content-Length': JSON.stringify(data).length
}
})
request2.on('response', response => {
response.on('data', data => console.log('mocked response (matched body): ' + data.toString('utf8')));
});
request2.write(JSON.stringify(data))
request2.end()
data.bar = 'biz';
const request3 = http.request({
hostname: 'cat-fact.herokuapp.com',
path: '/facts/random',
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Content-Length': JSON.stringify(data).length
}
})
request3.on('response', response => {
response.on('data', () => console.log('This will not be logged'));
response.on('end', () => console.log('Empty response (when the mock exists but the body did not match)'));
});
request3.write(JSON.stringify(data))
request3.end()
Does the bug have a test case?
Not that I can find.
Versions
| Software | Version(s) |
| -------- | ---------- |
| Nock | 10.0.6 & 11.0.0-beta.6 |
| Node | v9.11.2 & v10 |
Hi! Could you try with the latest beta release? As of now that's 11.0.0-beta.6.
Hi, tested it and the result is the same. The response gets no data.
Context:
propagate replaces the emit method with its own method that is not returning whether the event is handled or not. As we can see in the docs, emit Returns true if the event had listeners, false otherwise.
This causes node's http class to discard the response, since it thinks that there are no listeners for the response event. Node is checking the response of calling req.emit('response', res);, which with the propagate's emit method, is always undefined.
This is fixed with propagate 2.0.1, correct?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. We try to do our best, but nock is maintained by volunteers and there is only so much we can do at a time. Thank you for your contributions.
I just ran the example at the top in Runkit: https://runkit.com/melnikow/nock-1485
Can confirm that "This will not be logged" prints in nock 11.3.1 but not in 10.0.6. 馃憤