mirror of
https://github.com/BetterCorp/BetterFrame.git
synced 2026-05-26 17:56:34 +00:00
fix(nodered): parse JSON body in trigger nodes
RED.httpNode.post registers a raw express route with no body parser, so req.body was undefined and trigger payloads showed all fields null. Add a zero-dep readJsonBody helper that streams + parses req body.
This commit is contained in:
parent
faaa2cef39
commit
5b380d4694
7 changed files with 49 additions and 12 deletions
25
nodered/src/_http-body.js
Normal file
25
nodered/src/_http-body.js
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* Tiny JSON body reader for trigger nodes.
|
||||||
|
*
|
||||||
|
* RED.httpNode.post(path, handler) registers a raw Express route with no
|
||||||
|
* body parser, so req.body is undefined. Trigger nodes call readJsonBody(req)
|
||||||
|
* to get a parsed object (or {} on error / non-JSON).
|
||||||
|
*
|
||||||
|
* Zero dependencies — avoids relying on Node-RED's bundled body-parser being
|
||||||
|
* resolvable from our nodesDir.
|
||||||
|
*/
|
||||||
|
function readJsonBody(req) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (req.body && typeof req.body === "object") return resolve(req.body);
|
||||||
|
let data = "";
|
||||||
|
req.setEncoding("utf8");
|
||||||
|
req.on("data", (c) => { data += c; });
|
||||||
|
req.on("end", () => {
|
||||||
|
if (!data) return resolve({});
|
||||||
|
try { resolve(JSON.parse(data)); } catch { resolve({}); }
|
||||||
|
});
|
||||||
|
req.on("error", () => resolve({}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { readJsonBody };
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
* Output msg shape (kept compatible with the previous filter version):
|
* Output msg shape (kept compatible with the previous filter version):
|
||||||
* { topic, kiosk_id, camera_id, source_type, payload }
|
* { topic, kiosk_id, camera_id, source_type, payload }
|
||||||
*/
|
*/
|
||||||
|
const { readJsonBody } = require("./_http-body.js");
|
||||||
|
|
||||||
module.exports = function (RED) {
|
module.exports = function (RED) {
|
||||||
// Fixed ingest route. Server-side forwarders that want this node to receive
|
// Fixed ingest route. Server-side forwarders that want this node to receive
|
||||||
// their event should POST to /in/camera.event. (Previous releases used a
|
// their event should POST to /in/camera.event. (Previous releases used a
|
||||||
|
|
@ -27,8 +29,8 @@ module.exports = function (RED) {
|
||||||
const filterIdRaw = (config.camera_id || "").toString().trim();
|
const filterIdRaw = (config.camera_id || "").toString().trim();
|
||||||
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
||||||
|
|
||||||
function handler(req, res) {
|
async function handler(req, res) {
|
||||||
const body = (req.body && typeof req.body === "object") ? req.body : {};
|
const body = await readJsonBody(req);
|
||||||
const kioskId = body.kiosk_id !== undefined ? body.kiosk_id
|
const kioskId = body.kiosk_id !== undefined ? body.kiosk_id
|
||||||
: body.source_kiosk_id !== undefined ? body.source_kiosk_id
|
: body.source_kiosk_id !== undefined ? body.source_kiosk_id
|
||||||
: null;
|
: null;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
*
|
*
|
||||||
* Output msg.payload: { camera_id, event: "created" | "updated" | "deleted" }
|
* Output msg.payload: { camera_id, event: "created" | "updated" | "deleted" }
|
||||||
*/
|
*/
|
||||||
|
const { readJsonBody } = require("./_http-body.js");
|
||||||
|
|
||||||
module.exports = function (RED) {
|
module.exports = function (RED) {
|
||||||
const TOPIC = "camera.changed";
|
const TOPIC = "camera.changed";
|
||||||
const ROUTE = "/api/internal/" + TOPIC;
|
const ROUTE = "/api/internal/" + TOPIC;
|
||||||
|
|
@ -21,8 +23,8 @@ module.exports = function (RED) {
|
||||||
const filterIdRaw = (config.camera_id || "").toString().trim();
|
const filterIdRaw = (config.camera_id || "").toString().trim();
|
||||||
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
||||||
|
|
||||||
function handler(req, res) {
|
async function handler(req, res) {
|
||||||
const body = (req.body && typeof req.body === "object") ? req.body : {};
|
const body = await readJsonBody(req);
|
||||||
const camId = body.camera_id !== undefined ? body.camera_id : null;
|
const camId = body.camera_id !== undefined ? body.camera_id : null;
|
||||||
if (filterId !== null && Number(camId) !== filterId) {
|
if (filterId !== null && Number(camId) !== filterId) {
|
||||||
return res.status(200).end();
|
return res.status(200).end();
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
*
|
*
|
||||||
* Output msg.payload: { display_id, kiosk_id, state: "on" | "standby" }
|
* Output msg.payload: { display_id, kiosk_id, state: "on" | "standby" }
|
||||||
*/
|
*/
|
||||||
|
const { readJsonBody } = require("./_http-body.js");
|
||||||
|
|
||||||
module.exports = function (RED) {
|
module.exports = function (RED) {
|
||||||
const TOPIC = "display.power.changed";
|
const TOPIC = "display.power.changed";
|
||||||
const ROUTE = "/api/internal/" + TOPIC;
|
const ROUTE = "/api/internal/" + TOPIC;
|
||||||
|
|
@ -21,8 +23,8 @@ module.exports = function (RED) {
|
||||||
const filterIdRaw = (config.display_id || "").toString().trim();
|
const filterIdRaw = (config.display_id || "").toString().trim();
|
||||||
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
||||||
|
|
||||||
function handler(req, res) {
|
async function handler(req, res) {
|
||||||
const body = (req.body && typeof req.body === "object") ? req.body : {};
|
const body = await readJsonBody(req);
|
||||||
const displayId = body.display_id !== undefined ? body.display_id : null;
|
const displayId = body.display_id !== undefined ? body.display_id : null;
|
||||||
if (filterId !== null && Number(displayId) !== filterId) {
|
if (filterId !== null && Number(displayId) !== filterId) {
|
||||||
return res.status(200).end();
|
return res.status(200).end();
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
* event: "connected" | "disconnected" | "heartbeat",
|
* event: "connected" | "disconnected" | "heartbeat",
|
||||||
* cpu_temp_c?: number, fan_rpm?: number, fan_pwm?: number }
|
* cpu_temp_c?: number, fan_rpm?: number, fan_pwm?: number }
|
||||||
*/
|
*/
|
||||||
|
const { readJsonBody } = require("./_http-body.js");
|
||||||
|
|
||||||
module.exports = function (RED) {
|
module.exports = function (RED) {
|
||||||
const TOPIC = "kiosk.changed";
|
const TOPIC = "kiosk.changed";
|
||||||
const ROUTE = "/api/internal/" + TOPIC;
|
const ROUTE = "/api/internal/" + TOPIC;
|
||||||
|
|
@ -24,8 +26,8 @@ module.exports = function (RED) {
|
||||||
const filterIdRaw = (config.kiosk_id || "").toString().trim();
|
const filterIdRaw = (config.kiosk_id || "").toString().trim();
|
||||||
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
||||||
|
|
||||||
function handler(req, res) {
|
async function handler(req, res) {
|
||||||
const body = (req.body && typeof req.body === "object") ? req.body : {};
|
const body = await readJsonBody(req);
|
||||||
const kioskId = body.kiosk_id !== undefined ? body.kiosk_id : null;
|
const kioskId = body.kiosk_id !== undefined ? body.kiosk_id : null;
|
||||||
if (filterId !== null && Number(kioskId) !== filterId) {
|
if (filterId !== null && Number(kioskId) !== filterId) {
|
||||||
return res.status(200).end();
|
return res.status(200).end();
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
*
|
*
|
||||||
* Output msg.payload: { display_id, kiosk_id, layout_id, layout_name }
|
* Output msg.payload: { display_id, kiosk_id, layout_id, layout_name }
|
||||||
*/
|
*/
|
||||||
|
const { readJsonBody } = require("./_http-body.js");
|
||||||
|
|
||||||
module.exports = function (RED) {
|
module.exports = function (RED) {
|
||||||
const TOPIC = "layout.changed";
|
const TOPIC = "layout.changed";
|
||||||
const ROUTE = "/api/internal/" + TOPIC;
|
const ROUTE = "/api/internal/" + TOPIC;
|
||||||
|
|
@ -20,8 +22,8 @@ module.exports = function (RED) {
|
||||||
const filterIdRaw = (config.display_id || "").toString().trim();
|
const filterIdRaw = (config.display_id || "").toString().trim();
|
||||||
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
||||||
|
|
||||||
function handler(req, res) {
|
async function handler(req, res) {
|
||||||
const body = (req.body && typeof req.body === "object") ? req.body : {};
|
const body = await readJsonBody(req);
|
||||||
const displayId = body.display_id !== undefined ? body.display_id : null;
|
const displayId = body.display_id !== undefined ? body.display_id : null;
|
||||||
if (filterId !== null && Number(displayId) !== filterId) {
|
if (filterId !== null && Number(displayId) !== filterId) {
|
||||||
return res.status(200).end();
|
return res.status(200).end();
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
* Output msg.payload:
|
* Output msg.payload:
|
||||||
* { kiosk_id, kiosk_name, cpu_temp_c, fan_rpm, fan_pwm }
|
* { kiosk_id, kiosk_name, cpu_temp_c, fan_rpm, fan_pwm }
|
||||||
*/
|
*/
|
||||||
|
const { readJsonBody } = require("./_http-body.js");
|
||||||
|
|
||||||
module.exports = function (RED) {
|
module.exports = function (RED) {
|
||||||
const TOPIC = "kiosk.status";
|
const TOPIC = "kiosk.status";
|
||||||
const ROUTE = "/api/internal/" + TOPIC;
|
const ROUTE = "/api/internal/" + TOPIC;
|
||||||
|
|
@ -21,8 +23,8 @@ module.exports = function (RED) {
|
||||||
const filterIdRaw = (config.kiosk_id || "").toString().trim();
|
const filterIdRaw = (config.kiosk_id || "").toString().trim();
|
||||||
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
const filterId = filterIdRaw && !isNaN(Number(filterIdRaw)) ? Number(filterIdRaw) : null;
|
||||||
|
|
||||||
function handler(req, res) {
|
async function handler(req, res) {
|
||||||
const body = (req.body && typeof req.body === "object") ? req.body : {};
|
const body = await readJsonBody(req);
|
||||||
const kioskId = body.kiosk_id !== undefined ? body.kiosk_id : null;
|
const kioskId = body.kiosk_id !== undefined ? body.kiosk_id : null;
|
||||||
if (filterId !== null && Number(kioskId) !== filterId) {
|
if (filterId !== null && Number(kioskId) !== filterId) {
|
||||||
return res.status(200).end();
|
return res.status(200).end();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue