mirror of
https://github.com/node-red/node-red.git
synced 2025-12-27 07:31:07 +01:00
Merge branch 'dev' into truncate-topic-debug
This commit is contained in:
@@ -1290,7 +1290,7 @@
|
||||
"label": "Update Notifications",
|
||||
"settingsTitle": "Enable Update Notifications",
|
||||
"settingsDescription": "<p>Node-RED can notify you when there is a new version available. This ensures you keep up to date with the latest features and fixes.</p><p>This requires sending anonymised data back to the Node-RED team. It does not include any details of your flows or users.</p><p>For full information on what information is collected and how it is used, please see the <a href=\"https://nodered.org/docs/telemetry\" target=\"_blank\">documentation</a>.</p>",
|
||||
"settingsDescription2": "<p>You can change this setting at any time in the editor settings.</p>",
|
||||
"settingsDescription2": "<p>You can change this setting at any time in the User Settings.</p>",
|
||||
"enableLabel": "Yes, enable notifications",
|
||||
"disableLabel": "No, do not enable notifications",
|
||||
"updateAvailable": "Update available",
|
||||
|
||||
@@ -111,6 +111,7 @@
|
||||
"userSettings": "ユーザ設定",
|
||||
"nodes": "ノード",
|
||||
"displayStatus": "ノードのステータスを表示",
|
||||
"displayInfoIcon": "ノード情報のアイコンを表示",
|
||||
"displayConfig": "設定ノード",
|
||||
"import": "読み込み",
|
||||
"importExample": "フロー例を読み込み",
|
||||
@@ -264,6 +265,8 @@
|
||||
"download": "ダウンロード",
|
||||
"importUnrecognised": "認識できない型が読み込まれました:",
|
||||
"importUnrecognised_plural": "認識できない型が読み込まれました:",
|
||||
"importWithModuleInfo": "必要なモジュールが不足",
|
||||
"importWithModuleInfoDesc": "以下のノードは現在パレットにインストールされていませんが、読み込んだフローには必要なノードです:",
|
||||
"importDuplicate": "重複したノードを読み込みました:",
|
||||
"importDuplicate_plural": "重複したノードを読み込みました:",
|
||||
"nodesExported": "クリップボードへフローを書き出しました",
|
||||
@@ -623,12 +626,15 @@
|
||||
"yearsMonthsV": "__y__ 年 __count__ ヵ月前",
|
||||
"yearsMonthsV_plural": "__y__ 年 __count__ ヵ月前"
|
||||
},
|
||||
"manageModules": "モジュールを管理",
|
||||
"nodeCount": "__label__ 個のノード",
|
||||
"nodeCount_plural": "__label__ 個のノード",
|
||||
"pluginCount": "__count__ 個のプラグイン",
|
||||
"pluginCount_plural": "__count__ 個のプラグイン",
|
||||
"moduleCount": "__count__ 個のモジュール",
|
||||
"moduleCount_plural": "__count__ 個のモジュール",
|
||||
"updateCount": "__count__ 個の更新が存在",
|
||||
"updateCount_plural": "__count__ 個の更新が存在",
|
||||
"inuse": "使用中",
|
||||
"enableall": "全て有効化",
|
||||
"disableall": "全て無効化",
|
||||
@@ -638,9 +644,12 @@
|
||||
"update": "__version__ へ更新",
|
||||
"updated": "更新済",
|
||||
"install": "ノードを追加",
|
||||
"installAll": "全てインストール",
|
||||
"installed": "追加しました",
|
||||
"installing": "モジュールのインストールが進行中: __module__",
|
||||
"conflict": "競合",
|
||||
"conflictTip": "<p>インストール済みのノードの種別と競合しているため<br/>ノードをインストールできません</p><p>競合: <code>__module__</code></p>",
|
||||
"majorVersion": "<p>これはノードのメジャーバージョンの更新です。更新内容の詳細については、ドキュメントを確認してください。</p>",
|
||||
"loading": "カタログを読み込み中",
|
||||
"tab-nodes": "現在のノード",
|
||||
"tab-install": "ノードを追加",
|
||||
@@ -648,9 +657,12 @@
|
||||
"sortRelevance": "関連順",
|
||||
"sortAZ": "辞書順",
|
||||
"sortRecent": "日付順",
|
||||
"successfulInstall": "モジュールのインストールが成功",
|
||||
"more": "+ さらに __count__ 個",
|
||||
"upload": "モジュールのtgzファイルをアップロード",
|
||||
"refresh": "モジュールリスト更新",
|
||||
"deprecated": "非推奨",
|
||||
"deprecatedTip": "本モジュールは非推奨です",
|
||||
"errors": {
|
||||
"catalogLoadFailed": "<p>ノードのカタログの読み込みに失敗しました。</p><p>詳細はブラウザのコンソールを確認してください。</p>",
|
||||
"installFailed": "<p>追加処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
|
||||
@@ -1262,6 +1274,16 @@
|
||||
"header": "グローバル環境変数",
|
||||
"revert": "破棄"
|
||||
},
|
||||
"telemetry": {
|
||||
"label": "更新の通知",
|
||||
"settingsTitle": "更新の通知を有効化",
|
||||
"settingsDescription": "<p>新バージョンのNode-REDが存在した時に、通知を受けることができます。この機能によって最新機能の提供や修正があることを把握できます。</p><p>この通知を受け取るには、匿名化されたデータをNode-REDチームに送る必要があります。このデータには、フローやユーザの詳細は含まれません。</p><p>収集される情報と利用方法の詳細については、<a href=\"https://nodered.org/docs/telemetry\" target=\"_blank\">ドキュメント</a>を参照してください。</p>",
|
||||
"settingsDescription2": "<p>この設定はユーザ設定からいつでも変更できます。</p>",
|
||||
"enableLabel": "はい、通知を有効にします",
|
||||
"disableLabel": "いいえ、通知を有効にしません",
|
||||
"updateAvailable": "更新を利用可能",
|
||||
"updateAvailableDesc": "現在、Node-RED __version__ が利用可能"
|
||||
},
|
||||
"action-list": {
|
||||
"toggle-show-tips": "ヒント表示切替",
|
||||
"show-about": "Node-REDの説明を表示",
|
||||
@@ -1302,6 +1324,7 @@
|
||||
"toggle-show-grid": "グリッド表示切替",
|
||||
"toggle-snap-grid": "ノードの配置補助切替",
|
||||
"toggle-status": "ステータス表示切替",
|
||||
"toggle-node-info-icon": "ノード情報のアイコン表示切替",
|
||||
"show-selected-node-labels": "選択したノードのラベルを表示",
|
||||
"hide-selected-node-labels": "選択したノードのラベルを非表示",
|
||||
"scroll-view-up": "上スクロール",
|
||||
@@ -1414,6 +1437,7 @@
|
||||
"show-global-env": "グローバル環境変数を表示",
|
||||
"lock-flow": "フローを固定",
|
||||
"unlock-flow": "フローの固定を解除",
|
||||
"show-node-help": "ノードのヘルプを表示"
|
||||
"show-node-help": "ノードのヘルプを表示",
|
||||
"trigger-selected-nodes-action": "選択したノードのアクションを実行"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,14 @@
|
||||
**/
|
||||
RED.eventLog = (function() {
|
||||
|
||||
var template = '<script type="text/x-red" data-template-name="_eventLog"><div class="form-row node-text-editor-row"><div style="height: 100%;min-height: 150px;" class="node-text-editor" id="red-ui-event-log-editor"></div></div></script>';
|
||||
const template = '<script type="text/x-red" data-template-name="_eventLog"><div class="form-row node-text-editor-row"><div style="height: 100%;min-height: 150px;" class="node-text-editor" id="red-ui-event-log-editor"></div></div></script>';
|
||||
|
||||
let eventLogEditor;
|
||||
let backlog = [];
|
||||
let shown = false;
|
||||
|
||||
const activeLogs = new Set()
|
||||
|
||||
var eventLogEditor;
|
||||
var backlog = [];
|
||||
var shown = false;
|
||||
|
||||
function appendLogLine(line) {
|
||||
backlog.push(line);
|
||||
@@ -38,6 +41,18 @@ RED.eventLog = (function() {
|
||||
init: function() {
|
||||
$(template).appendTo("#red-ui-editor-node-configs");
|
||||
RED.actions.add("core:show-event-log",RED.eventLog.show);
|
||||
|
||||
const statusWidget = $('<button type="button" class="red-ui-footer-button red-ui-event-log-status" style="line-height: normal"><img style="width: 80%" src="red/images/spin.svg"/></div></button>');
|
||||
statusWidget.on("click", function(evt) {
|
||||
RED.actions.invoke("core:show-event-log");
|
||||
})
|
||||
RED.statusBar.add({
|
||||
id: "red-ui-event-log-status",
|
||||
align: "right",
|
||||
element: statusWidget
|
||||
});
|
||||
// RED.statusBar.hide("red-ui-event-log-status");
|
||||
|
||||
},
|
||||
show: function() {
|
||||
if (shown) {
|
||||
@@ -98,6 +113,12 @@ RED.eventLog = (function() {
|
||||
},
|
||||
log: function(id,payload) {
|
||||
var ts = (new Date(payload.ts)).toISOString()+" ";
|
||||
if (!payload.end) {
|
||||
activeLogs.add(id)
|
||||
} else {
|
||||
activeLogs.delete(id);
|
||||
}
|
||||
|
||||
if (payload.type) {
|
||||
ts += "["+payload.type+"] "
|
||||
}
|
||||
@@ -111,6 +132,11 @@ RED.eventLog = (function() {
|
||||
appendLogLine(ts+line);
|
||||
})
|
||||
}
|
||||
if (activeLogs.size > 0) {
|
||||
RED.statusBar.show("red-ui-event-log-status");
|
||||
} else {
|
||||
RED.statusBar.hide("red-ui-event-log-status");
|
||||
}
|
||||
},
|
||||
startEvent: function(name) {
|
||||
backlog.push("");
|
||||
|
||||
@@ -769,6 +769,11 @@ RED.palette.editor = (function() {
|
||||
});
|
||||
|
||||
RED.events.on('registry:module-updated', function(ns) {
|
||||
if (nodeEntries[ns.module]) {
|
||||
// Set the node/plugin as updated
|
||||
nodeEntries[ns.module].info.pending_version = ns.version;
|
||||
}
|
||||
|
||||
refreshNodeModule(ns.module);
|
||||
refreshUpdateStatus();
|
||||
});
|
||||
|
||||
@@ -80,7 +80,7 @@ RED.palette = (function() {
|
||||
getNodeCount: function (visibleOnly) {
|
||||
const nodes = catDiv.find(".red-ui-palette-node")
|
||||
if (visibleOnly) {
|
||||
return nodes.filter(function() { return $(this).css('display') !== 'none'}).length
|
||||
return nodes.filter(function() { return $(this).attr("data-filter") !== "true"}).length
|
||||
} else {
|
||||
return nodes.length
|
||||
}
|
||||
@@ -572,8 +572,10 @@ RED.palette = (function() {
|
||||
var currentLabel = $(el).attr("data-palette-label");
|
||||
var type = $(el).attr("data-palette-type");
|
||||
if (val === "" || re.test(type) || re.test(currentLabel)) {
|
||||
$(el).attr("data-filter", null)
|
||||
$(this).show();
|
||||
} else {
|
||||
$(el).attr("data-filter", "true")
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ export default {
|
||||
"ja": "複数ユーザ同時利用モード",
|
||||
"fr": "Mode Multi-utilisateur"
|
||||
},
|
||||
image: 'images/nr4-multiplayer-location.png',
|
||||
image: '4.0/images/nr4-multiplayer-location.png',
|
||||
description: {
|
||||
"en-US": `<p>This release includes the first small steps towards making Node-RED easier
|
||||
to work with when you have multiple people editing flows at the same time.</p>
|
||||
@@ -44,7 +44,7 @@ export default {
|
||||
"ja": "バックグラウンドのデプロイ処理の改善",
|
||||
"fr": "Meilleure gestion du déploiement en arrière-plan"
|
||||
},
|
||||
image: 'images/nr4-background-deploy.png',
|
||||
image: '4.0/images/nr4-background-deploy.png',
|
||||
description: {
|
||||
"en-US": `<p>If another user deploys changes whilst you are editing, we now use a more discrete notification
|
||||
that doesn't stop you continuing your work - especially if they are being very productive and deploying lots
|
||||
@@ -60,7 +60,7 @@ export default {
|
||||
"ja": "フローの差分表示の改善",
|
||||
"fr": "Amélioration des différences de flux"
|
||||
},
|
||||
image: 'images/nr4-diff-update.png',
|
||||
image: '4.0/images/nr4-diff-update.png',
|
||||
description: {
|
||||
"en-US": `<p>When viewing changes made to a flow, Node-RED now distinguishes between nodes that have had configuration
|
||||
changes and those that have only been moved.<p>
|
||||
@@ -79,7 +79,7 @@ export default {
|
||||
"ja": "設定ノードのUXが向上",
|
||||
"fr": "Meilleure expérience utilisateur du noeud de configuration"
|
||||
},
|
||||
image: 'images/nr4-config-select.png',
|
||||
image: '4.0/images/nr4-config-select.png',
|
||||
description: {
|
||||
"en-US": `<p>The Configuration node selection UI has had a small update to have a dedicated 'add' button
|
||||
next to the select box.</p>
|
||||
@@ -97,7 +97,7 @@ export default {
|
||||
"ja": "タイムスタンプの形式の項目",
|
||||
"fr": "Options de formatage de l'horodatage"
|
||||
},
|
||||
image: 'images/nr4-timestamp-formatting.png',
|
||||
image: '4.0/images/nr4-timestamp-formatting.png',
|
||||
description: {
|
||||
"en-US": `<p>Nodes that let you set a timestamp now have options on what format that timestamp should be in.</p>
|
||||
<p>We're keeping it simple to begin with by providing three options:<p>
|
||||
@@ -128,7 +128,7 @@ export default {
|
||||
"ja": "フロー/グローバル、環境変数の型の自動補完",
|
||||
"fr": "Saisie automatique des types de flux/global et env"
|
||||
},
|
||||
image: 'images/nr4-auto-complete.png',
|
||||
image: '4.0/images/nr4-auto-complete.png',
|
||||
description: {
|
||||
"en-US": `<p>The <code>flow</code>/<code>global</code> context inputs and the <code>env</code> input
|
||||
now all include auto-complete suggestions based on the live state of your flows.</p>
|
||||
@@ -146,7 +146,7 @@ export default {
|
||||
"ja": "サブフローでの設定ノードのカスタマイズ",
|
||||
"fr": "Personnalisation du noeud de configuration dans les sous-flux"
|
||||
},
|
||||
image: 'images/nr4-sf-config.png',
|
||||
image: '4.0/images/nr4-sf-config.png',
|
||||
description: {
|
||||
"en-US": `<p>Subflows can now be customised to allow each instance to use a different
|
||||
config node of a selected type.</p>
|
||||
@@ -183,7 +183,7 @@ export default {
|
||||
"ja": "パレット管理にプラグインを表示",
|
||||
"fr": "Affichage des Plugins dans le gestionnaire de palettes"
|
||||
},
|
||||
image: 'images/nr4-plugins.png',
|
||||
image: '4.0/images/nr4-plugins.png',
|
||||
description: {
|
||||
"en-US": `<p>The palette manager now shows any plugin modules you have installed, such as
|
||||
<code>node-red-debugger</code>. Previously they would only be shown if the plugins include
|
||||
|
||||
@@ -17,23 +17,28 @@ export default {
|
||||
{
|
||||
title: {
|
||||
"en-US": "Update notifications",
|
||||
"ja": "更新の通知",
|
||||
"fr": "Notifications de mise à jour"
|
||||
},
|
||||
image: 'images/update-notification.png',
|
||||
description: {
|
||||
"en-US": `<p>Stay up to date with notifications when there is a new Node-RED version available, or updates to the nodes you have installed</p>`,
|
||||
"ja": `<p>新バージョンのNode-REDの提供や、インストールしたノードの更新があった時に、通知を受け取ることができます。</p>`,
|
||||
"fr": `<p>Désormais vous recevrez une notification lorsqu'une nouvelle version de Node-RED ou une nouvelle version relative à un des noeuds que vous avez installés est disponible</p>`
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Flow documentation",
|
||||
"ja": "フローのドキュメント",
|
||||
"fr": "Documentation des flux"
|
||||
},
|
||||
image: 'images/node-docs.png',
|
||||
description: {
|
||||
"en-US": `<p>Quickly see which nodes have additional documentation with the new documentation icon.</p>
|
||||
<p>Clicking on the icon opens up the Description tab of the node edit dialog.</p>`,
|
||||
"ja": `<p>ドキュメントアイコンによって、どのノードにドキュメントが追加されているかをすぐに確認できます。</p>
|
||||
<p>アイコンをクリックすると、ノード編集ダイアログの説明タブが開きます。</p>`,
|
||||
"fr": `<p>Voyez rapidement quels noeuds ont une documentation supplémentaire avec la nouvelle icône de documentation.</p>
|
||||
<p>Cliquer sur l'icône ouvre l'onglet Description de la boîte de dialogue d'édition du noeud.</p>`
|
||||
}
|
||||
@@ -41,6 +46,7 @@ export default {
|
||||
{
|
||||
title: {
|
||||
"en-US": "Palette Manager Improvements",
|
||||
"ja": "パレットの管理の改善",
|
||||
"fr": "Améliorations du Gestionnaire de Palettes"
|
||||
},
|
||||
description: {
|
||||
@@ -50,6 +56,12 @@ export default {
|
||||
<li>See which nodes have been deprecated by their author and are no longer recommended for use</li>
|
||||
<li>Links to node documentation for the nodes you already have installed</li>
|
||||
</ul>`,
|
||||
"ja": `<p>パレットの管理に多くの改善が加えられました:</p>
|
||||
<ul>
|
||||
<li>検索結果はダウンロード数順で並べられ、最も人気のあるノードを見つけやすくなりました。</li>
|
||||
<li>作者によって非推奨とされ、利用が推奨されなくなったノードかを確認できるようになりました。</li>
|
||||
<li>既にインストールされているノードに、ノードのドキュメントへのリンクが追加されました。</li>
|
||||
</ul>`,
|
||||
"fr": `<p>Le Gestionnaire de Palettes a bénéficié de nombreuses améliorations :</p>
|
||||
<ul>
|
||||
<li>Les résultats de recherche sont triés par téléchargement pour vous aider à trouver les noeuds les plus populaires.</li>
|
||||
@@ -61,6 +73,7 @@ export default {
|
||||
{
|
||||
title: {
|
||||
"en-US": "Installing missing modules",
|
||||
"ja": "不足モジュールのインストール",
|
||||
"fr": "Installation des modules manquants"
|
||||
},
|
||||
image: 'images/missing-modules.png',
|
||||
@@ -68,6 +81,9 @@ export default {
|
||||
"en-US": `<p>Flows exported from Node-RED 4.1 now include information on what additional modules need to be installed.</p>
|
||||
<p>When importing a flow with this information, the editor will let you know what is missing and help to get them installed.</p>
|
||||
`,
|
||||
"ja": `<p>Node-RED 4.1から書き出したフローには、インストールが必要な追加モジュールの情報が含まれる様になりました。</p>
|
||||
<p>この情報を含むフローを読み込むと、エディタは不足しているモジュールを通知し、インストールを支援します。</p>
|
||||
`,
|
||||
"fr": `<p>Les flux exportés depuis Node-RED 4.1 incluent désormais des informations sur les modules supplémentaires à installer.</p>
|
||||
<p>Lors de l'importation d'un flux contenant ces informations, l'éditeur vous indiquera les modules manquants et vous aidera à les installer.</p>
|
||||
`
|
||||
@@ -89,9 +105,13 @@ export default {
|
||||
<li>Better display of error objects in the Debug sidebar</li>
|
||||
<li>and lots more...</li>
|
||||
</ul>`,
|
||||
// "ja": `<p>コアノードには沢山の軽微な修正、ドキュメント更新、小さな機能拡張が入っています。全リストはヘルプサイドバーにある変更履歴を参照してください。</p>
|
||||
// <ul>
|
||||
// </ul>`,
|
||||
"ja": `<p>コアノードには沢山の軽微な修正、ドキュメント更新、小さな機能拡張が入っています。全リストはヘルプサイドバーにある変更履歴を参照してください。</p>
|
||||
<ul>
|
||||
<li>Functionノードで<code>node:</code>のプレフィックスモジュールをサポート</li>
|
||||
<li>ランタイム設定からFunctionノードのグローバルタイムアウトを設定可能</li>
|
||||
<li>デバッグサイドバーでのエラーオブジェクトの表示を改善</li>
|
||||
<li>その他、多数...</li>
|
||||
</ul>`,
|
||||
"fr": `<p>Les noeuds principaux ont bénéficié de nombreux correctifs mineurs, de mises à jour de documentation et d'améliorations mineures.
|
||||
Consultez le journal complet des modifications dans la barre latérale d'aide pour une liste complète.</p>
|
||||
<ul>
|
||||
|
||||
@@ -25,11 +25,22 @@
|
||||
<option value="patch">PATCH</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row form-row-http-in-upload hide">
|
||||
|
||||
<div id="form-reqBody-http-in-controller" class="form-row hide" style="display: flex;">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-upload" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-upload" style="width: 70%;" data-i18n="httpin.label.upload"></label>
|
||||
<div style="display: flex; margin-left: 5px; flex-direction: column-reverse; gap:35%;">
|
||||
<div id="form-row-http-in-upload" class="hide" style="display: flex;">
|
||||
<input type="checkbox" id="node-input-upload" style="margin-right: 5%; margin-bottom: 5%;">
|
||||
<label for="node-input-upload" style="text-wrap: nowrap;" data-i18n="httpin.label.upload"></label>
|
||||
</div>
|
||||
<div id="form-row-http-in-parsing" class="hide" style="display: flex;">
|
||||
<input type="checkbox" id="node-input-skipBodyParsing" style="margin-right: 5%; margin-bottom: 5%;">
|
||||
<label for="node-input-skipBodyParsing" style="text-wrap: nowrap;" data-i18n="httpin.label.parsing"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-url"><i class="fa fa-globe"></i> <span data-i18n="httpin.label.url"></span></label>
|
||||
<input id="node-input-url" type="text" placeholder="/url">
|
||||
@@ -74,6 +85,7 @@
|
||||
label:RED._("node-red:httpin.label.url")},
|
||||
method: {value:"get",required:true},
|
||||
upload: {value:false},
|
||||
skipBodyParsing: {value:false},
|
||||
swaggerDoc: {type:"swagger-doc", required:false}
|
||||
},
|
||||
inputs:0,
|
||||
@@ -115,16 +127,22 @@
|
||||
$('.row-swagger-doc').hide();
|
||||
}
|
||||
$("#node-input-method").on("change", function() {
|
||||
if ($(this).val() === "post") {
|
||||
$(".form-row-http-in-upload").show();
|
||||
var method = $(this).val();
|
||||
if(["post", "put", "patch","delete"].includes(method)){
|
||||
$("#form-reqBody-http-in-controller").show();
|
||||
$("#form-row-http-in-parsing").show();
|
||||
if (method === "post") {
|
||||
$("#form-row-http-in-upload").show();
|
||||
} else {
|
||||
$("#form-row-http-in-upload").hide();
|
||||
}
|
||||
} else {
|
||||
$(".form-row-http-in-upload").hide();
|
||||
$("#form-row-http-in-parsing").hide();
|
||||
$("#form-row-http-in-upload").hide();
|
||||
$("#form-reqBody-http-in-controller").hide();
|
||||
}
|
||||
}).change();
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
var headerTypes = [
|
||||
{value:"content-type",label:"Content-Type",hasValue: false},
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var rootApp;
|
||||
var bodyParser = require("body-parser");
|
||||
var multer = require("multer");
|
||||
var cookieParser = require("cookie-parser");
|
||||
@@ -26,6 +27,7 @@ module.exports = function(RED) {
|
||||
var mediaTyper = require('media-typer');
|
||||
var isUtf8 = require('is-utf8');
|
||||
var hashSum = require("hash-sum");
|
||||
var rawDataRoutes = new Set();
|
||||
|
||||
function rawBodyParser(req, res, next) {
|
||||
if (req.skipRawBodyParser) { next(); } // don't parse this if told to skip
|
||||
@@ -71,7 +73,65 @@ module.exports = function(RED) {
|
||||
});
|
||||
}
|
||||
|
||||
var corsSetup = false;
|
||||
/**
|
||||
* This method retrieves the root app by traversing the parent hierarchy.
|
||||
* @param {import('express').Application} app
|
||||
* @returns {import('express').Application}
|
||||
*/
|
||||
function getRootApp(app) {
|
||||
if (typeof app.parent === 'undefined') {
|
||||
return app;
|
||||
}
|
||||
return getRootApp(app.parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* It provide the unique route key
|
||||
* @param {{method: string, url: string}} obj
|
||||
* @returns
|
||||
*/
|
||||
function getRouteKey(obj) {
|
||||
var method = obj.method.toUpperCase();
|
||||
// Normalize the URL by replacing double slashes with a single slash and removing the trailing slash
|
||||
var url = obj.url.replace(/\/{2,}/g, '/').replace(/\/$/, '');
|
||||
return `${method}:${url}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* This middleware is for capture raw body
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} _res
|
||||
* @param {import('express').NextFunction} next
|
||||
* @returns
|
||||
*/
|
||||
function rawBodyCapture(req, _res, next) {
|
||||
var routeKey = getRouteKey({ method: req.method, url: req._parsedUrl.pathname });
|
||||
// Check if routeKey exist in rawDataRoutes
|
||||
if (rawDataRoutes.has(routeKey)) {
|
||||
// Convert the request stream to buffer
|
||||
getBody(req, {
|
||||
length: req.headers['content-length'],
|
||||
}, function (err, buf) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
req.body = buf;
|
||||
// Skip the body parsing
|
||||
req.skipRawBodyParser = true;
|
||||
req._body = true;
|
||||
next();
|
||||
})
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
if(typeof RED.httpNode === 'function' && (rootApp = getRootApp(RED.httpNode))) {
|
||||
// Add middleware to the stack
|
||||
rootApp.use(rawBodyCapture);
|
||||
// Move the middleware to top of the stack
|
||||
rootApp._router.stack.unshift(rootApp._router.stack.pop());
|
||||
}
|
||||
|
||||
function createRequestWrapper(node,req) {
|
||||
// This misses a bunch of properties (eg headers). Before we use this function
|
||||
@@ -125,6 +185,7 @@ module.exports = function(RED) {
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
function createResponseWrapper(node,res) {
|
||||
var wrapper = {
|
||||
_res: res
|
||||
@@ -188,9 +249,16 @@ module.exports = function(RED) {
|
||||
}
|
||||
this.method = n.method;
|
||||
this.upload = n.upload;
|
||||
this.skipBodyParsing = n.skipBodyParsing;
|
||||
this.swaggerDoc = n.swaggerDoc;
|
||||
|
||||
var node = this;
|
||||
var routeKey = getRouteKey({method: this.method, url: RED.httpNode.path() + this.url});
|
||||
|
||||
// If the user enables raw body, add it to the raw data routes.
|
||||
if(this.skipBodyParsing) {
|
||||
rawDataRoutes.add(routeKey);
|
||||
}
|
||||
|
||||
this.errorHandler = function(err,req,res,next) {
|
||||
node.warn(err);
|
||||
@@ -227,7 +295,9 @@ module.exports = function(RED) {
|
||||
}
|
||||
|
||||
var maxApiRequestSize = RED.settings.apiMaxLength || '5mb';
|
||||
|
||||
var jsonParser = bodyParser.json({limit:maxApiRequestSize});
|
||||
|
||||
var urlencParser = bodyParser.urlencoded({limit:maxApiRequestSize,extended:true});
|
||||
|
||||
var metricsHandler = function(req,res,next) { next(); }
|
||||
@@ -254,25 +324,27 @@ module.exports = function(RED) {
|
||||
var mp = multer({ storage: multer.memoryStorage() }).any();
|
||||
multipartParser = function(req,res,next) {
|
||||
mp(req,res,function(err) {
|
||||
req._body = true;
|
||||
next(err);
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
if (this.method == "get") {
|
||||
RED.httpNode.get(this.url,cookieParser(),httpMiddleware,corsHandler,metricsHandler,this.callback,this.errorHandler);
|
||||
RED.httpNode.get(this.url, cookieParser(), httpMiddleware, corsHandler, metricsHandler, this.callback, this.errorHandler);
|
||||
} else if (this.method == "post") {
|
||||
RED.httpNode.post(this.url,cookieParser(),httpMiddleware,corsHandler,metricsHandler,jsonParser,urlencParser,multipartParser,rawBodyParser,this.callback,this.errorHandler);
|
||||
RED.httpNode.post(this.url,cookieParser(), httpMiddleware, corsHandler, metricsHandler, jsonParser, urlencParser, multipartParser, rawBodyParser, this.callback, this.errorHandler);
|
||||
} else if (this.method == "put") {
|
||||
RED.httpNode.put(this.url,cookieParser(),httpMiddleware,corsHandler,metricsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler);
|
||||
RED.httpNode.put(this.url, cookieParser(), httpMiddleware, corsHandler, metricsHandler, jsonParser, urlencParser, rawBodyParser, this.callback, this.errorHandler);
|
||||
} else if (this.method == "patch") {
|
||||
RED.httpNode.patch(this.url,cookieParser(),httpMiddleware,corsHandler,metricsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler);
|
||||
RED.httpNode.patch(this.url, cookieParser(), httpMiddleware, corsHandler, metricsHandler, jsonParser, urlencParser, rawBodyParser, this.callback, this.errorHandler);
|
||||
} else if (this.method == "delete") {
|
||||
RED.httpNode.delete(this.url,cookieParser(),httpMiddleware,corsHandler,metricsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler);
|
||||
RED.httpNode.delete(this.url, cookieParser(), httpMiddleware, corsHandler, metricsHandler, jsonParser, urlencParser, rawBodyParser, this.callback, this.errorHandler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.on("close",function() {
|
||||
// Remove it from the raw data routes if the node is closed
|
||||
rawDataRoutes.delete(routeKey);
|
||||
var node = this;
|
||||
RED.httpNode._router.stack.forEach(function(route,i,routes) {
|
||||
if (route.route && route.route.path === node.url && route.route.methods[node.method]) {
|
||||
@@ -284,9 +356,9 @@ module.exports = function(RED) {
|
||||
this.warn(RED._("httpin.errors.not-created"));
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.registerType("http in",HTTPIn);
|
||||
|
||||
|
||||
function HTTPOut(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
var node = this;
|
||||
@@ -361,5 +433,6 @@ module.exports = function(RED) {
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
RED.nodes.registerType("http response",HTTPOut);
|
||||
}
|
||||
|
||||
@@ -599,7 +599,18 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
||||
}
|
||||
} else {
|
||||
if (msg.hasOwnProperty('rejectUnauthorized')) {
|
||||
opts.https = { rejectUnauthorized: msg.rejectUnauthorized };
|
||||
if (typeof msg.rejectUnauthorized === 'boolean') {
|
||||
opts.https = { rejectUnauthorized: msg.rejectUnauthorized }
|
||||
} else if (typeof msg.rejectUnauthorized === 'string') {
|
||||
if (msg.rejectUnauthorized.toLowerCase() === 'true' || msg.rejectUnauthorized.toLowerCase() === 'false') {
|
||||
opts.https = { rejectUnauthorized: (msg.rejectUnauthorized.toLowerCase() === 'true') }
|
||||
} else {
|
||||
node.warn(RED._("httpin.errors.rejectunauthorized-invalid"))
|
||||
}
|
||||
} else {
|
||||
node.warn(RED._("httpin.errors.rejectunauthorized-invalid"))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -516,6 +516,7 @@
|
||||
"doc": "Docs",
|
||||
"return": "Return",
|
||||
"upload": "Accept file uploads?",
|
||||
"parsing": "Skip body parsing?",
|
||||
"status": "Status code",
|
||||
"headers": "Headers",
|
||||
"other": "other",
|
||||
@@ -563,7 +564,8 @@
|
||||
"timeout-isnan": "Timeout value is not a valid number, ignoring",
|
||||
"timeout-isnegative": "Timeout value is negative, ignoring",
|
||||
"invalid-payload": "Invalid payload",
|
||||
"invalid-url": "Invalid url"
|
||||
"invalid-url": "Invalid url",
|
||||
"rejectunauthorized-invalid": "msg.rejectUnauthorized should be a boolean"
|
||||
},
|
||||
"status": {
|
||||
"requesting": "requesting"
|
||||
|
||||
@@ -406,6 +406,7 @@
|
||||
"label": {
|
||||
"unknown": "unknown"
|
||||
},
|
||||
"manageModules": "モジュールを管理",
|
||||
"tip": "<p>現在のNode-RED環境では、本ノードの型が不明です。</p><p><i>現在の状態で本ノードをデプロイすると設定は保存されますが、不明なノードがインストールされるまでフローは実行されません。</i></p><p>詳細はノードの「情報」を参照してください。</p>"
|
||||
},
|
||||
"mqtt": {
|
||||
|
||||
@@ -135,7 +135,7 @@ function getLibraryEntry(type,path) {
|
||||
throw err;
|
||||
});
|
||||
} else {
|
||||
throw err;
|
||||
throw new Error(`Library Entry not found ${path}`, { cause: err});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ module.exports = {
|
||||
stdout: stdout,
|
||||
stderr: stderr
|
||||
}
|
||||
emit && events.emit("event-log", {id:invocationId,payload:{ts: Date.now(),data:"rc="+code}});
|
||||
emit && events.emit("event-log", {id:invocationId,payload:{ts: Date.now(), data:"rc="+code, end: true}});
|
||||
|
||||
if (code === 0) {
|
||||
resolve(result)
|
||||
|
||||
2
packages/node_modules/node-red/red.js
vendored
2
packages/node_modules/node-red/red.js
vendored
@@ -66,6 +66,7 @@ var knownOpts = {
|
||||
"define": [String, Array],
|
||||
"no-telemetry": Boolean
|
||||
};
|
||||
|
||||
var shortHands = {
|
||||
"?":["--help"],
|
||||
"p":["--port"],
|
||||
@@ -292,7 +293,6 @@ httpsPromise.then(function(startupHttps) {
|
||||
server = http.createServer(function(req,res) {app(req,res);});
|
||||
}
|
||||
server.setMaxListeners(0);
|
||||
|
||||
function formatRoot(root) {
|
||||
if (root[0] != "/") {
|
||||
root = "/" + root;
|
||||
|
||||
Reference in New Issue
Block a user