Skip to content
This repository has been archived by the owner on Jul 12, 2019. It is now read-only.

Commit

Permalink
Prevent raw curies from being sent in a request. Allow removing empty…
Browse files Browse the repository at this point in the history
… values for body
  • Loading branch information
Steve Gardner committed May 27, 2019
1 parent 132ec04 commit 914941a
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 33 deletions.
20 changes: 2 additions & 18 deletions src/http-middlewares/before/add-query-params.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
'use strict';

const querystring = require('querystring');

const isCurlies = /{{.*?}}/g;
const shouldPruneQueryParam = value =>
value === '' ||
value === null ||
value === undefined ||
isCurlies.test(value);

// Mutates the object (it'll be deleted later anyway)
const pruneMissingQueryParams = params =>
Object.keys(params).forEach(param => {
if (shouldPruneQueryParam(params[param])) {
delete params[param];
}
});
const { normalizeEmptyParamField } = require('../../tools/cleaner');

const hasQueryParams = ({ params = {} }) => Object.keys(params).length;

Expand All @@ -26,9 +12,7 @@ const addQueryParams = req => {
if (hasQueryParams(req)) {
const splitter = req.url.includes('?') ? '&' : '?';

if (req.removeMissingValuesFrom.params) {
pruneMissingQueryParams(req.params);
}
Object.entries(req.params).forEach(normalizeEmptyParamField(req));

const stringifiedParams = querystring.stringify(req.params);

Expand Down
15 changes: 9 additions & 6 deletions src/http-middlewares/before/prepare-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ const _ = require('lodash');
const stream = require('stream');
const querystring = require('querystring');

const cleaner = require('../../tools/cleaner');
const {
createBundleBank,
normalizeEmptyBodyField,
recurseReplaceBank
} = require('../../tools/cleaner');
const requestMerge = require('../../tools/request-merge');
const {
getContentType,
Expand Down Expand Up @@ -56,6 +60,8 @@ const coerceBody = req => {
} else if (Buffer.isBuffer(req.body)) {
// leave a buffer alone!
} else if (req.body && !_.isString(req.body)) {
Object.entries(req.body).forEach(normalizeEmptyBodyField(req));

// this is a general - popular fallback
req.body = JSON.stringify(req.body);

Expand Down Expand Up @@ -120,11 +126,8 @@ const prepareRequest = function(req) {

// replace {{curlies}} in the request
if (req.replace) {
const bank = cleaner.createBundleBank(
input._zapier.app,
input._zapier.event
);
req = cleaner.recurseReplaceBank(req, bank);
const bank = createBundleBank(input._zapier.app, input._zapier.event);
req = recurseReplaceBank(req, bank);
}

req = coerceBody(req);
Expand Down
36 changes: 33 additions & 3 deletions src/tools/cleaner.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,39 @@ const createBundleBank = (appRaw, event = {}) => {

const maskOutput = output => _.pick(output, 'results', 'status');

const normalizeEmptyRequestField = (shouldCleanup, field) => req => {
const handleEmpty = req.removeMissingValuesFrom[field]
? key => delete req[field][key]
: key => (req[field][key] = '');

return ([key, value]) => {
if (shouldCleanup(value)) {
handleEmpty(key);
}
};
};

const isCurlies = /{{.*?}}/;
const isEmptyQueryParam = value =>
value === '' ||
value === null ||
value === undefined ||
isCurlies.test(value);

const normalizeEmptyParamField = normalizeEmptyRequestField(
isEmptyQueryParam,
'params'
);
const normalizeEmptyBodyField = normalizeEmptyRequestField(
v => isCurlies.test(v),
'body'
);

module.exports = {
recurseCleanFuncs,
recurseReplaceBank,
createBundleBank,
maskOutput
maskOutput,
normalizeEmptyBodyField,
normalizeEmptyParamField,
recurseCleanFuncs,
recurseReplaceBank
};
57 changes: 51 additions & 6 deletions test/create-request-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ describe('request client', () => {
});

describe('adds query params', () => {
it('should not omit empty params by default', () => {
it('should replace remaining curly params with empty string by default', () => {
const request = createAppRequestClient(input);
return request({
url: 'https://httpbin.org/get',
Expand All @@ -387,18 +387,18 @@ describe('request client', () => {
const response = JSON.parse(JSON.stringify(responseBefore));

response.json.args.something.should.eql('');
response.json.args.really.should.eql('{{bundle.inputData.really}}');
response.json.args.really.should.eql('');
response.json.args.cool.should.eql('true');
response.status.should.eql(200);

const body = JSON.parse(response.content);
body.url.should.eql(
'https://httpbin.org/get?something=&really={{bundle.inputData.really}}&cool=true'
'https://httpbin.org/get?something=&really=&cool=true'
);
});
});

it('should not omit empty params when set as false', () => {
it('should replace remaining curly params with empty string when set as false', () => {
const request = createAppRequestClient(input);
return request({
url: 'https://httpbin.org/get',
Expand All @@ -414,13 +414,13 @@ describe('request client', () => {
const response = JSON.parse(JSON.stringify(responseBefore));

response.json.args.something.should.eql('');
response.json.args.really.should.eql('{{bundle.inputData.really}}');
response.json.args.really.should.eql('');
response.json.args.cool.should.eql('true');
response.status.should.eql(200);

const body = JSON.parse(response.content);
body.url.should.eql(
'https://httpbin.org/get?something=&really={{bundle.inputData.really}}&cool=true'
'https://httpbin.org/get?something=&really=&cool=true'
);
});
});
Expand Down Expand Up @@ -460,6 +460,7 @@ describe('request client', () => {
should(response.json.args.foo).eql(undefined);
should(response.json.args.bar).eql(undefined);
should(response.json.args.empty).eql(undefined);
should(response.json.args.really).eql(undefined);
response.json.args.cool.should.eql('false');
response.json.args.zzz.should.eql('[]');
response.json.args.yyy.should.eql('{}');
Expand Down Expand Up @@ -574,13 +575,57 @@ describe('request client', () => {
}).then(response => {
const { json } = response.json;

should(json.empty).eql(undefined);
json.number.should.eql(123);
json.bool.should.eql(true);
json.float.should.eql(123.456);
json.arr.should.eql([1, 2, 3]);
});
});

it('should remove keys from body for empty values if configured to', () => {
const event = {
bundle: {
inputData: {
name: 'Burgundy'
}
}
};
const bodyInput = createInput({}, event, testLogger);
const request = createAppRequestClient(bodyInput);
return request({
url: 'https://httpbin.org/post',
method: 'POST',
body: {
name: '{{bundle.inputData.name}}',
empty: '{{bundle.inputData.empty}}'
},
removeMissingValuesFrom: {
body: true
}
}).then(response => {
const { json } = response.json;

should(json.empty).eql(undefined);
json.name.should.eql('Burgundy');
});
});

it('should replace curlies with an empty string by default', () => {
const request = createAppRequestClient(input);
return request({
url: 'https://httpbin.org/post',
method: 'POST',
body: {
empty: '{{bundle.inputData.empty}}'
}
}).then(response => {
const { json } = response.json;

should(json.empty).eql('');
});
});

it('should interpolate strings', () => {
const event = {
bundle: {
Expand Down

0 comments on commit 914941a

Please sign in to comment.