UNPKG

node-red-contrib-snap4city-user

Version:

Nodes for Snap4city project, targeted to standard user (no developer)

183 lines (161 loc) 5.96 kB
/* NODE-RED-CONTRIB-SNAP4CITY-USER Copyright (C) 2018 DISIT Lab http://www.disit.org - University of Florence This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ module.exports = function (RED) { "use strict"; var bodyParser = require("body-parser"); var cookieParser = require("cookie-parser"); var getBody = require('raw-body'); var cors = require('cors'); var jsonParser = bodyParser.json(); var urlencParser = bodyParser.urlencoded({ extended: true }); var onHeaders = require('on-headers'); var typer = require('media-typer'); var isUtf8 = require('is-utf8'); function rawBodyParser(req, res, next) { if (req._body) { return next(); } req.body = ""; req._body = true; var isText = true; var checkUTF = false; if (req.headers['content-type']) { var parsedType = typer.parse(req.headers['content-type']) if (parsedType.type === "text") { isText = true; } else if (parsedType.subtype === "xml" || parsedType.suffix === "xml") { isText = true; } else if (parsedType.type !== "application") { isText = false; } else if (parsedType.subtype !== "octet-stream") { checkUTF = true; } } getBody(req, { length: req.headers['content-length'], encoding: isText ? "utf8" : null }, function (err, buf) { if (err) { return next(err); } if (!isText && checkUTF && isUtf8(buf)) { buf = buf.toString() } req.body = buf; next(); }); } var corsSetup = false; function createResponseWrapper(node, res) { var wrapper = { _res: res }; var toWrap = [ "append", "attachment", "cookie", "clearCookie", "download", "end", "format", "get", "json", "jsonp", "links", "location", "redirect", "render", "send", "sendfile", "sendFile", "sendStatus", "set", "status", "type", "vary" ]; toWrap.forEach(function (f) { wrapper[f] = function () { node.warn("sigfox in: Deprecated call to msg.res." + f); var result = res[f].apply(res, arguments); if (result === res) { return wrapper; } else { return result; } } }); return wrapper; } var corsHandler = function (req, res, next) { next(); } if (RED.settings.httpNodeCors) { corsHandler = cors(RED.settings.httpNodeCors); RED.httpNode.options("*", corsHandler); } function sigfoxIn(config) { var s4cUtility = require("./snap4city-utility.js"); RED.nodes.createNode(this, config); if (RED.settings.httpNodeRoot !== false) { if (!config.device) { this.warn("sigfox in: Missing device type ID"); return; } this.url = "/sigfox/callback/" + config.device; this.method = "post"; var node = this; this.errorHandler = function (err, req, res, next) { node.warn("sigfox in: " + err); res.sendStatus(500); }; this.callback = function (req, res) { var msgid = RED.util.generateId(); res._msgid = msgid; s4cUtility.eventLog(RED, {}, req.body, config, "Node-Red", "SigFox", "/sigfox/callback/" + config.device, "RX"); res.sendStatus(200); node.send({ _msgid: msgid, req: req, res: createResponseWrapper(node, res), payload: req.body }); }; var httpMiddleware = function (req, res, next) { next(); } if (RED.settings.httpNodeMiddleware) { if (typeof RED.settings.httpNodeMiddleware === "function") { httpMiddleware = RED.settings.httpNodeMiddleware; } } var metricsHandler = function (req, res, next) { next(); } RED.httpNode.post(this.url, cookieParser(), httpMiddleware, corsHandler, metricsHandler, jsonParser, urlencParser, rawBodyParser, this.callback, this.errorHandler); this.on("close", function () { 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]) { routes.splice(i, 1); } }); }); } else { this.warn("sigfox in: Cannot create sigfox-in node when httpNodeRoot set to false"); } } RED.nodes.registerType("sigfox in", sigfoxIn); }