mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #3488 from Steve-Mcl/httpreq-headers-ui
Add UI for Http Request node headers
This commit is contained in:
commit
a7932da207
@ -100,14 +100,107 @@
|
||||
<option value="obj" data-i18n="httpin.json"></option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-row form-tips" id="tip-json" hidden><span data-i18n="httpin.tip.req"></span></div>
|
||||
|
||||
<div class="form-row" style="margin-bottom:0;">
|
||||
<label><i class="fa fa-list"></i> <span data-i18n="httpin.label.headers"></span></label>
|
||||
</div>
|
||||
<div class="form-row node-input-headers-container-row">
|
||||
<ol id="node-input-headers-container"></ol>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||
</div>
|
||||
<div class="form-tips" id="tip-json" hidden><span data-i18n="httpin.tip.req"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
const headerTypes = [
|
||||
{ value: "Accept", label: "Accept", hasValue: false },
|
||||
{ value: "Accept-Encoding", label: "Accept-Encoding", hasValue: false },
|
||||
{ value: "Accept-Language", label: "Accept-Language", hasValue: false },
|
||||
{ value: "Authorization", label: "Authorization", hasValue: false },
|
||||
{ value: "Content-Type", label: "Content-Type", hasValue: false },
|
||||
{ value: "Cache-Control", label: "Cache-Control", hasValue: false },
|
||||
{ value: "User-Agent", label: "User-Agent", hasValue: false },
|
||||
{ value: "Location", label: "Location", hasValue: false },
|
||||
{ value: "other", label: "other", hasValue: true, icon: "red/images/typedInput/az.png" },
|
||||
{ value: "msg", label: "msg.", hasValue: true },
|
||||
]
|
||||
const headerOptions = {};
|
||||
const defaultOptions = [
|
||||
{ value: "other", label: "other", hasValue: true, icon: "red/images/typedInput/az.png" },
|
||||
{ value: "msg", label: "msg.", hasValue: true },
|
||||
];
|
||||
headerOptions["accept"] = [
|
||||
{ value: "text/plain", label: "text/plain", hasValue: false },
|
||||
{ value: "text/html", label: "text/html", hasValue: false },
|
||||
{ value: "application/json", label: "application/json", hasValue: false },
|
||||
{ value: "application/xml", label: "application/xml", hasValue: false },
|
||||
...defaultOptions,
|
||||
];
|
||||
headerOptions["accept-encoding"] = [
|
||||
{ value: "gzip", label: "gzip", hasValue: false },
|
||||
{ value: "deflate", label: "deflate", hasValue: false },
|
||||
{ value: "compress", label: "compress", hasValue: false },
|
||||
{ value: "br", label: "br", hasValue: false },
|
||||
{ value: "gzip, deflate", label: "gzip, deflate", hasValue: false },
|
||||
{ value: "gzip, deflate, br", label: "gzip, deflate, br", hasValue: false },
|
||||
...defaultOptions,
|
||||
];
|
||||
headerOptions["accept-language"] = [
|
||||
{ value: "*", label: "*", hasValue: false },
|
||||
{ value: "en-GB, en-US, en;q=0.9", label: "en-GB, en-US, en;q=0.9", hasValue: false },
|
||||
{ value: "de-AT, de-DE;q=0.9, en;q=0.5", label: "de-AT, de-DE;q=0.9, en;q=0.5", hasValue: false },
|
||||
{ value: "es-mx,es,en;q=0.5", label: "es-mx,es,en;q=0.5", hasValue: false },
|
||||
{ value: "fr-CH, fr;q=0.9, en;q=0.8", label: "fr-CH, fr;q=0.9, en;q=0.8", hasValue: false },
|
||||
{ value: "zh-CN, zh-TW; q = 0.9, zh-HK; q = 0.8, zh; q = 0.7, en; q = 0.6", label: "zh-CN, zh-TW; q = 0.9, zh-HK; q = 0.8, zh; q = 0.7, en; q = 0.6", hasValue: false },
|
||||
{ value: "ja-JP, jp", label: "ja-JP, jp", hasValue: false },
|
||||
...defaultOptions,
|
||||
];
|
||||
headerOptions["content-type"] = [
|
||||
{ value: "text/css", label: "text/css", hasValue: false },
|
||||
{ value: "text/plain", label: "text/plain", hasValue: false },
|
||||
{ value: "text/html", label: "text/html", hasValue: false },
|
||||
{ value: "application/json", label: "application/json", hasValue: false },
|
||||
{ value: "application/octet-stream", label: "application/octet-stream", hasValue: false },
|
||||
{ value: "application/pdf", label: "application/pdf", hasValue: false },
|
||||
{ value: "application/xml", label: "application/xml", hasValue: false },
|
||||
{ value: "application/zip", label: "application/zip", hasValue: false },
|
||||
{ value: "multipart/form-data", label: "multipart/form-data", hasValue: false },
|
||||
{ value: "audio/aac", label: "audio/aac", hasValue: false },
|
||||
{ value: "audio/ac3", label: "audio/ac3", hasValue: false },
|
||||
{ value: "audio/basic", label: "audio/basic", hasValue: false },
|
||||
{ value: "audio/mp4", label: "audio/mp4", hasValue: false },
|
||||
{ value: "audio/ogg", label: "audio/ogg", hasValue: false },
|
||||
{ value: "image/bmp", label: "image/bmp", hasValue: false },
|
||||
{ value: "image/gif", label: "image/gif", hasValue: false },
|
||||
{ value: "image/jpeg", label: "image/jpeg", hasValue: false },
|
||||
{ value: "image/png", label: "image/png", hasValue: false },
|
||||
{ value: "image/tiff", label: "image/tiff", hasValue: false },
|
||||
...defaultOptions,
|
||||
];
|
||||
headerOptions["cache-control"] = [
|
||||
{ value: "max-age=0", label: "max-age=0", hasValue: false },
|
||||
{ value: "max-age=86400", label: "max-age=86400", hasValue: false },
|
||||
{ value: "no-cache", label: "no-cache", hasValue: false },
|
||||
...defaultOptions,
|
||||
];
|
||||
|
||||
headerOptions["user-agent"] = [
|
||||
{ value: "Mozilla/5.0", label: "Mozilla/5.0", hasValue: false },
|
||||
...defaultOptions,
|
||||
];
|
||||
|
||||
function getHeaderOptions(headerName) {
|
||||
const lc = (headerName || "").toLowerCase();
|
||||
let opts = headerOptions[lc];
|
||||
return opts || defaultOptions;
|
||||
}
|
||||
|
||||
RED.nodes.registerType('http request',{
|
||||
category: 'network',
|
||||
color:"rgb(231, 231, 174)",
|
||||
@ -121,7 +214,8 @@
|
||||
persist: {value:false},
|
||||
proxy: {type:"http proxy",required: false},
|
||||
authType: {value: ""},
|
||||
senderr: {value: false}
|
||||
senderr: {value: false},
|
||||
headers: { value: [] }
|
||||
},
|
||||
credentials: {
|
||||
user: {type:"text"},
|
||||
@ -144,6 +238,7 @@
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
const node = this;
|
||||
$("#node-input-useAuth").on("change", function() {
|
||||
if ($(this).is(":checked")) {
|
||||
$(".node-input-useAuth-row").show();
|
||||
@ -157,9 +252,10 @@
|
||||
$('#node-input-user').val('');
|
||||
$('#node-input-password').val('');
|
||||
}
|
||||
RED.tray.resize();
|
||||
});
|
||||
$("#node-input-authType-select").on("change", function() {
|
||||
var val = $(this).val();
|
||||
const val = $(this).val();
|
||||
$("#node-input-authType").val(val);
|
||||
if (val === "basic" || val === "digest") {
|
||||
$(".node-input-basic-row").show();
|
||||
@ -171,6 +267,7 @@
|
||||
$('#node-span-token').show();
|
||||
$('#node-input-user').val('');
|
||||
}
|
||||
RED.tray.resize();
|
||||
});
|
||||
$("#node-input-method").on("change", function() {
|
||||
if ($(this).val() == "GET") {
|
||||
@ -178,17 +275,18 @@
|
||||
} else {
|
||||
$(".node-input-paytoqs-row").hide();
|
||||
}
|
||||
RED.tray.resize();
|
||||
});
|
||||
if (this.paytoqs === true || this.paytoqs == "query") {
|
||||
if (node.paytoqs === true || node.paytoqs == "query") {
|
||||
$("#node-input-paytoqs").val("query");
|
||||
} else if (this.paytoqs === "body") {
|
||||
} else if (node.paytoqs === "body") {
|
||||
$("#node-input-paytoqs").val("body");
|
||||
} else {
|
||||
$("#node-input-paytoqs").val("ignore");
|
||||
}
|
||||
if (this.authType) {
|
||||
if (node.authType) {
|
||||
$('#node-input-useAuth').prop('checked', true);
|
||||
$("#node-input-authType-select").val(this.authType);
|
||||
$("#node-input-authType-select").val(node.authType);
|
||||
$("#node-input-authType-select").change();
|
||||
} else {
|
||||
$('#node-input-useAuth').prop('checked', false);
|
||||
@ -201,8 +299,9 @@
|
||||
} else {
|
||||
$("#node-row-tls").hide();
|
||||
}
|
||||
RED.tray.resize();
|
||||
}
|
||||
if (this.tls) {
|
||||
if (node.tls) {
|
||||
$('#node-input-usetls').prop('checked', true);
|
||||
} else {
|
||||
$('#node-input-usetls').prop('checked', false);
|
||||
@ -218,8 +317,9 @@
|
||||
} else {
|
||||
$("#node-input-useProxy-row").hide();
|
||||
}
|
||||
RED.tray.resize();
|
||||
}
|
||||
if (this.proxy) {
|
||||
if (node.proxy) {
|
||||
$("#node-input-useProxy").prop("checked", true);
|
||||
} else {
|
||||
$("#node-input-useProxy").prop("checked", false);
|
||||
@ -235,7 +335,70 @@
|
||||
} else {
|
||||
$("#tip-json").hide();
|
||||
}
|
||||
RED.tray.resize();
|
||||
});
|
||||
const hasMatch = function (arr, value) {
|
||||
return arr.some(function (ht) {
|
||||
return ht.value === value
|
||||
});
|
||||
}
|
||||
const headerList = $("#node-input-headers-container").css('min-height', '150px').css('min-width', '450px').editableList({
|
||||
addItem: function (container, i, header) {
|
||||
const row = $('<div/>').css({
|
||||
overflow: 'hidden',
|
||||
whiteSpace: 'nowrap',
|
||||
display: 'flex'
|
||||
}).appendTo(container);
|
||||
const propertNameCell = $('<div/>').css({ 'flex-grow': 1 }).appendTo(row);
|
||||
const propertyName = $('<input/>', { class: "node-input-header-name", type: "text", style: "width: 100%" })
|
||||
.appendTo(propertNameCell)
|
||||
.typedInput({ types: headerTypes });
|
||||
|
||||
const propertyValueCell = $('<div/>').css({ 'flex-grow': 1, 'margin-left': '10px' }).appendTo(row);
|
||||
const propertyValue = $('<input/>', { class: "node-input-header-value", type: "text", style: "width: 100%" })
|
||||
.appendTo(propertyValueCell)
|
||||
.typedInput({
|
||||
types: getHeaderOptions(header.keyType)
|
||||
});
|
||||
|
||||
const setup = function(_header) {
|
||||
const headerTypeIsAPreset = function(h) {return hasMatch(headerTypes, h) };
|
||||
const headerValueIsAPreset = function(h, v) {return hasMatch(getHeaderOptions(h), v) };
|
||||
const {keyType, keyValue, valueType, valueValue} = header;
|
||||
if(keyType == "msg" || keyType == "other") {
|
||||
propertyName.typedInput('type', keyType);
|
||||
propertyName.typedInput('value', keyValue);
|
||||
} else if (headerTypeIsAPreset(keyType)) {
|
||||
propertyName.typedInput('type', keyType);
|
||||
} else {
|
||||
propertyName.typedInput('type', "other");
|
||||
propertyName.typedInput('value', keyValue);
|
||||
}
|
||||
if(valueType == "msg" || valueType == "other") {
|
||||
propertyValue.typedInput('type', valueType);
|
||||
propertyValue.typedInput('value', valueValue);
|
||||
} else if (headerValueIsAPreset(propertyName.typedInput('type'), valueType)) {
|
||||
propertyValue.typedInput('type', valueType);
|
||||
} else {
|
||||
propertyValue.typedInput('type', "other");
|
||||
propertyValue.typedInput('value', valueValue);
|
||||
}
|
||||
}
|
||||
setup(header);
|
||||
|
||||
propertyName.on('change', function (event) {
|
||||
propertyValue.typedInput('types', getHeaderOptions(propertyName.typedInput('type')));
|
||||
});
|
||||
|
||||
},
|
||||
removable: true
|
||||
});
|
||||
if (node.headers) {
|
||||
for (let index = 0; index < node.headers.length; index++) {
|
||||
const element = node.headers[index];
|
||||
headerList.editableList('addItem', node.headers[index]);
|
||||
}
|
||||
}
|
||||
},
|
||||
oneditsave: function() {
|
||||
if (!$("#node-input-usetls").is(':checked')) {
|
||||
@ -244,6 +407,36 @@
|
||||
if (!$("#node-input-useProxy").is(":checked")) {
|
||||
$("#node-input-proxy").val("_ADD_");
|
||||
}
|
||||
const headers = $("#node-input-headers-container").editableList('items');
|
||||
const node = this;
|
||||
node.headers = [];
|
||||
headers.each(function(i) {
|
||||
const header = $(this);
|
||||
const keyType = header.find(".node-input-header-name").typedInput('type');
|
||||
const keyValue = header.find(".node-input-header-name").typedInput('value');
|
||||
const valueType = header.find(".node-input-header-value").typedInput('type');
|
||||
const valueValue = header.find(".node-input-header-value").typedInput('value');
|
||||
if (keyType !== '' || keyType === 'other' || keyType === 'msg') {
|
||||
node.headers.push({
|
||||
keyType, keyValue, valueType, valueValue
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
oneditresize: function(size) {
|
||||
const dlg = $("#dialog-form");
|
||||
const expandRow = dlg.find('.node-input-headers-container-row');
|
||||
let height = dlg.height() - 5;
|
||||
if(expandRow && expandRow.length){
|
||||
const siblingRows = dlg.find('> .form-row:not(.node-input-headers-container-row)');
|
||||
for (let i = 0; i < siblingRows.size(); i++) {
|
||||
const cr = $(siblingRows[i]);
|
||||
if(cr.is(":visible"))
|
||||
height -= cr.outerHeight(true);
|
||||
}
|
||||
$("#node-input-headers-container").editableList('height',height);
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
@ -73,7 +73,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
||||
var paytobody = false;
|
||||
var redirectList = [];
|
||||
var sendErrorsToCatch = n.senderr;
|
||||
|
||||
node.headers = n.headers || [];
|
||||
var nodeHTTPPersistent = n["persist"];
|
||||
if (n.tls) {
|
||||
var tlsNode = RED.nodes.getNode(n.tls);
|
||||
@ -105,6 +105,37 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
||||
timingLog = RED.settings.httpRequestTimingLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Case insensitive header value update util function
|
||||
* @param {object} headersObject The opt.headers object to update
|
||||
* @param {string} name The header name
|
||||
* @param {string} value The header value to set (if blank, header is removed)
|
||||
*/
|
||||
const updateHeader = function(headersObject, name, value ) {
|
||||
const hn = name.toLowerCase();
|
||||
const keys = Object.keys(headersObject);
|
||||
const matchingKeys = keys.filter(e => e.toLowerCase() == hn)
|
||||
const updateKey = (k,v) => {
|
||||
delete headersObject[k]; //delete incase of case change
|
||||
if(v) { headersObject[name] = v } //re-add with requested name & value
|
||||
}
|
||||
if(matchingKeys.length == 0) {
|
||||
updateKey(name, value)
|
||||
} else {
|
||||
matchingKeys.forEach(k => {
|
||||
updateKey(k, value);
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {Object} headersObject
|
||||
* @param {string} name
|
||||
* @return {any} value
|
||||
*/
|
||||
const getHeaderValue = (headersObject, name) => {
|
||||
const asLowercase = name.toLowercase();
|
||||
return headersObject[Object.keys(headersObject).find(k => k.toLowerCase() === asLowercase)];
|
||||
}
|
||||
this.on("input",function(msg,nodeSend,nodeDone) {
|
||||
checkNodeAgentPatch();
|
||||
//reset redirectList on each request
|
||||
@ -183,7 +214,6 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
||||
// TODO: add UI option to auto decompress. Setting to false for 1.x compatibility
|
||||
opts.decompress = false;
|
||||
opts.method = method;
|
||||
opts.headers = {};
|
||||
opts.retry = 0;
|
||||
opts.responseType = 'buffer';
|
||||
opts.maxRedirects = 21;
|
||||
@ -229,34 +259,85 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
||||
]
|
||||
}
|
||||
|
||||
var ctSet = "Content-Type"; // set default camel case
|
||||
var clSet = "Content-Length";
|
||||
let ctSet = "Content-Type"; // set default camel case
|
||||
let clSet = "Content-Length";
|
||||
const normaliseKnownHeader = function (name) {
|
||||
const _name = name.toLowerCase();
|
||||
// only normalise the known headers used later in this
|
||||
// function. Otherwise leave them alone.
|
||||
switch (_name) {
|
||||
case "content-type":
|
||||
ctSet = name;
|
||||
name = _name;
|
||||
break;
|
||||
case "content-length":
|
||||
clSet = name;
|
||||
name = _name;
|
||||
break;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
opts.headers = {};
|
||||
//add msg.headers
|
||||
//NOTE: ui headers will take precidence over msg.headers
|
||||
if (msg.headers) {
|
||||
if (msg.headers.hasOwnProperty('x-node-red-request-node')) {
|
||||
var headerHash = msg.headers['x-node-red-request-node'];
|
||||
const headerHash = msg.headers['x-node-red-request-node'];
|
||||
delete msg.headers['x-node-red-request-node'];
|
||||
var hash = hashSum(msg.headers);
|
||||
const hash = hashSum(msg.headers);
|
||||
if (hash === headerHash) {
|
||||
delete msg.headers;
|
||||
}
|
||||
}
|
||||
if (msg.headers) {
|
||||
for (var v in msg.headers) {
|
||||
if (msg.headers.hasOwnProperty(v)) {
|
||||
var name = v.toLowerCase();
|
||||
if (name !== "content-type" && name !== "content-length") {
|
||||
// only normalise the known headers used later in this
|
||||
// function. Otherwise leave them alone.
|
||||
name = v;
|
||||
}
|
||||
else if (name === 'content-type') { ctSet = v; }
|
||||
else { clSet = v; }
|
||||
opts.headers[name] = msg.headers[v];
|
||||
}
|
||||
for (let hn in msg.headers) {
|
||||
const name = normaliseKnownHeader(hn);
|
||||
updateHeader(opts.headers, name, msg.headers[hn]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//add/remove/update headers from UI.
|
||||
if (node.headers.length) {
|
||||
for (let index = 0; index < node.headers.length; index++) {
|
||||
const header = node.headers[index];
|
||||
let headerName, headerValue;
|
||||
if (header.keyType === "other") {
|
||||
headerName = header.keyValue
|
||||
} else if (header.keyType === "msg") {
|
||||
RED.util.evaluateNodeProperty(header.keyValue, header.keyType, node, msg, (err, value) => {
|
||||
if (err) {
|
||||
//ignore header
|
||||
} else {
|
||||
headerName = value;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
headerName = header.keyType
|
||||
}
|
||||
if (!headerName) {
|
||||
continue; //skip if header name is empyy
|
||||
}
|
||||
if (header.valueType === "other") {
|
||||
headerValue = header.valueValue
|
||||
} else if (header.valueType === "msg") {
|
||||
RED.util.evaluateNodeProperty(header.valueValue, header.valueType, node, msg, (err, value) => {
|
||||
if (err) {
|
||||
//ignore header
|
||||
} else {
|
||||
headerValue = value;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
headerValue = header.valueType
|
||||
}
|
||||
const hn = normaliseKnownHeader(headerName);
|
||||
updateHeader(opts.headers, hn, headerValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (msg.hasOwnProperty('followRedirects')) {
|
||||
opts.followRedirect = !!msg.followRedirects;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
<dd>If not configured in the node, this optional property sets the HTTP method of the request.
|
||||
Must be one of <code>GET</code>, <code>PUT</code>, <code>POST</code>, <code>PATCH</code> or <code>DELETE</code>.</dd>
|
||||
<dt class="optional">headers <span class="property-type">object</span></dt>
|
||||
<dd>Sets the HTTP headers of the request.</dd>
|
||||
<dd>Sets the HTTP headers of the request. NOTE: Any headers set in the node configuration will overwrite any matching headers in <code>msg.headers</code> </dd>
|
||||
<dt class="optional">cookies <span class="property-type">object</span></dt>
|
||||
<dd>If set, can be used to send cookies with the request.</dd>
|
||||
<dt class="optional">payload</dt>
|
||||
|
@ -1500,6 +1500,50 @@ describe('HTTP Request Node', function() {
|
||||
n1.receive({payload:{foo:"bar"}, headers: { 'content-type': 'text/plain', "x-node-red-request-node":"INVALID_SUM"}});
|
||||
});
|
||||
});
|
||||
|
||||
it('should use ui headers', function (done) {
|
||||
const flow = [
|
||||
{
|
||||
id: "n1", type: "http request", wires: [["n2"]], method: "GET", ret: "obj", url: getTestURL('/rawHeaders'),
|
||||
"headers": [
|
||||
{ "keyType": "Accept", "keyValue": "", "valueType": "application/json", "valueValue": "" },//set "Accept" to "application/json"
|
||||
{ "keyType": "Content-Type", "keyValue": "", "valueType": "application/json", "valueValue": "" },//overwrite msg.headers['content-type'] with UI header 'Content-Type']
|
||||
{ "keyType": "msg", "keyValue": "dynamicHeaderName", "valueType": "msg", "valueValue": "dynamicHeaderValue" }, //dynamic msg.dynamicHeaderName/msg.dynamicHeaderValue
|
||||
{ "keyType": "other", "keyValue": "static-header-name", "valueType": "other", "valueValue": "static-header-value" }, //static "other" header and value
|
||||
{ "keyType": "Location", "keyValue": "", "valueType": "other", "valueValue": "" }, //delete "Location" header (initially set in msg.headers['location'] by passing empty string for value
|
||||
]
|
||||
},
|
||||
{ id: "n2", type: "helper" }];
|
||||
helper.load(httpRequestNode, flow, function () {
|
||||
const n1 = helper.getNode("n1");
|
||||
const n2 = helper.getNode("n2");
|
||||
n2.on("input", function (msg) {
|
||||
try {
|
||||
msg.should.have.property('statusCode',200);
|
||||
msg.payload.should.have.property('headers');
|
||||
//msg.headers['Accept'] should be set by Flow UI
|
||||
msg.payload.headers.should.have.property('Accept').which.startWith('application/json');
|
||||
//msg.headers['content-type'] should be updated to 'Content-Type' by the value set in the Flow UI
|
||||
msg.payload.headers.should.have.property('Content-Type').which.startWith('application/json');
|
||||
//msg.dynamicHeaderName should be present in headers with the value of msg.dynamicHeaderValue
|
||||
msg.payload.headers.should.have.property('dyn-header-name').which.startWith('dyn-header-value');
|
||||
//static (custom) header set in Flow UI should be present
|
||||
msg.payload.headers.should.have.property('static-header-name').which.startWith('static-header-value');
|
||||
//msg.headers['location'] should be deleted because Flow UI "Location" header has a blank value
|
||||
//ensures headers with matching characters but different case are eliminated
|
||||
msg.payload.headers.should.not.have.property('location');
|
||||
msg.payload.headers.should.not.have.property('Location');
|
||||
done();
|
||||
} catch (err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
// Pass in a headers property with a "content-type" & "location" header
|
||||
// Pass in dynamicHeaderName & dynamicHeaderValue properties to set the Flow UI `msg.xxx` header entries
|
||||
n1.receive({ payload: { foo: "bar" }, dynamicHeaderName: "dyn-header-name", dynamicHeaderValue: "dyn-header-value", headers: { 'content-type': 'text/plain', 'location': 'london' } });
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('protocol', function() {
|
||||
@ -1976,8 +2020,14 @@ describe('HTTP Request Node', function() {
|
||||
|
||||
describe('file-upload', function() {
|
||||
it('should upload a file', function(done) {
|
||||
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'POST',ret:'obj',url:getTestURL('/file-upload')},
|
||||
{id:"n2", type:"helper"}];
|
||||
const flow = [
|
||||
{
|
||||
id: 'n1', type: 'http request', wires: [['n2']], method: 'POST', ret: 'obj', url: getTestURL('/file-upload'), headers: [
|
||||
{ "keyType": "Content-Type", "keyValue": "", "valueType": "multipart/form-data", "valueValue": "" }
|
||||
]
|
||||
},
|
||||
{ id: "n2", type: "helper" }
|
||||
];
|
||||
helper.load(httpRequestNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
@ -1995,9 +2045,6 @@ describe('HTTP Request Node', function() {
|
||||
}
|
||||
});
|
||||
n1.receive({
|
||||
headers: {
|
||||
'content-type':'multipart/form-data'
|
||||
},
|
||||
payload: {
|
||||
file: {
|
||||
value: Buffer.from("Hello World"),
|
||||
|
Loading…
Reference in New Issue
Block a user