Skip to content

Commit

Permalink
Stringify query params which are objects as JSON
Browse files Browse the repository at this point in the history
Stringify query params which are objects in a way in which empty ararys
are preserved instead of removed (default querystring implementation).

fix: strongloop#324
  • Loading branch information
horiaradu authored and jskrzypek committed Sep 28, 2016
1 parent 7eae4d3 commit 608225c
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 1 deletion.
8 changes: 7 additions & 1 deletion lib/http-invocation.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,13 @@ HttpInvocation.prototype._processArg = function(req, verb, query, accept) {
// default to query string for GET
if (val !== undefined) {
query = query || {};
query[name] = val;

if ((accept.type === 'object' || accept.type === 'string') &&
typeof val === 'object') {
query[name] = JSON.stringify(val);
} else {
query[name] = val;
}
}
} else {
// default to storing args on the body for !GET
Expand Down
124 changes: 124 additions & 0 deletions test/http-invocation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,122 @@ describe('HttpInvocation', function() {
});
});
});

describe('createRequest', function() {
it('should create a simple request', function() {
var method = givenSharedStaticMethod();
method.getEndpoints = function() {
return [createEndpoint()];
};
var inv = new HttpInvocation(method, [], [], 'http://base');

var expectedReq = { method: 'GET',
url: 'http://base/testModel/testMethod',
protocol: 'http:',
json: true,
};
expect(inv.createRequest()).to.eql(expectedReq);
});

it('should make primitive type arguments as query params', function() {
var method = givenSharedStaticMethod({
accepts: [
{ arg: 'a', type: 'number' },
{ arg: 'b', type: 'string' },
],
});
method.getEndpoints = function() {
return [createEndpoint()];
};

var aValue = 2;
var bValue = 'foo';
var inv = new HttpInvocation(method, [], [aValue, bValue], 'http://base');

var expectedReq = { method: 'GET',
url: 'http://base/testModel/testMethod?a=2&b=foo',
protocol: 'http:',
json: true,
};
expect(inv.createRequest()).to.eql(expectedReq);
});

it('should make an array argument as a query param', function() {
var method = givenSharedStaticMethod({
accepts: [
{ arg: 'a', type: 'object' },
],
});
method.getEndpoints = function() {
return [createEndpoint()];
};

var aValue = [1, 2, 3];
var inv = new HttpInvocation(method, [], [aValue], 'http://base');

var expectedReq = { method: 'GET',
url: 'http://base/testModel/testMethod?a=' + encodeURIComponent('[1,2,3]'),
protocol: 'http:',
json: true,
};
expect(inv.createRequest()).to.eql(expectedReq);
});

it('should keep an empty array as a query param', function() {
var method = givenSharedStaticMethod({
accepts: [
{ arg: 'a', type: 'object' },
],
});
method.getEndpoints = function() {
return [createEndpoint()];
};

var aValue = [];
var inv = new HttpInvocation(method, [], [aValue], 'http://base');

var expectedReq = { method: 'GET',
url: 'http://base/testModel/testMethod?a=' + encodeURIComponent('[]'),
protocol: 'http:',
json: true,
};
expect(inv.createRequest()).to.eql(expectedReq);
});

it('should handle a loopback filter as a query param', function() {
var method = givenSharedStaticMethod({
accepts: [
{ arg: 'filter', type: 'object' },
],
});
method.getEndpoints = function() {
return [createEndpoint()];
};

var filter = {
where: {
id: {
inq: [1, 2],
},
typeId: {
inq: [],
},
},
include: ['related'],
};
var inv = new HttpInvocation(method, [], [filter], 'http://base');

var expectedFilter =
'{"where":{"id":{"inq":[1,2]},"typeId":{"inq":[]}},"include":["related"]}';
var expectedReq = { method: 'GET',
url: 'http://base/testModel/testMethod?filter=' +
encodeURIComponent(expectedFilter),
protocol: 'http:',
json: true,
};
expect(inv.createRequest()).to.eql(expectedReq);
});
});
});

function givenSharedStaticMethod(fn, config) {
Expand All @@ -200,3 +316,11 @@ function givenSharedStaticMethod(fn, config) {
extend(testClass.testMethod, config);
return SharedMethod.fromFunction(fn, 'testStaticMethodName', null, true);
}

function createEndpoint(config) {
config = config || {};
return {
verb: config.verb || 'GET',
fullPath: config.fullPath || '/testModel/testMethod',
};
}

0 comments on commit 608225c

Please sign in to comment.