Express + MQTT from POST request to publish in topic - node.js

I need a Node.js web service that accept a specific POST request that will trigger a publishing in a specific MQTT topic.
I use Express to listen for the request and this part of the script works fine.
The problem is when I it should trigger the publish in topic to perform a downlink.
The code without the Express part works fine. So It seems like Express interfere with MQTT. But the connection to the Broker works fine. Only the publish procedure doesn't work.
var express = require('express');
var bodyParser = require('body-parser');
var mqtt = require('mqtt')
var fs = require('fs')
var path = require('path')
const util = require('util')
var app = express();
var CERT = //certificate
var PORT = //port
var HOST = // host
var options = {
port: PORT,
host: HOST,
clientId: //client_id
username: //uname
password: //pswd
cert: CERT,
rejectUnauthorized: false,
protocol: 'mqtts'
}
var client;
var jsonParser = bodyParser.json();
var port = process.env.PORT || 8080;
app.use(express.static('public'));
app.get('/', function (req, res) {
res.render(__dirname + "/public/index.html");
})
client = mqtt.connect(options);
client.on("connect", () => {
console.log("MQTT connected");
})
client.on('message', function (topic, message) {
var msg = JSON.parse(message)
console.log("topic: " + topic + " msg:" + util.inspect(msg))
});
app.post('/', jsonParser, function (req, res) {
// Prepare output in JSON format
data = {
dev_id: req.body.dev_id,
pswd: req.body.password,
tx_cycle: req.body.tx_cycle
};
if (data.pswd != "password") {
console.log("Wrong password")
}
else {
console.log(data);
var topic = 'publish_topic';
var tx_cy = data.tx_cycle;
var msg = '{"port":"222","payload":"' + tx_cy + '","confirmed": false,"window":"BOTH","priority":0}';
console.log('Try to send downlink message, for ' + data.dev_id + ' set to ' + data.tx_cycle + ' min -> hex ' + tx_cy);
client.subscribe('reply/+/id/+');
client.publish(topic, msg);
res.status(200).send(msg + " sent to broker");
}
});
var server = app.listen(port, function () {
var host = server.address().address
var port = server.address().port
console.log("App listening at http://%s:%s", host, port)
})

I solve the problem. The client id was refused by the broker because was not unique. Changing it solved the issue.

Related

error websocket server nodejs fluctuating data on react frontend

I am trying to impliment websocket server for my frontend chart for trading values but whenever i try to change graph pairs its fluctuating my frontend and not clearing privious request here's my server file
const express = require('express');
const path = require('path');
const mysql = require('mysql')
const bodyParser = require('body-parser');
const passport = require('passport');
const exchangeCtrl = require("./controllers/exchange.controller.js");
const webSocketServer = require("websocket").server;
const cors = require("cors");
const app = express();
app.use(cors());
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use('/static', express.static('public'))
const port = 8000;
var server = app.listen(port, () => console.log(`Server up and running on port
${port} !`));
const wsServer = new webSocketServer({
noServer: true,
path: "/websockets",
httpServer: server,
});
const client = {};
const getUniqueId = () => {
const s4 = () =>
Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
return s4() + "-" + s4() + "-" + s4();
};
var socketDataVar = "";
wsServer.on("request", function (request) {
var userUd = getUniqueId();
const connection = request.accept(null, request.origin);
client[userUd] = connection;
client[userUd].send(JSON.stringify(userUd));
connection.on("message", async function (message) {
var interval = 1000;
if (message.type === "utf8") {
if (message.utf8Data) {
if (JSON.parse(message.utf8Data) == "disconnect") {
clearInterval(socketDataVar);
} else {
socketDataVar = setInterval(
() => socketData(message.utf8Data),
interval
);
}
}
}
});
const socketData = async (socket) => {
var value = JSON.parse(socket);
var firstCoinId = value.firstCoinId;
var secondCoinId = value.secondCoinId;
var userId = value.userId;
var clientId = value.clientId;
var graphDataApi = await exchangeCtrl.graphData(firstCoinId, secondCoinId);
var topBarApi = await exchangeCtrl.topBar(firstCoinId, secondCoinId);
var filalData = {
graphDataApi,
topBarApi
};
for (key in client) {
client[key].sendUTF(JSON.stringify(filalData));
}
};
});
I am trying to clear the interval and then set the new values but i might think that its not working and i get 2 set of data on each click of frontend

Https proxy decode encoded data node js

