@frankvdb/node-red-contrib-amqp
Version:
RabbitMQ nodes for node-red
291 lines (272 loc) • 12.6 kB
HTML
<script type="text/javascript">
RED.nodes.registerType('amqp-out', {
category: 'AMQP',
color: '#98b886',
defaults: {
name: { value: '' },
broker: { value: '', type: 'amqp-broker' },
reconnectOnError: { value: false },
exchangeName: { value: '' },
exchangeType: { value: 'topic' },
exchangeRoutingKey: { value: '' },
exchangeRoutingKeyType: { value: 'str' },
showExchangeConfiguration: { value: false },
autoCreateExchangeBindings: { value: false },
exchangeDurable: { value: true },
amqpProperties: {
value: '{ "headers": {} }',
},
waitForConfirms: { value: false },
rpcTimeoutMilliseconds: { value: 3000 },
outputs: { value: 0 },
},
inputs: 1,
outputs: 0,
align: 'right',
icon: 'rabbitmq.png',
label: function () {
if (this.name) {
return this.name
}
const name = this.exchangeName
const colon = name && this.exchangeRoutingKey ? ': ' : ''
const label = name + colon + this.exchangeRoutingKey
return label || 'amqp-out'
},
oneditprepare: function () {
$("#node-input-exchangeRoutingKey").typedInput({
default: "str",
types: ["str", "msg", "flow", "global", "jsonata"],
typeField: $("#node-input-exchangeRoutingKeyType")
})
$('#node-input-amqpProperties').typedInput({
type: 'json',
types: ['json'],
})
$('#node-input-rpcTimeoutMilliseconds').typedInput({
type: 'num',
types: ['num'],
})
function updateExchangeFields() {
const exchangeType = $('#node-input-exchangeType').val()
const showExchangeConfiguration = $('#node-input-showExchangeConfiguration').is(':checked')
$('.exchange-configuration-section').toggle(showExchangeConfiguration)
// hide/show routing key field
if (!showExchangeConfiguration || ['fanout', 'headers'].includes(exchangeType)) {
$('.routing-key-form-input').hide()
} else {
$('.routing-key-form-input').show()
}
// hide/show headers exchange help text
if (showExchangeConfiguration && ['headers'].includes(exchangeType)) {
$('.headers-form-input').show()
} else {
$('.headers-form-input').hide()
}
}
$('#node-input-exchangeType').change(function (e) {
updateExchangeFields()
})
$('#node-input-showExchangeConfiguration').change(function (e) {
updateExchangeFields()
})
updateExchangeFields()
},
})
function truncate(str, length = 40, ending = '...') {
if (str.length > length) {
return str.substring(0, length - ending.length) + ending
}
return str
}
</script>
<style>
div.wide-label-amqp-out label {
width: 35% ;
}
div.wide-label-amqp-out input.simple-input {
width: 64% ;
}
div.wide-label-amqp-out div.red-ui-typedInput-container {
width: 64%
}
div.wider-label-amqp-out label {
width: 50% ;
}
select.small-amqp-out {
width: 75px ;
}
input.small-amqp-out {
width: 120px ;
}
div.form-tips {
margin: 20px 0;
}
</style>
<script type="text/html" data-template-name="amqp-out">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Leave blank to use exchange name">
</div>
<div class="form-row">
<label for="node-input-broker"><i class="fa fa-globe"></i> Broker</label>
<input type="text" id="node-input-broker" placeholder="AMQP Broker">
</div>
<div class="form-row">
<label> </label>
<input id="node-input-reconnectOnError" style="width:20px; vertical-align:baseline; margin-right:5px;" type="checkbox">
<label for="node-input-reconnectOnError" style="width:auto; margin-top:7px;">reconnectOnError</label>
</div>
<hr>
<div class="form-row">
<label for="node-input-showExchangeConfiguration" style="width:100%; font-weight:700; margin-bottom:0;">
<input id="node-input-showExchangeConfiguration" type="checkbox" style="width:20px; vertical-align:middle; margin-right:8px;">
Exchange Configuration
</label>
</div>
<div class="form-row wide-label-amqp-out exchange-configuration-section">
<label for="node-input-exchangeType"><i class="fa fa-filter"></i> Type</label>
<select id="node-input-exchangeType">
<option value="topic">Topic</option>
<option value="direct">Direct</option>
<option value="fanout">Fanout</option>
<option value="headers">Headers</option>
</select>
</div>
<div class="form-tips headers-form-input exchange-configuration-section">
<i class="fa fa-info-circle"></i>
Add key/value pairs to a `headers` field in the AMQP Properties field below
</div>
<div class="form-row wide-label-amqp-out exchange-configuration-section">
<label for="node-input-exchangeName"><i class="fa fa-tag"></i> Exchange Name</label>
<input type="text" class="simple-input" id="node-input-exchangeName" placeholder="Leave blank for the default exchange">
</div>
<div class="form-row wide-label-amqp-out routing-key-form-input exchange-configuration-section">
<label for="node-input-exchangeRoutingKey"><i class="fa fa-filter"></i> Routing Key</label>
<input type="text" id="node-input-exchangeRoutingKey">
<input type="hidden" id="node-input-exchangeRoutingKeyType" />
</div>
<div class="form-tips routing-key-form-input exchange-configuration-section">
<i class="fa fa-info-circle"></i>
You can specify multiple routing keys separated by commas
</div>
<div class="form-row exchange-configuration-section">
<label> </label>
<input style="width:20px; vertical-align:baseline; margin-right:5px;" type="checkbox" id="node-input-exchangeDurable">
<label style="width:auto; margin-top:7px;" for="node-input-exchangeDurable">Durable</label>
</div>
<div class="form-row exchange-configuration-section">
<label> </label>
<input style="width:20px; vertical-align:baseline; margin-right:5px;" type="checkbox" id="node-input-autoCreateExchangeBindings">
<label style="width:auto; margin-top:7px;" for="node-input-autoCreateExchangeBindings">Auto-create</label>
</div>
<hr>
<h4>Message Info</h4>
<div class="form-row wide-label-amqp-out">
<label for="node-input-amqpProperties"><i class="fa fa-filter"></i> AMQP Properties</label>
<input type="text" id="node-input-amqpProperties">
</div>
<div class="form-tips">
<i class="fa fa-info-circle"></i>
Standard AMQP message properties as specified in <a href="https://www.squaremobius.net/amqp.node/channel_api.html#channel_publish" target="_blank">the amqplib docs</a>.<br />
<br />
Enable "Wait for publisher confirmations" to publish via a confirm channel and only complete the message after the broker acknowledges receipt.
</div>
<div class="form-row">
<label> </label>
<input style="width:20px; vertical-align:baseline; margin-right:5px;" type="checkbox" id="node-input-waitForConfirms">
<label style="width:auto; margin-top:7px;" for="node-input-waitForConfirms">Wait for publisher confirmations</label>
</div>
<span id="rpc-section">
<hr>
<h4>Remote Procedure Call</h4>
<div class="form-row wider-label-amqp-out">
<label for="node-input-outputs"><i class="fa fa-globe"></i> Request RPC response</label>
<select id="node-input-outputs" class="small-amqp-out">
<option value="0">No</option>
<option value="1">Yes</option>
</select>
</div>
<div class="form-row wider-label-amqp-out">
<label for="node-input-rpcTimeoutMilliseconds"><i class="fa fa-clock-o"></i> RPC Timeout (ms)</label>
<input type="text" class="small-amqp-out" id="node-input-rpcTimeoutMilliseconds">
</div>
<div class="form-tips">
<i class="fa fa-info-circle"></i>
If set to yes, the amqp properties <em>correlationId</em> and <em>replyTo</em> will be auto-generated and sent along with the published message. The message consumer will need to send a response using those fields for this node to then consume and send to output. See the <a href="https://www.rabbitmq.com/tutorials/tutorial-six-javascript.html" target="_blank">RabbitMQ RPC Tutorial</a> for more info. If the consumer for whatever reason does not send a response the request will timeout (configurable here with a default of 3000ms) and the rpc consumer will be cancelled.
<br />
<br />
Note: You <em>can</em> override the <em>correlationId</em> and <em>replyTo</em> AMQP properties by specifying them above or sending them via the node input but it is not recommended except for special use cases.
</div>
</span>
</script>
<script type="text/html" data-help-name="amqp-out">
<p>Connects and sends messages to an AMQP broker.</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt>payload
<span class="property-type">json | object | primitive</span>
</dt>
<dd>the payload of the message to send to the AMQP broker. </dd>
<dt>routingKey
<span class="property-type">string</span>
</dt>
<dd>
If the node's routing key field type is specified as a string, the value of this field will override the node's configured routing key(s). If the node's routing key field type is not specified as a string, this value will have no effect and the value of the typedinput will be used as the routing key.
</dd>
<dt>vhost
<span class="property-type">string</span>
</dt>
<dd>
Optional virtual host override. When provided, the node reconnects using this vhost before publishing.
</dd>
<dt>properties
<span class="property-type">object</span>
</dt>
<dd>
Standard AMQP message properties as specified in <a href="https://www.squaremobius.net/amqp.node/channel_api.html#channel_publish" target="_blank">the amqplib docs</a>. This will shallow merge with whatever is specified in the properties field in the node's configuration.
<br />
<ul>
<li><code>contentType</code>: any | undefined</li>
<li><code>contentEncoding</code>: any | undefined</li>
<li><code>headers</code>: Object | undefined</li>
<li><code>deliveryMode</code>: any | undefined</li>
<li><code>priority</code>: any | undefined</li>
<li><code>correlationId</code>: any | undefined</li>
<li><code>replyTo</code>: any | undefined</li>
<li><code>expiration</code>: any | undefined</li>
<li><code>messageId</code>: any | undefined</li>
<li><code>timestamp</code>: any | undefined</li>
<li><code>type</code>: any | undefined</li>
<li><code>userId</code>: any | undefined</li>
<li><code>appId</code>: any | undefined</li>
<li><code>clusterId</code>: any | undefined</li>
</ul>
</dd>
</dl>
<h3>Behavior Notes</h3>
<ul>
<li><code>msg.properties</code> is shallow-merged over configured AMQP properties.</li>
<li><code>msg.routingKey</code> only overrides when routing key type is <code>str</code>.</li>
<li>When <code>msg.vhost</code> is provided, the node reconnects with that vhost before publish.</li>
</ul>
<h3>Publisher confirmations</h3>
<p>
Enabling the <em>Wait for publisher confirmations</em> option configures the node to publish on a confirm channel and to
wait for acknowledgements from the broker before completing the message. This helps ensure that published messages have been
persisted or routed by the broker before downstream nodes continue processing.
</p>
<h3>Payload encoding</h3>
<p>Payloads are encoded before publish using the following rules:</p>
<ul>
<li><code>Buffer</code> and <code>Uint8Array</code> values are sent as raw bytes</li>
<li><code>string</code> values are sent as-is</li>
<li><code>undefined</code> is sent as an empty payload</li>
<li>All other values (including <code>null</code>, objects, arrays, numbers, and booleans) are JSON-serialized</li>
</ul>
<h3>References</h3>
<ul>
<li>This node relies on the <a href="http://www.squaremobius.net/amqp.node/" target="_blank">amqplib</a> library.</li>
<li>Project repository: <a href="https://github.com/frankvdb7/node-red-contrib-amqp" target="_blank">https://github.com/frankvdb7/node-red-contrib-amqp</a></li>
</ul>
</script>