Skip to content

Commit

Permalink
✨ Request util to wrap got library (#8980)
Browse files Browse the repository at this point in the history
no issue

This PR includes a new util which wraps the `got` library. It is not used in the codebase yet, but tested with `image-size` util:
- wraps `got` request library in its own `request.js` util that returns bluebird promises and validates URL before starting a request
- adds tests
  • Loading branch information
aileen authored and ErisDS committed Sep 7, 2017
1 parent cdf6a10 commit 6c216b8
Show file tree
Hide file tree
Showing 2 changed files with 210 additions and 0 deletions.
24 changes: 24 additions & 0 deletions core/server/utils/request.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
var got = require('got'),
Promise = require('bluebird'),
validator = require('../data/validation').validator,
errors = require('../errors'),
_ = require('lodash');

module.exports = function request(url, options) {
if (_.isEmpty(url) || !validator.isURL(url)) {
return Promise.reject(new errors.InternalServerError({
message: 'URL empty or invalid.',
code: 'URL_MISSING_INVALID',
context: url
}));
}

return got(
url,
options
).then(function (response) {
return Promise.resolve(response);
}).catch(function (err) {
return Promise.reject(err);
});
};
186 changes: 186 additions & 0 deletions core/test/unit/utils/request_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
var should = require('should'),
sinon = require('sinon'),
rewire = require('rewire'),
nock = require('nock'),

// Stuff we are testing
request = rewire('../../../server/utils/request'),

sandbox = sinon.sandbox.create();

describe('Request', function () {
var result,
requestMock,
secondRequestMock;

afterEach(function () {
sandbox.restore();
});

it('[success] should return response for http request', function (done) {
var url = 'http://some-website.com/endpoint/',
expectedResponse =
{
body: 'Response body',
url: 'http://some-website.com/endpoint/',
statusCode: 200
},
options = {
headers: {
'User-Agent': 'Mozilla/5.0'
}
};

requestMock = nock('http://some-website.com')
.get('/endpoint/')
.reply(200, 'Response body');

result = request(url, options).then(function (res) {
requestMock.isDone().should.be.true();
should.exist(res);
should.exist(res.body);
res.body.should.be.equal(expectedResponse.body);
should.exist(res.url);
res.statusCode.should.be.equal(expectedResponse.statusCode);
should.exist(res.statusCode);
res.url.should.be.equal(expectedResponse.url);
done();
}).catch(done);
});

it('[success] can handle redirect', function (done) {
var url = 'http://some-website.com/endpoint/',
expectedResponse =
{
body: 'Redirected response',
url: 'http://someredirectedurl.com/files/',
statusCode: 200
},
options = {
headers: {
'User-Agent': 'Mozilla/5.0'
}
};

requestMock = nock('http://some-website.com')
.get('/endpoint/')
.reply(301, 'Oops, got redirected',
{
location: 'http://someredirectedurl.com/files/'
});

secondRequestMock = nock('http://someredirectedurl.com')
.get('/files/')
.reply(200, 'Redirected response');

result = request(url, options).then(function (res) {
requestMock.isDone().should.be.true();
secondRequestMock.isDone().should.be.true();
should.exist(res);
should.exist(res.body);
res.body.should.be.equal(expectedResponse.body);
should.exist(res.url);
res.statusCode.should.be.equal(expectedResponse.statusCode);
should.exist(res.statusCode);
res.url.should.be.equal(expectedResponse.url);
done();
}).catch(done);
});

it('[failure] can handle invalid url', function (done) {
var url = 'test',
options = {
headers: {
'User-Agent': 'Mozilla/5.0'
}
};

result = request(url, options)
.catch(function (err) {
should.exist(err);
err.message.should.be.equal('URL empty or invalid.');
done();
});
});

it('[failure] can handle empty url', function (done) {
var url = '',
options = {
headers: {
'User-Agent': 'Mozilla/5.0'
}
};

result = request(url, options)
.catch(function (err) {
should.exist(err);
err.message.should.be.equal('URL empty or invalid.');
done();
});
});

it('[failure] can handle an error with statuscode not 200', function (done) {
var url = 'http://nofilehere.com/files/test.txt',
options = {
headers: {
'User-Agent': 'Mozilla/5.0'
}
};

requestMock = nock('http://nofilehere.com')
.get('/files/test.txt')
.reply(404);

result = request(url, options)
.catch(function (err) {
requestMock.isDone().should.be.true();
should.exist(err);
err.statusMessage.should.be.equal('Not Found');
done();
});
});

it('[failure] will timeout', function (done) {
var url = 'http://nofilehere.com/files/test.txt',
options = {
headers: {
'User-Agent': 'Mozilla/5.0'
},
timeout: 10
};

requestMock = nock('http://nofilehere.com')
.get('/files/test.txt')
.socketDelay(11)
.reply(408);

result = request(url, options)
.catch(function (err) {
requestMock.isDone().should.be.true();
should.exist(err);
err.statusMessage.should.be.equal('Request Timeout');
done();
});
});

it('[failure] returns error if request errors', function (done) {
var url = 'http://nofilehere.com/files/test.txt',
options = {
headers: {
'User-Agent': 'Mozilla/5.0'
}
};

requestMock = nock('http://nofilehere.com')
.get('/files/test.txt')
.reply(500, {message: 'something aweful happend', code: 'AWFUL_ERROR'});

result = request(url, options)
.catch(function (err) {
requestMock.isDone().should.be.true();
should.exist(err);
err.statusMessage.should.be.equal('Internal Server Error');
done();
});
});
});

0 comments on commit 6c216b8

Please sign in to comment.