I am trying to setup a proxy for http and https. Here is my code,
const http = require('http');
var https = require('https');
const fs = require('fs');
var url = require('url');
var net = require('net');
const config = require('./config');
let proxify = function (req, res) {
var urlObj = url.parse(req.url);
var target = urlObj.protocol + '//' + urlObj.host;
if (!req.headers['x-target']) req.headers['x-target'] = target;
req.headers['x-proxy-username'] = config.username;
req.headers['x-proxy-password'] = config.password;
console.log(target);
console.log('Proxy HTTP request for:', target);
var proxy = httpProxy.createProxyServer({});
proxy.on('error', function (err, req, res) {
console.log('proxy error', err);
res.end();
});
proxy.web(req, res, { target: config.server, changeOrigin: true });
};
var httpserver = http.createServer(proxify).listen(2890); //this is the port your clients will connect to
const httpsserver = https
.createServer(
{
cert: fs.readFileSync('./ssl_cert/cert.pem'),
key: fs.readFileSync('./ssl_cert/key.pem'),
},
proxify
)
.listen(2891);
var regex_hostport = /^([^:]+)(:([0-9]+))?$/;
var getHostPortFromString = function (hostString, defaultPort) {
var host = hostString;
var port = defaultPort;
var result = regex_hostport.exec(hostString);
if (result != null) {
host = result[1];
if (result[2] != null) {
port = result[3];
}
}
return [host, port];
};
httpserver.addListener('connect', function (req, socket, bodyhead) {
var hostPort = getHostPortFromString(req.url, 443);
var hostDomain = hostPort[0];
var port = parseInt(hostPort[1]);
console.log('Proxying HTTPS request for:', hostDomain, port);
req.headers['x-target'] = 'http://' + hostDomain + ':' + port;
req.headers['x-proxy-username'] = config.username;
req.headers['x-proxy-password'] = config.password;
var proxyHost = new URL(config.server);
var proxySocket = new net.Socket();
proxySocket.connect(
{ port: proxyHost.port, host: proxyHost.hostname },
function () {
console.log('bodyhead', bodyhead.toString()); //debug
proxySocket.write(bodyhead);
socket.write(
'HTTP/' + req.httpVersion + ' 200 Connection established\r\n\r\n'
);
}
);
proxySocket.on('data', function (chunk) {
console.log('proxy data chunk', chunk.toString()); // debug
socket.write(chunk);
});
proxySocket.on('end', function () {
socket.end();
});
proxySocket.on('error', function () {
socket.write('HTTP/' + req.httpVersion + ' 500 Connection error\r\n\r\n');
socket.end();
});
socket.on('data', function (chunk) {
console.log('data chunk', chunk.toString('utf8')); // debug
proxySocket.write(chunk);
});
socket.on('end', function () {
proxySocket.end();
});
socket.on('error', function () {
proxySocket.end();
});
});
Don't judge me too hard, just trying to get it working first.
When proxying http with windows 10 proxy settings, it works fine. But when I am trying to proxy https, it logs encoded data like `↕►♦♦♦☺♣♣♣♠♠☺↕3+)/1.1♣♣☺
☺↔ \s☻�t�DQ��g}T�c\‼sO��♦��U��ޝ∟-☻☺☺+♂
→→♥♦♥♥♥☻♥☺♥☻☻j☺§�` and gives a 400 bad request.I don't know if its the encoding of https response or something else, I have no idea what i am doing at this point and need help.
it is because https uses tls/ssl to encrypt the data.

Socketio on https using redis

