diff --git a/nodes/api/api.html b/nodes/api/api.html index e63db90b59..ccf6d3914d 100644 --- a/nodes/api/api.html +++ b/nodes/api/api.html @@ -38,39 +38,7 @@ $("#node-input-data") .typedInput({ - types: [ - { - value: "json", - label: "JSON", - icon: "red/images/typedInput/json.png", - validate: function(v) { - if (!v) return true; - try { - JSON.parse(v); - return true; - } catch (e) { - return false; - } - }, - expand: function() { - const that = this; - const value = this.value(); - try { - value = JSON.stringify(JSON.parse(value), null, 4); - } catch (err) {} - RED.editor.editJSON({ - value: value, - complete: function(v) { - const value = v; - try { - value = JSON.stringify(JSON.parse(v)); - } catch (err) {} - that.value(value); - } - }); - } - } - ] + types: ["json"] }) .typedInput("width", "68%"); @@ -168,12 +136,39 @@

Configuration

JSON Object to send for WebSocket requests and HTTP posts.
Resultsstring
-
Location to saved the API results.
+
Location to save the API results.
+ + +

Inputs

+
+
payload.protocol[websocket|http] string
+
Overrides or sets the protocol property of the config.
+ +
payload.method[get|post] string
+
Overrides or sets the method property of the config.
-
Templates
-
Templates can be used in path, params and data fields.
+
payload.pathstring
+
Overrides or sets the path property of the config.
+ +
payload.dataJSON | string
+
Overrides or sets the data/params property of the config.
+ +
payload.locationstring
+
Overrides or sets the results property of the config.
+ +
payload.locationType[msg|flow|global] string
+
Overrides or sets the results type property of the config.

Outputs

- Will output the results received from the API call to the location defined in the config. +

Will output the results received from the API call to the location defined in the config.

+ +

Templates

+

Templates can be used in path, params and data fields. When using templates the top level is a property of the message object: msg.payload would be {{payload}}.

+ +

References

+

+ http api
+ websocket api +

diff --git a/nodes/api/api.js b/nodes/api/api.js index 3e3b27e06b..01e170c01d 100644 --- a/nodes/api/api.js +++ b/nodes/api/api.js @@ -1,5 +1,6 @@ const RenderTemplate = require('../../lib/mustache-context'); const BaseNode = require('../../lib/base-node'); +const Joi = require('joi'); module.exports = function(RED) { const nodeOptions = { @@ -12,6 +13,52 @@ module.exports = function(RED) { data: {}, location: {}, locationType: {} + }, + input: { + protocol: { + messageProp: 'payload.protocol', + configProp: 'protocol', + validation: { + haltOnFail: true, + schema: Joi.string().valid('websocket', 'http') + } + }, + method: { + messageProp: 'payload.method', + configProp: 'method', + validation: { + haltOnFail: true, + schema: Joi.string().valid('get', 'post') + } + }, + path: { + messageProp: 'payload.path', + configProp: 'path', + validation: { + haltOnFail: true, + schema: Joi.string() + } + }, + data: { + messageProp: 'payload.data', + configProp: 'data' + }, + location: { + messageProp: 'payload.location', + configProp: 'location', + validation: { + haltOnFail: true, + schema: Joi.string() + } + }, + locationType: { + messageProp: 'payload.locationType', + configProp: 'locationType', + validation: { + haltOnFail: true, + schema: Joi.string().valid('msg', 'flow', 'global') + } + } } }; class ApiNode extends BaseNode { @@ -19,21 +66,24 @@ module.exports = function(RED) { super(nodeDefinition, RED, nodeOptions); } - onInput({ message }) { + onInput({ message, parsedMessage }) { const node = this; const config = node.nodeConfig; const serverName = node.utils.toCamelCase(config.server.name); const data = RenderTemplate( - config.data, + typeof parsedMessage.data.value === 'object' + ? JSON.stringify(parsedMessage.data.value) + : parsedMessage.data.value, message, node.node.context(), serverName ); + const method = parsedMessage.method.value; let apiCall; - if (config.protocol === 'http') { + if (parsedMessage.protocol.value === 'http') { const path = RenderTemplate( - config.path, + parsedMessage.path.value, message, node.node.context(), serverName @@ -45,13 +95,13 @@ module.exports = function(RED) { return; } - if (!['get', 'post'].includes(config.method)) { + if (!['get', 'post'].includes(method)) { node.error('HTTP request requires a valid method'); node.setStatusFailed(); return; } - apiCall = config.server.http[`_${config.method}`].bind( + apiCall = config.server.http[`_${method}`].bind( config.server.http, path, data @@ -83,18 +133,21 @@ module.exports = function(RED) { return apiCall() .then(results => { - node.setStatusSuccess(`${config.protocol} called`); + node.setStatusSuccess( + `${parsedMessage.protocol.value} called` + ); const contextKey = RED.util.parseContextStore( - config.location + parsedMessage.location.value ); contextKey.key = contextKey.key || 'payload'; - const locationType = config.location_type || 'msg'; + const locationType = + parsedMessage.locationType.value || 'msg'; if (locationType === 'flow' || locationType === 'global') { node.node .context() - [locationType].set( + [parsedMessage.locationType.value].set( contextKey.key, results, contextKey.store