Skip to content

Commit

Permalink
[Fixes #81] Don't throw on invalid fetcher access
Browse files Browse the repository at this point in the history
  • Loading branch information
Vijar committed Jun 16, 2015
1 parent 2f0d568 commit 6b22531
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 47 deletions.
46 changes: 40 additions & 6 deletions libs/fetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ var OP_UPDATE = 'update';
var GET = 'GET';
var qs = require('querystring');
var debug = require('debug')('Fetchr');
var fumble = require('fumble');

function parseValue(value) {
// take care of value of type: array, object
Expand Down Expand Up @@ -80,6 +81,16 @@ function parseParamValues (params) {
return Fetcher.fetchers[name];
};

/**
* @method hasFetcher
* @memberof Fetcher
* @param {String} name
* @returns {Boolean} true if fetcher with name was registered
*/
Fetcher.hasFetcher = function (name) {
return name && Fetcher.fetchers[name];
};

/**
* @method middleware
* @memberof Fetcher
Expand All @@ -91,12 +102,23 @@ function parseParamValues (params) {
Fetcher.middleware = function () {
return function (req, res, next) {
var request;
var error;

if (req.method === GET) {
var path = req.path.substr(1).split(';');
var resource = path.shift();

if (!Fetcher.hasFetcher(resource)) {
error = fumble.http.badRequest('Invalid Fetchr Access', {
debug: 'Bad resource ' + resource
});
error.source = 'fetchr';
return next(error);
}

request = {
req: req,
resource: path.shift(),
resource: resource,
operation: OP_READ,
params: parseParamValues(qs.parse(path.join('&'))),
config: {},
Expand All @@ -115,15 +137,27 @@ function parseParamValues (params) {
}
};
} else {
var requests = req.body.requests;
var requests = req.body && req.body.requests;

if (!requests || Object.keys(requests).length === 0) {
res.status(400).end();
return;
error = fumble.http.badRequest('Invalid Fetchr Access', {
debug: 'No resources'
});
error.source = 'fetchr';
return next(error);
}

var DEFAULT_GUID = 'g0';
var singleRequest = requests[DEFAULT_GUID];

if (!Fetcher.hasFetcher(singleRequest.resource)) {
error = fumble.http.badRequest('Invalid Fetchr Access', {
debug: 'Bad resource ' + singleRequest.resource
});
error.source = 'fetchr';
return next(error);
}

var DEFAULT_GUID = 'g0',
singleRequest = requests[DEFAULT_GUID];
request = {
req: req,
resource: singleRequest.resource,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
],
"dependencies": {
"debug": "^2.0.0",
"fumble": "^0.1.0",
"lodash": "^3.3.0",
"xhr": "^2.0.0"
},
Expand Down
78 changes: 37 additions & 41 deletions tests/unit/libs/fetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,39 +35,6 @@ describe('Server Fetcher', function () {

describe('#middleware', function () {
describe('#POST', function() {
it('should 404 to POST request with no req.body.requests object', function (done) {
var operation = 'create',
statusCodeSet = false,
req = {
method: 'POST',
path: '/' + mockService.name,
body: {
requests: {},
context: {
site: '',
device: ''
}
}
},
res = {
status: function (code) {
expect(code).to.equal(400);
statusCodeSet = true;
return this;
},
end: function () {
done();
}
},
next = function () {
console.log('Not Expected: middleware skipped request');
},
middleware = Fetcher.middleware();

middleware(req, res, next);
expect(statusCodeSet).to.be.true;
});

it('should respond to POST api request', function (done) {
var operation = 'create',
statusCodeSet = false,
Expand Down Expand Up @@ -101,6 +68,7 @@ describe('Server Fetcher', function () {
expect(data.operation.success).to.be.true;
expect(data.args).to.contain.keys('params');
expect(data.args.params).to.equal(req.body.requests.g0.params);
expect(statusCodeSet).to.be.true;
done();
},
status: function(code) {
Expand All @@ -118,7 +86,6 @@ describe('Server Fetcher', function () {
middleware = Fetcher.middleware();

middleware(req, res, next);
expect(statusCodeSet).to.be.true;
});

it('should respond to POST api request with custom status code and custom headers', function (done) {
Expand Down Expand Up @@ -157,6 +124,8 @@ describe('Server Fetcher', function () {
expect(data.operation.success).to.be.true;
expect(data.args).to.contain.keys('params');
expect(data.args.params).to.equal(req.body.requests.g0.params);
expect(headersSet).to.eql(responseHeaders);
expect(statusCodeSet).to.be.true;
done();
},
status: function(code) {
Expand All @@ -183,8 +152,6 @@ describe('Server Fetcher', function () {
};

middleware(req, res, next);
expect(statusCodeSet).to.be.true;
expect(headersSet).to.eql(responseHeaders);
});

var makePostApiErrorTest = function(params, expStatusCode, expMessage) {
Expand All @@ -211,6 +178,7 @@ describe('Server Fetcher', function () {
res = {
json: function(data) {
expect(data).to.eql(expMessage);
expect(statusCodeSet).to.be.true;
done();
},
status: function(code) {
Expand All @@ -227,7 +195,6 @@ describe('Server Fetcher', function () {
},
middleware = Fetcher.middleware({pathPrefix: '/api'});
middleware(req, res, next);
expect(statusCodeSet).to.be.true;
};
};

Expand Down Expand Up @@ -262,6 +229,7 @@ describe('Server Fetcher', function () {
expect(response.operation.success).to.be.true;
expect(response.args).to.contain.keys('params');
expect(response.args.params).to.deep.equal(params);
expect(statusCodeSet).to.be.true;
done();
},
status: function(code) {
Expand All @@ -279,7 +247,6 @@ describe('Server Fetcher', function () {
middleware = Fetcher.middleware({pathPrefix: '/api'});

middleware(req, res, next);
expect(statusCodeSet).to.be.true;
});

it('should respond to GET api request with custom status code and custom headers', function (done) {
Expand All @@ -305,6 +272,8 @@ describe('Server Fetcher', function () {
expect(response.operation.success).to.be.true;
expect(response.args).to.contain.keys('params');
expect(response.args.params).to.deep.equal(params);
expect(statusCodeSet).to.be.true;
expect(headersSet).to.eql(responseHeaders);
done();
},
set: function(headers) {
Expand All @@ -330,8 +299,6 @@ describe('Server Fetcher', function () {
statusCode: statusCode
};
middleware(req, res, next);
expect(statusCodeSet).to.be.true;
expect(headersSet).to.eql(responseHeaders);
});

var makeGetApiErrorTest = function(params, expStatusCode, expMessage) {
Expand All @@ -345,6 +312,7 @@ describe('Server Fetcher', function () {
res = {
json: function(data) {
expect(data).to.eql(expMessage);
expect(statusCodeSet).to.be.true;
done();
},
status: function(code) {
Expand All @@ -361,7 +329,6 @@ describe('Server Fetcher', function () {
},
middleware = Fetcher.middleware({pathPrefix: '/api'});
middleware(req, res, next);
expect(statusCodeSet).to.be.true;
};
};

Expand All @@ -374,6 +341,35 @@ describe('Server Fetcher', function () {
it('should respond to GET api request with custom error message',
makeGetApiErrorTest({message: 'Error message...'}, 400, {message: 'Error message...'}));
});

describe('Invalid Access', function () {
function makeInvalidReqTest(req, done) {
var res = {};
var next = function (err) {
expect(err).to.exist;
expect(err).to.be.an.object;
expect(err.message).to.equal('Invalid Fetchr Access');
expect(err.statusCode).to.equal(400);
expect(err.source).to.equal('fetchr');
done();
};
var middleware = Fetcher.middleware();
middleware(req, res, next);
}
it('should skip empty url', function (done) {
makeInvalidReqTest({method: 'GET', path: '/'}, done);
});
it('should skip invalid resource', function (done) {
makeInvalidReqTest({method: 'GET', path: '/invalidService'}, done);
});
it('should skip POST request with empty req.body.requests object', function (done) {
makeInvalidReqTest({method: 'POST', body: { requests: {}}}, done);
});
it('should skip POST request with no req.body.requests object', function (done) {
makeInvalidReqTest({method: 'POST'}, done);
});

});
});

describe('#CRUD', function () {
Expand Down

0 comments on commit 6b22531

Please sign in to comment.