Skip to content

Commit cc3f523

Browse files
authored
Merge pull request #8 from f5devcentral/http-fetch
HTTP fetch and forwarding
2 parents 107bf67 + 606a18f commit cc3f523

File tree

6 files changed

+261
-26
lines changed

6 files changed

+261
-26
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# v0.7.0
22
## Added
33
* Add jsdoc-style docs to classes mentioned in the README
4+
* Add option to get variable values from HTTP requests
5+
* Add Template.forwardHttp() to forward a rendered template result to an HTTP server
46

57
## Fixed
68
* Improve guiUtils.filterExtraProperties() when using template merging

lib/http_utils.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@ const makeRequest = (opts, payload) => {
2323
res.on('end', () => {
2424
let body = buffer.join('');
2525
body = body || '{}';
26-
try {
27-
body = JSON.parse(body);
28-
} catch (e) {
29-
return reject(new Error(`Invalid response object from ${combOpts.method} to ${combOpts.path}`));
26+
if (combOpts.headers && combOpts.headers['Content-Type'] === 'application/json') {
27+
try {
28+
body = JSON.parse(body);
29+
} catch (e) {
30+
return reject(
31+
new Error(`Invalid response object from ${combOpts.method} to ${combOpts.path}`)
32+
);
33+
}
3034
}
3135
return resolve({
3236
status: res.statusCode,

lib/template.js

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const $RefParser = require('@apidevtools/json-schema-ref-parser');
99
const url = require('url');
1010
const deepmerge = require('deepmerge');
1111
const path = require('path');
12+
const jsonpath = require('jsonpath');
1213

1314
const httpUtils = require('./http_utils');
1415

@@ -114,6 +115,7 @@ class Template {
114115
this._allOf = [];
115116
this._anyOf = [];
116117
this.contentType = 'text/plain';
118+
this.httpForward = null;
117119
}
118120

119121
_loadTypeSchemas(schemaProvider) {
@@ -431,12 +433,9 @@ class Template {
431433
_createParametersValidator() {
432434
const loadSchema = (uri) => {
433435
uri = url.parse(uri);
434-
const opts = {
435-
host: uri.host,
436-
port: uri.port,
437-
parth: uri.pathName,
436+
const opts = Object.assign({}, url.parse(uri), {
438437
method: 'GET'
439-
};
438+
});
440439
return httpUtils.makeRequest(opts)
441440
.then((res) => {
442441
if (res.statusCode >= 400) {
@@ -772,6 +771,80 @@ class Template {
772771
return acc;
773772
});
774773
}
774+
775+
fetchHttp() {
776+
const promises = [];
777+
const view = {};
778+
Object.entries(this.definitions).forEach(([def, defProp]) => {
779+
if (!defProp.url) {
780+
return;
781+
}
782+
783+
const defaultOpts = {
784+
method: 'GET',
785+
host: null,
786+
port: null,
787+
headers: {
788+
}
789+
};
790+
const urlOpts = (typeof defProp.url === 'string') ? url.parse(defProp.url) : defProp.url;
791+
const opts = Object.assign({}, defaultOpts, urlOpts);
792+
promises.push(Promise.resolve()
793+
.then(() => httpUtils.makeRequest(opts))
794+
.then((res) => {
795+
if (res.statusCode >= 400) {
796+
return Promise.reject(new Error(`error loading ${defProp.url}: ${res.statusCode}`));
797+
}
798+
try {
799+
view[def] = JSON.parse(res.body);
800+
} catch (e) {
801+
view[def] = res.body;
802+
}
803+
if (defProp.pathQuery) {
804+
const results = jsonpath.query(view[def], defProp.pathQuery, 1);
805+
view[def] = results[0];
806+
}
807+
return Promise.resolve();
808+
}));
809+
});
810+
return Promise.all(promises)
811+
.then(() => view);
812+
}
813+
814+
fetchAndRender(parameters) {
815+
return Promise.resolve()
816+
.then(() => this.fetchHttp())
817+
.then(httpView => Object.assign({}, parameters, httpView))
818+
.then(combParams => this.render(combParams));
819+
}
820+
821+
forwardHttp(parameters) {
822+
if (!this.httpForward) {
823+
return Promise.reject(
824+
new Error('httpForward was not defined for this template')
825+
);
826+
}
827+
828+
const defaultOpts = {
829+
method: 'POST',
830+
host: null,
831+
port: null,
832+
headers: {
833+
'Content-Type': this.contentType
834+
}
835+
};
836+
const urlOpts = (typeof this.httpForward.url === 'string') ? url.parse(this.httpForward.url) : this.httpForward.url;
837+
const opts = Object.assign({}, defaultOpts, urlOpts);
838+
return Promise.resolve()
839+
.then(() => this.fetchAndRender(parameters))
840+
.then(() => httpUtils.makeRequest(opts))
841+
.then((res) => {
842+
if (res.statusCode >= 400) {
843+
return Promise.reject(new Error(`error forwarding to ${this.httpForward.url}: ${res.statusCode}`));
844+
}
845+
return Promise.resolve(res);
846+
});
847+
}
775848
}
776849

777850
module.exports = {

package-lock.json

Lines changed: 36 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"deepmerge": "^4.2.2",
5757
"js-yaml": "^3.14.0",
5858
"json-schema-merge-allof": "^0.7.0",
59+
"jsonpath": "^1.0.2",
5960
"mustache": "^4.0.1",
6061
"uuid": "^7.0.3",
6162
"yargs": "^15.4.1"

0 commit comments

Comments
 (0)