Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions lib/requester/request-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ var _ = require('lodash'),
cb(null, options);
};

module.exports = function (request, options, onStart, onData, callback) {
function requestWrapper (request, options, onStart, onData, callback) {
var req = {};

async.waterfall([
Expand All @@ -89,4 +89,7 @@ module.exports = function (request, options, onStart, onData, callback) {
});

return req;
};
}

module.exports = requestWrapper;
module.exports.request = requestWrapper;
Comment on lines +94 to +95
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done for adding testability + Keeping this module backwards compatible with the browser version of this.

15 changes: 13 additions & 2 deletions lib/requester/requester.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var _ = require('lodash'),
EventEmitter = require('events'),
now = require('performance-now'),
sdk = require('postman-collection'),
requests = require('./request-wrapper'),
requestWrapperModule = require('./request-wrapper'),
dryRun = require('./dry-run'),
SSEProcessor = require('./sse-processor'),

Expand Down Expand Up @@ -435,20 +435,31 @@ class Requester extends EventEmitter {
return onEnd(new Error(ERROR_RESTRICTED_ADDRESS + hostname));
}

const requests = requestWrapperModule.request || requestWrapperModule;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added for testability via Sinon stubbing


return requests(request, requestOptions, onStart, onData, function (err, res, resBody, debug) {
// prepare history from request debug data
var history = getExecutionHistory(debug),
responseTime,
response;

if (err) {
if (err && !err.res) {
// bubble up http errors
// @todo - Should we send an empty sdk Response here?
//
// Sending `history` object even in case of error
return onEnd(err, undefined, history);
}

// If the error has a response attached, use it to populate the response instead of treating
// it as a crash.
if (err && err.res) {
res = err.res;

if (Buffer.isBuffer(err.res.body)) {
resBody = err.res.body;
}
}

// Calculate the time taken for us to get the response.
responseTime = Date.now() - startTime;
Expand Down
82 changes: 82 additions & 0 deletions test/integration/sanity/error-with-response.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const sdk = require('postman-collection'),
sinon = require('sinon').createSandbox(),
requestWrapper = require('../../../lib/requester/request-wrapper');

(typeof window === 'undefined' ? describe : describe.skip)('handling of error with response', function () {
before(function (done) {
const fakeRequester = sinon.fake((_request, _requestOptions, onStart, _onData, callback) => {
const error = new Error('test error'),
mockResponse = {
status: 407,
statusMessage: 'Proxy Authentication Required',
body: Buffer.from('Proxy Authentication Required - Response Body from Proxy'),
headers: [],
request: {
_debug: [{
request: {
method: 'GET',
href: 'https://postman-echo.com/get',
headers: [],
httpVersion: '1.1'
},
response: {
downloadedBytes: 100
}
}]
}
};

mockResponse.getAllResponseHeaders = () => {
return mockResponse.headers;
};

error.res = mockResponse;

onStart(error.res); // Calling of onStart via the 'response' event is handled by the postman-request library
callback(error, null, null, mockResponse.request._debug);
});

sinon.stub(requestWrapper, 'request').callsFake(fakeRequester);

done();
});

after(function () {
sinon.restore();
});

it('should handle error with an attached response', function (done) {
this.run({ collection: { item: { request: 'https://postman-echo.com/get' } } }, function (err, results) {
if (err) {
return done(err);
}

const testrun = results;

sinon.assert.calledOnce(testrun.responseStart);
sinon.assert.calledOnce(testrun.response);
sinon.assert.calledOnce(testrun.done);

// Even though the callback to runtime returned an error, we handle the response attached to it
// and don't consider it as a crash.

let responseStartCalledWith = testrun.responseStart.getCall(0).args,
responseCalledWith = testrun.response.getCall(0).args,
doneCalledWith = testrun.done.getCall(0).args;

expect(responseStartCalledWith[0]).to.be.equal(null); // Not an error
expect(responseStartCalledWith[2]).to.be.instanceOf(sdk.Response);
expect(responseStartCalledWith[2].code).to.be.equal(407);

expect(responseCalledWith[0]).to.be.equal(null); // Not an error
expect(responseCalledWith[2]).to.be.instanceOf(sdk.Response);
expect(responseCalledWith[2].text()).to.be.equal('Proxy Authentication Required' +
' - Response Body from Proxy');
expect(responseCalledWith[2].code).to.be.equal(407);

expect(doneCalledWith[0]).to.be.equal(null); // Not an error

done();
});
});
});
Loading