1 | <script type="text/javascript">
|
2 | RED.nodes.registerType("axios-endpoint", {
|
3 | category: "config",
|
4 | defaults: {
|
5 | name: { value: "" },
|
6 | baseURL: { value: "", required: true },
|
7 | caCertPath: { value: "" },
|
8 | rejectUnauthorized: { value: true },
|
9 | proxyEnabled: { value: false },
|
10 | proxyProtocol: { value: "https" },
|
11 | proxyHost: { value: "" },
|
12 | proxyPort: { value: "" },
|
13 | },
|
14 | credentials: {
|
15 | username: { value: "", type: "text" },
|
16 | password: { value: "", type: "password" },
|
17 | bearerToken: { value: "", type: "password" },
|
18 | proxyUsername: { value: "", type: "text" },
|
19 | proxyPassword: { value: "", type: "password" },
|
20 | },
|
21 | color: "#cbbbf7",
|
22 | icon: "icons/node-red/white-globe.svg",
|
23 | label: function () {
|
24 | return this.name || this.baseURL;
|
25 | },
|
26 | oneditprepare: function () {
|
27 |
|
28 | this.tabs = RED.tabs.create({
|
29 | id: "tabs",
|
30 | onchange: function (tab) {
|
31 | $("#tabs-content").children().hide();
|
32 | $("#" + tab.id).show();
|
33 | },
|
34 | });
|
35 |
|
36 | this.tabs.addTab({
|
37 | id: "tab-endpoint",
|
38 | label: "Endpoint",
|
39 | });
|
40 |
|
41 | this.tabs.addTab({
|
42 | id: "tab-tls",
|
43 | label: "TLS",
|
44 | });
|
45 |
|
46 | this.tabs.addTab({
|
47 | id: "tab-proxy",
|
48 | label: "Proxy",
|
49 | });
|
50 |
|
51 | this.tabs.activateTab("tab-endpoint");
|
52 | },
|
53 | });
|
54 | </script>
|
55 |
|
56 | <style>
|
57 | .node-input-params-container-row .red-ui-editableList-container,
|
58 | .node-input-headers-container-row .red-ui-editableList-container {
|
59 | height: auto !important;
|
60 | }
|
61 | </style>
|
62 |
|
63 | <script type="text/html" data-template-name="axios-endpoint">
|
64 | <div class="form-row">
|
65 | <label for="node-config-input-name"
|
66 | ><i class="fa fa-tag"></i> Name</label
|
67 | >
|
68 | <input type="text" id="node-config-input-name" />
|
69 | </div>
|
70 |
|
71 | <div class="form-row tabs-row">
|
72 | <ul style="min-width: 600px; margin-bottom: 20px;" id="tabs"></ul>
|
73 | </div>
|
74 |
|
75 | <div id="tabs-content">
|
76 | <div id="tab-endpoint" style="display:none">
|
77 | <div class="form-row">
|
78 | <label for="node-config-input-baseURL"
|
79 | ><i class="fa fa-star"></i> Base URL</label
|
80 | >
|
81 | <input
|
82 | type="text"
|
83 | id="node-config-input-baseURL"
|
84 | placeholder="https://some-domain.com/api"
|
85 | />
|
86 | </div>
|
87 | <h4>Basic Authentication</h4>
|
88 | <div class="form-row">
|
89 | <label for="node-config-input-username"
|
90 | ><i class="fa fa-user"></i> Username</label
|
91 | >
|
92 | <input type="text" id="node-config-input-username" />
|
93 | </div>
|
94 | <div class="form-row">
|
95 | <label for="node-config-input-password"
|
96 | ><i class="fa fa-lock"></i> Password</label
|
97 | >
|
98 | <input type="password" id="node-config-input-password" />
|
99 | </div>
|
100 | <h4>Bearer Token</h4>
|
101 | <div class="form-row">
|
102 | <label for="node-config-input-bearerToken"
|
103 | ><i class="fa fa-key"></i> Token</label
|
104 | >
|
105 | <input type="password" id="node-config-input-bearerToken" />
|
106 | </div>
|
107 | </div>
|
108 |
|
109 | <div id="tab-tls" style="display:none">
|
110 | <div class="form-row">
|
111 | <label for="node-config-input-caCertPath" style="width: auto;"
|
112 | ><i class="fa fa-user"></i> CA Certificate</label
|
113 | >
|
114 | <input
|
115 | type="text"
|
116 | id="node-config-input-caCertPath"
|
117 | placeholder="path to ca certificate (PEM)"
|
118 | />
|
119 | </div>
|
120 | <div class="form-row">
|
121 | <input
|
122 | type="checkbox"
|
123 | id="node-config-input-rejectUnauthorized"
|
124 | style="display: inline-block; width: auto; vertical-align: top;"
|
125 | />
|
126 | <label
|
127 | for="node-config-input-rejectUnauthorized"
|
128 | style="width: auto;"
|
129 | >Verify server certificate</label
|
130 | >
|
131 | </div>
|
132 | </div>
|
133 |
|
134 | <div id="tab-proxy" style="display:none">
|
135 | <div class="form-row">
|
136 | <input
|
137 | type="checkbox"
|
138 | id="node-config-input-proxyEnabled"
|
139 | style="display: inline-block; width: auto; vertical-align: top;"
|
140 | />
|
141 | <label for="node-config-input-proxyEnabled" style="width: auto;"
|
142 | >Proxy Enabled</label
|
143 | >
|
144 | </div>
|
145 | <div class="form-row">
|
146 | <label for="node-config-input-proxyHost">Hostname</label>
|
147 | <input type="text" id="node-config-input-proxyHost" />
|
148 | </div>
|
149 | <div class="form-row">
|
150 | <label for="node-config-input-proxyPort">Port</label>
|
151 | <input type="number" id="node-config-input-proxyPort" />
|
152 | </div>
|
153 | <div class="form-row">
|
154 | <label for="node-config-input-proxyUsername">Username</label>
|
155 | <input type="text" id="node-config-input-proxyUsername" />
|
156 | </div>
|
157 | <div class="form-row">
|
158 | <label for="node-config-input-proxyPassword">Password</label>
|
159 | <input type="password" id="node-config-input-proxyPassword" />
|
160 | </div>
|
161 | </div>
|
162 | </div>
|
163 | </script>
|
164 |
|
165 | <script type="text/markdown" data-help-name="axios-endpoint">
|
166 | http endpoint configuration for axios request
|
167 |
|
168 | ### Endpoint
|
169 |
|
170 | : BaseURL (string) : `baseURL` will be prepended to request node `url`.
|
171 | : Username (string) : Optional - Username for http basic authentication.
|
172 | : Password (string) : Optional - Password for http basic authentication.
|
173 |
|
174 | ### TLS
|
175 |
|
176 | : CA Certificate (path) : Add the path to your custom CA certificate.
|
177 | : Verify server certificate (bool) : TLS certificate verification.
|
178 |
|
179 | ### Proxy
|
180 |
|
181 | Proxy hostname, port and optional authentication for proxy.
|
182 | </script>
|
183 |
|
184 | <script type="text/javascript">
|
185 | RED.nodes.registerType("axios-request", {
|
186 | category: "network-input",
|
187 | defaults: {
|
188 | name: { value: "" },
|
189 | endpoint: { type: "axios-endpoint", required: true },
|
190 | method: { value: "get", required: true },
|
191 | url: { value: "" },
|
192 | responseType: { value: "json" },
|
193 | keepAlive: { value: false },
|
194 | timeout: { value: 30000, required: true },
|
195 | validateStatus: { value: true },
|
196 | headers: { value: [] },
|
197 | params: { value: [] }
|
198 | },
|
199 | inputs: 1,
|
200 | outputs: 1,
|
201 | color: "#cbbbf7",
|
202 | icon: "icons/node-red/white-globe.svg",
|
203 | paletteLabel: "axios",
|
204 | oneditprepare: function() {
|
205 | const node = this;
|
206 | ['params', 'headers'].forEach(property => {
|
207 | const plist = node[property] || [];
|
208 | const list = $(`#node-input-${property}-container`)
|
209 | .editableList({
|
210 | addItem: function (container, i, prop) {
|
211 | const row = $('<div/>').css({
|
212 | overflow: 'hidden',
|
213 | whiteSpace: 'nowrap',
|
214 | display: 'flex'
|
215 | }).appendTo(container);
|
216 |
|
217 | const propertyKeyCell = $('<div/>').css({ 'flex-grow': 1 }).appendTo(row);
|
218 | const propertyKeyValue = $('<input/>', {
|
219 | class: `node-input-${property}-name`,
|
220 | type: "text",
|
221 | style: "width: 100%",
|
222 | placeholder: "key"
|
223 | })
|
224 | .appendTo(propertyKeyCell)
|
225 | .typedInput({ types: ["str", "msg", "flow", "global"] });
|
226 | propertyKeyValue.typedInput('type', prop.keyType);
|
227 | propertyKeyValue.typedInput('value', prop.keyValue);
|
228 |
|
229 | const propertyValueCell = $('<div/>').css({ 'flex-grow': 1, 'margin-left': '10px' }).appendTo(row);
|
230 | const propertyValue = $('<input/>', {
|
231 | class: `node-input-${property}-value`,
|
232 | type: "text",
|
233 | style: "width: 100%",
|
234 | placeholder: "value"
|
235 | })
|
236 | .appendTo(propertyValueCell)
|
237 | .typedInput({ types: ["str", "msg", "flow", "global"] });
|
238 | propertyValue.typedInput('type', prop.valueType);
|
239 | propertyValue.typedInput('value', prop.valueValue);
|
240 |
|
241 | },
|
242 | sortable: true,
|
243 | removable: true
|
244 | });
|
245 | plist.forEach(prop => {
|
246 | list.editableList('addItem', prop);
|
247 | });
|
248 | });
|
249 | },
|
250 | oneditsave: function() {
|
251 | ['params', 'headers'].forEach(property => {
|
252 | const list = $(`#node-input-${property}-container`).editableList('items');
|
253 | const node = this;
|
254 | node[property] = [];
|
255 | list.each(function(i) {
|
256 | const prop = $(this);
|
257 | const keyType = prop.find(`.node-input-${property}-name`).typedInput('type');
|
258 | const keyValue = prop.find(`.node-input-${property}-name`).typedInput('value');
|
259 | const valueType = prop.find(`.node-input-${property}-value`).typedInput('type');
|
260 | const valueValue = prop.find(`.node-input-${property}-value`).typedInput('value');
|
261 | node[property].push({
|
262 | keyType, keyValue, valueType, valueValue
|
263 | })
|
264 | });
|
265 | });
|
266 | },
|
267 | oneditresize: function(size) {
|
268 | const dlg = $("#dialog-form");
|
269 | ['params', 'headers'].forEach(property => {
|
270 | const expandRow = dlg.find(`.node-input-${property}-container-row`);
|
271 | let height = dlg.height() - 5;
|
272 | if(expandRow && expandRow.length){
|
273 | const siblingRows = dlg.find(`> .form-row:not(.node-input-${property}-container-row)`);
|
274 | for (let i = 0; i < siblingRows.size(); i++) {
|
275 | const cr = $(siblingRows[i]);
|
276 | if(cr.is(":visible"))
|
277 | height -= cr.outerHeight(true);
|
278 | }
|
279 | $(`#node-input-${property}-container`).editableList('height',height);
|
280 | }
|
281 | });
|
282 |
|
283 | },
|
284 | label: function () {
|
285 | return `[${this.method}] ${this.name || this.url || "request"}`;
|
286 | },
|
287 | });
|
288 | </script>
|
289 |
|
290 | <script type="text/html" data-template-name="axios-request">
|
291 | <div class="form-row">
|
292 | <label for="node-input-endpoint"
|
293 | ><i class="fa fa-server"></i> Endpoint</label
|
294 | >
|
295 | <input type="text" id="node-input-endpoint" />
|
296 | </div>
|
297 | <div class="form-row">
|
298 | <label for="node-input-method"
|
299 | ><i class="fa fa-envelope-o"></i> Method</label
|
300 | >
|
301 | <select id="node-input-method">
|
302 | <option value="get">GET</option>
|
303 | <option value="post">POST</option>
|
304 | <option value="put">PUT</option>
|
305 | <option value="delete">DELETE</option>
|
306 | <option value="patch">PATCH</option>
|
307 | </select>
|
308 | </div>
|
309 | <div class="form-row">
|
310 | <label for="node-input-url"><i class="fa fa-terminal"></i> URL</label>
|
311 | <input type="text" id="node-input-url" placeholder="/resource" />
|
312 | </div>
|
313 | <div class="form-row" style="margin-bottom:0;">
|
314 | <label><i class="fa fa-list"></i> Params</label>
|
315 | </div>
|
316 | <div class="form-row node-input-params-container-row">
|
317 | <ol id="node-input-params-container"></ol>
|
318 | </div>
|
319 | <div class="form-row" style="margin-bottom:0;">
|
320 | <label><i class="fa fa-list"></i> Headers</label>
|
321 | </div>
|
322 | <div class="form-row node-input-headers-container-row">
|
323 | <ol id="node-input-headers-container"></ol>
|
324 | </div>
|
325 | <div class="form-row">
|
326 | <label for="node-input-responseType"
|
327 | ><i class="fa fa-sign-out"></i> Response</label
|
328 | >
|
329 | <select id="node-input-responseType">
|
330 | <option value="json">JSON</option>
|
331 | <option value="text">Text</option>
|
332 | <option value="arraybuffer">Array Buffer</option>
|
333 | </select>
|
334 | </div>
|
335 | <div class="form-row">
|
336 | <input
|
337 | type="checkbox"
|
338 | id="node-input-keepAlive"
|
339 | style="display: inline-block; width: auto; vertical-align: top;"
|
340 | />
|
341 | <label for="node-input-keepAlive" style="width: auto;"
|
342 | >Connection keep-alive</label
|
343 | >
|
344 | </div>
|
345 | <div class="form-row">
|
346 | <label for="node-input-timeout"
|
347 | ><i class="fa fa-clock-o"></i> Timeout</label
|
348 | >
|
349 | <input type="number" id="node-input-timeout" />
|
350 | <span>ms</span>
|
351 | </div>
|
352 | <div class="form-row">
|
353 | <input
|
354 | type="checkbox"
|
355 | id="node-input-validateStatus"
|
356 | style="display: inline-block; width: auto; vertical-align: top;"
|
357 | />
|
358 | <label for="node-input-validateStatus" style="width: auto;"
|
359 | >Throw error if HTTP response status code other than 2xx</label
|
360 | >
|
361 | </div>
|
362 | <div class="form-row">
|
363 | <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
364 | <input type="text" id="node-input-name" />
|
365 | </div>
|
366 | </script>
|
367 |
|
368 | <script type="text/markdown" data-help-name="axios-request">
|
369 | http axios request node
|
370 |
|
371 | ### Node Properties
|
372 |
|
373 | : Endpoint (axios-endpoint) : Define an endpoint configuration
|
374 | : Method (http-method) : Http method [GET, POST, PUT, DELETE].
|
375 | : URL (string) : `URL` will be added to `baseURL`. Overwrite with `msg.url`.
|
376 | : Response (axios-responseType) : JSON, text or array buffer.
|
377 | : Connection keep-alive (boolean) : Keep tcp connection alive between requests for better performance in certain scenarios.
|
378 | : Timeout (integer) : Timeout for request in milliseconds.
|
379 |
|
380 | ### Message Properties
|
381 |
|
382 | : msg.payload (any) : `msg.payload` is the data to be sent as the request body. Only applicable for request methods 'PUT', 'POST', 'DELETE , and 'PATCH'.
|
383 | : msg.headers (object) : `headers` are custom headers to be sent.
|
384 | : msg.params (object) : `params` are the URL parameters to be sent with the request.
|
385 |
|
386 | </script> |
\ | No newline at end of file |