I have a webapplication on a bitnami lamp stack, the os is ubuntu and it uses Apache as a webserver.
The SSL Certificate is generated using Let's Encrypt. I can visit the site on http and https.
Furthermore I am using following stacks:
- nodejs
- socket.io
- redis
Sending notifications on my local machine work fine, the websocket works.
But on my production Server which runs on https it does not work. I Keep getting following error messages:
socket.io.js:2 GET https://mypage.com:3000/socket.io/?EIO=3&transport=polling&t=MNxGNEt
net::ERR_CONNECTION_TIMED_OUT
This is how my socket.js (Server) Looks like:
var app = require('http').createServer(handler);
var fs = require('fs');
var io = require('socket.io')(app);
var Redis = require('ioredis');
var redis = new Redis();
// class declaration
var Redis = require('ioredis');
function handler(req, res) {
res.writeHead(200);
res.end('');
}
io.on('connection', function(socket) {});
var redisUserSignedUp = new Redis();
redisUserSignedUp.subscribe('signed-up-channel');
redisUserSignedUp.on('message', function(channel, message) {
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
// run server on port 3000
app.listen(3000, function () {
console.log('Server runs!');
});
In my production I currently am trying it like this:
var app = require('https').createServer({
key: fs.readFileSync('/opt/bitnami/apache2/conf/serverKey.pem'),
cert: fs.readFileSync('/opt/bitnami/apache2/conf/serverCrt.pem')
}, handler);
var fs = require('fs');
var io = require('socket.io')(app);
var Redis = require('ioredis');
var redis = new Redis();
// class declaration
var Redis = require('ioredis');
function handler(req, res) {
res.writeHead(200);
res.end('');
}
io.on('connection', function(socket) {});
var redisUserSignedUp = new Redis();
redisUserSignedUp.subscribe('signed-up-channel');
redisUserSignedUp.on('message', function(channel, message) {
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
// run server on port 3000
app.listen(3000, function () {
console.log('Server runs!');
});
And I am trying to Access it like this:
var options = {
key: fs.readFileSync('/opt/bitnami/apache2/conf/serverKey.pem'),
cert: fs.readFileSync('/opt/bitnami/apache2/conf/serverCrt.pem'),
requestCert: true
}
var app = require('https').createServer(options, handler);
local:
const socket = io('http://myapp.test:3000'); // localhost dev Folder is mapped to this .test url
socket.on('signed-in-channel:App\\Events\\UserSignedIn', (data) => {
…
production:
var socket = io('mypage.com:3000', {secure: true});
You only create a http server but to connect with ssl you need a https server.
var options = {
key: fs.readFileSync('./file.pem'),
cert: fs.readFileSync('./file.crt')
};
var app = require('https').createServer(handler);

Node.js server just keeps loading with no result

server.js
const http = require('http');
const app = require('./app');
const port = process.env.PORT || 3000;
const server = http.createServer();
server.listen(port);
app.js
const express = require('express');
const app = express();
const productRoutes = require('./api/routes/products');
app.use('/products', productRoutes);
module.exports = app;
so when i just run the code node server.js it just keep looping without any result.
Check out this link It gives a bit more detail on how that works.
const http = require('http');
const net = require('net');
const url = require('url');
// Create an HTTP tunneling proxy
const proxy = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('okay');
});
proxy.on('connect', (req, cltSocket, head) => {
// connect to an origin server
const srvUrl = url.parse(`http://${req.url}`);
const srvSocket = net.connect(srvUrl.port, srvUrl.hostname, () => {
cltSocket.write('HTTP/1.1 200 Connection Established\r\n' +
'Proxy-agent: Node.js-Proxy\r\n' +
'\r\n');
srvSocket.write(head);
srvSocket.pipe(cltSocket);
cltSocket.pipe(srvSocket);
});
});
// now that proxy is running
proxy.listen(1337, '127.0.0.1', () => {
// make a request to a tunneling proxy
const options = {
port: 1337,
hostname: '127.0.0.1',
method: 'CONNECT',
path: 'www.google.com:80'
};
const req = http.request(options);
req.end();
req.on('connect', (res, socket, head) => {
console.log('got connected!');
// make a request over an HTTP tunnel
socket.write('GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n');
socket.on('data', (chunk) => {
console.log(chunk.toString());
});
socket.on('end', () => {
proxy.close();
});
});
});
const http = require('http');
const app = require('./app');
const port = process.env.PORT || 3000;
const server = http.createServer();
server.listen(port);
As far I could extract from code, the thing that is most probably happening in your server.js is that your server is waiting for some request. And you have nothing in your code handle requests.
I think you have to call the require function to return the actual router object, try to change this line
from: const productRoutes = require('./api/routes/products');
to: const productRoutes = require('./api/routes/products')();

Start a proxy server with nodejs so that it serves requests preprended with "/wps_proxy/wps_proxy?url="

I want to start a proxy server with node.js so that it serves requests preprended with "/wps_proxy/wps_proxy?url=". I want it so I can use the wps-js library of north52 (check the installation tips) . I have already a server where I run my application.
What I did try until now is :
the server.js file
var express = require('express');
var bodyParser = require('body-parser');
var fs = require('fs');
var path = require("path");
var app = express();
app.use(express.static(__dirname + '/' + 'public'));
var urlencodedParser = bodyParser.urlencoded({ extended: false });
//****** this is my try ******************************
app.get('/wps_proxy/wps_proxy',function (req,res){
res.sendfile(__dirname + '/' + 'public/wps_proxy/wps-js/target/wps-js-0.1.2-SNAPSHOT/example.html');
if(req.query !== undefined){//because it enters sometimes without url
var http = require('http');
//Options to be used by request
var options = {
host:"geostatistics.demo.52north.org",//fixed given data
port:"80",
path:"/wps/WebProcessingService"
};
var callback = function(response){
var dat = "";
response.on("data",function(data){
dat+=data;
});
response.on("end", function(){
res.end(dat)
})
};
//Make the request
var req = http.request(options,callback);
req.end()
}
})
var ipaddress = process.env.OPENSHIFT_NODEJS_IP||'127.0.0.1';
var port = process.env.OPENSHIFT_NODEJS_PORT || 8080;
app.set('port', port);
app.listen(app.get('port'),ipaddress, function() {
console.log( 'Server started on port ' + app.get('port'))
})
//***************************************
but its not working.. I think that the data are not sent back correctly..
This is a live example of what I want to do.. http://geoprocessing.demo.52north.org/wps-js-0.1.1/
and this is a live example of my application (check the console for errors) http://gws-hydris.rhcloud.com/wps_proxy/wps_proxy
I did find my answer from this post How to create a simple http proxy in node.js? so the way i solve it was:
app.get('/wps_proxy/wps_proxy',function (req,res){
var queryData = url.parse(req.url, true).query;
if (queryData.url) {
request({
url: queryData.url
}).on('error', function(e) {
res.end(e);
}).pipe(res);
}
else {
res.end("no url found");
}
})

Resources