diff --git a/packages/nodes-base/nodes/HttpRequest.node.ts b/packages/nodes-base/nodes/HttpRequest.node.ts index 32da2e4019..ccec53a90b 100644 --- a/packages/nodes-base/nodes/HttpRequest.node.ts +++ b/packages/nodes-base/nodes/HttpRequest.node.ts @@ -1,4 +1,7 @@ -import { IExecuteFunctions } from 'n8n-core'; +import { + BINARY_ENCODING, + IExecuteFunctions, +} from 'n8n-core'; import { IDataObject, INodeExecutionData, @@ -306,67 +309,65 @@ export class HttpRequest implements INodeType { }, - // Header Parameters + // Body Parameter { - displayName: 'Headers', - name: 'headerParametersJson', - type: 'json', + displayName: 'Send Binary Data', + name: 'sendBinaryData', + type: 'boolean', displayOptions: { + show: { + // TODO: Make it possible to use dot-notation + // 'options.bodyContentType': [ + // 'raw', + // ], + jsonParameters: [ + true, + ], + requestMethod: [ + 'PATCH', + 'POST', + 'PUT', + ], + }, + }, + default: false, + description: 'If binary data should be send as body.', + }, + { + displayName: 'Binary Property', + name: 'binaryPropertyName', + type: 'string', + required: true, + default: 'data', + displayOptions: { + hide: { + sendBinaryData: [ + false, + ], + }, show: { jsonParameters: [ true, ], - }, - }, - default: '', - description: 'Header parameters as JSON (flat object).', - }, - { - displayName: 'Headers', - name: 'headerParametersUi', - placeholder: 'Add Header', - type: 'fixedCollection', - typeOptions: { - multipleValues: true, - }, - displayOptions: { - show: { - jsonParameters: [ - false, + requestMethod: [ + 'PATCH', + 'POST', + 'PUT', ], }, }, - description: 'The headers to send.', - default: {}, - options: [ - { - name: 'parameter', - displayName: 'Header', - values: [ - { - displayName: 'Name', - name: 'name', - type: 'string', - default: '', - description: 'Name of the header.', - }, - { - displayName: 'Value', - name: 'value', - type: 'string', - default: '', - description: 'Value to set for the header.', - }, - ] - }, - ], + description: 'Name of the binary property which contains
the data for the file to be uploaded.', }, - // Body Parameter { displayName: 'Body Parameters', name: 'bodyParametersJson', type: 'json', displayOptions: { + hide: { + sendBinaryData: [ + true, + ], + }, show: { jsonParameters: [ true, @@ -427,6 +428,62 @@ export class HttpRequest implements INodeType { ], }, + // Header Parameters + { + displayName: 'Headers', + name: 'headerParametersJson', + type: 'json', + displayOptions: { + show: { + jsonParameters: [ + true, + ], + }, + }, + default: '', + description: 'Header parameters as JSON or RAW.', + }, + { + displayName: 'Headers', + name: 'headerParametersUi', + placeholder: 'Add Header', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + displayOptions: { + show: { + jsonParameters: [ + false, + ], + }, + }, + description: 'The headers to send.', + default: {}, + options: [ + { + name: 'parameter', + displayName: 'Header', + values: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Name of the header.', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + description: 'Value to set for the header.', + }, + ] + }, + ], + }, + // Query Parameter { displayName: 'Query Parameters', @@ -573,6 +630,33 @@ export class HttpRequest implements INodeType { // Paramter is empty so skip it continue; } + + if (optionData.name === 'body' && parametersAreJson === true) { + const sendBinaryData = this.getNodeParameter('sendBinaryData', itemIndex, false) as boolean; + if (sendBinaryData === true) { + + if (options.bodyContentType !== 'raw') { + // As n8n-workflow.NodeHelpers.getParamterResolveOrder can not be changed + // easily to handle parameters in dot.notation simply error for now. + throw new Error('Sending binary data is only supported when option "Body Content Type" is set to "RAW/CUSTOM"!'); + } + + const item = items[itemIndex]; + + if (item.binary === undefined) { + throw new Error('No binary data exists on item!'); + } + + const binaryPropertyName = this.getNodeParameter('binaryPropertyName', itemIndex) as string; + if (item.binary[binaryPropertyName] === undefined) { + throw new Error(`No binary data property "${binaryPropertyName}" does not exists on item!`); + } + + requestOptions.body = Buffer.from(item.binary[binaryPropertyName].data, BINARY_ENCODING); + continue; + } + } + // @ts-ignore requestOptions[optionData.name] = tempValue; diff --git a/packages/workflow/src/NodeHelpers.ts b/packages/workflow/src/NodeHelpers.ts index a1b631a19f..e3c6a79b8a 100644 --- a/packages/workflow/src/NodeHelpers.ts +++ b/packages/workflow/src/NodeHelpers.ts @@ -282,10 +282,10 @@ export function displayParameter(nodeValues: INodeParameters, parameter: INodePr for (const propertyName of Object.keys(parameter.displayOptions.show)) { if (propertyName.charAt(0) === '/') { // Get the value from the root of the node - value = nodeValuesRoot[propertyName.slice(1)]; + value = get(nodeValuesRoot, propertyName.slice(1)); } else { // Get the value from current level - value = nodeValues[propertyName]; + value = get(nodeValues, propertyName); } if (value === undefined || !parameter.displayOptions.show[propertyName].includes(value as string)) { @@ -299,10 +299,10 @@ export function displayParameter(nodeValues: INodeParameters, parameter: INodePr for (const propertyName of Object.keys(parameter.displayOptions.hide)) { if (propertyName.charAt(0) === '/') { // Get the value from the root of the node - value = nodeValuesRoot[propertyName.slice(1)]; + value = get(nodeValuesRoot, propertyName.slice(1)); } else { // Get the value from current level - value = nodeValues[propertyName]; + value = get(nodeValues, propertyName); } if (value !== undefined && parameter.displayOptions.hide[propertyName].includes(value as string)) { return false; @@ -475,7 +475,7 @@ export function getParamterResolveOrder(nodePropertiesArray: INodeProperties[], } if (itterations > lastIndexReduction + nodePropertiesArray.length) { - throw new Error('Could not resolve parameter depenencies!'); + throw new Error('Could not resolve parameter depenencies. Max itterations got reached!'); } lastIndexLength = indexToResolve.length; }