Switching from working node js socket io serialport to node express router how to? - express

I am new to node express (started with node long time ago but didn't do much) and I would like to learn how to use it. I am going through some of my older work and reading lots of tutorials but I just can't seem to get this one working.
I have this app that reads data from some sensors on serial port and sends it to sesors.ejs. I would like to reprogram it in express. I have the sensor reading in terminal but not in ejs.
old (working) app.js
var http = require('http');
var fs = require('fs');
var url = require('url');
var path = require('path');
const { SerialPort } = require('serialport')
const { ByteLengthParser } = require('#serialport/parser-byte-length')
const port = new SerialPort({ path: 'COM4', baudRate: 9600 })
const parser = port.pipe(new ByteLengthParser({ length: 30 }))
var sensors = fs.readFileSync('views/sensors.ejs');
var app = http.createServer(function(req, res){
res.writeHead(200, {'Content-Type':'text/html'});
res.end(sensors);
});
var io = require('socket.io').listen(app);
io.on('connection', function(data){
console.log
});
parser.on('data', function(data){
console.log(data.toString("UTF8"));
io.emit('data', data.toString("UTF8"))
});
app.listen(3000);
old (working) sensors.ejs
<script>
var socket = io();
socket.on('data', function(data){...}
</script>
This works great.
I went through several express routing tutorials but I don't know how to send io data to router.
I have c/p most of the code from old app.js to new sensor.js in routes dir, without fs, app.listen etc. I have c/p sensors.ejs to views folder.
In new app.js I have:
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var sensorsRouter = require('./routes/senzori');
var app = express();
app.set('views', path.join(\__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(\__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/senzori', sensorsRouter);
index.ejs and users.ejs (fetch mysql data) are working (express is installed and working)
Thanks

I have found the solution. If anyone else with my level of "knowledge" needs the solution, here it is:
I have moved reading serial port to bin/www
The only code in sensors.js is:
router.get('/', function(req, res, next) {
res.render('sensors');
});

Related

Jest test does not find provided route

Started working on a new application and decided to write tests from very early stage to avoid any future mistakes. However, little bit struggling I guess with setting up the Jest correctly. I made a follow on few tutorials and documentation, but the result is not the one I'm expecting. What I am trying to do is to make a basic test for creating a user, however I receive and error:
error: Error: cannot POST /register (404)
I get the point that the test can't find the endpoint /register, but I thought that is the point to keep server.js and app.js for supertest, because he will be smart enough to understand the path to this endpoint, which actually is: "/api/v1/auth/register". I want to mark that the registration process works fine trough postman.
Here is the app.js:
require("dotenv").config();
require("express-async-errors");
const express = require("express");
const app = express();
// routers
const authRouter = require("./src/routes/auth/auth.router");
// packages
const morgan = require("morgan");
const fs = require("fs");
const cookieParser = require("cookie-parser");
// middlewares
const errorMiddleware = require("./src/middlewares/errorMiddleware");
app.use(express.json());
app.use(cookieParser(process.env.ACCESS_TOKEN));
app.use(morgan("common", {
stream: fs.createWriteStream("./src/utils/logs/logs.log", {
flags: "a"
})
}));
// endpoints
app.use("/api/v1/auth", authRouter);
app.use(errorMiddleware);
module.exports = app;
Here is the server.js:
const app = require("./app");
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}...`);
});
Here is the auth.test.js:
const request = require("supertest");
const app = require("../../../app");
describe("POST /register", () => {
it("Should create a new user", async () => {
const response = await request(app).post("/register").send({
email: "superemail#gmail.com",
username: "superusername",
password: "superpassword"
});
console.log(response); // I see here the 404 error.
});
});
Not sure if it helps, but here is the router file:
const express = require("express");
const router = express.Router();
const {check} = require("express-validator");
const {registerUserController, loginUserController} = require("../../controllers/auth/auth.controller");
router.post("/register", [
check("email").trim().not().isEmpty().isEmail(),
check("username").trim().not().isEmpty().isString(),
check("password").trim().not().isEmpty().isString().isLength({
min: 6
}).withMessage("Password has to be at least 6 characters long"),
check("firstName").optional().trim().not().isEmpty().isString(),
check("lastName").optional().trim().not().isEmpty().isString(),
check("age").optional().trim().not().isEmpty().isNumeric().isInt({
min: 0
}).withMessage("Age can't be less than 0"),
], registerUserController);
module.exports = router;

How to use vuejs routing with history fallback and expressjs routes

I've been stuck on this for a number of weeks and I can't figure it out. It's driving me crazy... Ive read numerous tutorials and it sounds like it's something that should work!
I have an expressjs server setup and a vuejs app. I want to be able to serve the vuejs routes with history browser mode and I also want to be able to setup server side routes for my api layer.
If I disable the history mode, everything works ok - but I need to enable history mode, so that I can use auth0 library and callbacks. Callbacks do not allow # in the url.
Here is my code:
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const logger = require('morgan');
const history = require('connect-history-api-fallback');
const app = express();
app.use(require('connect-history-api-fallback')())
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(history({
verbose: true
}));
app.get('/api', (req, res) => res.send('Hello World!'))
app.use('/', express.static(path.join(__dirname, 'dist')));
var port = process.env.PORT || 8080;
app.listen(port);
console.log('server started '+ port);
For the code above, the vuejs app is sitting under /dist and all the routes for that one work. But when I try to hit /api - it is also being redirected to the vuejs app.
Any help would be greatly appreciated! I'm at the point where I'm thinking its just not possible.
I was having the same issue. I fixed it by adding app.use(history()) after my api routes, but before app.use('/', express.static(path.join(__dirname, 'dist')));.
So I think for you it'd be like
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const logger = require('morgan');
const history = require('connect-history-api-fallback');
const app = express();
app.use(logger('dev'));
app.use(bodyParser.json());
app.get('/api', (req, res) => res.send('Hello World!'));
app.use(history({
verbose: true
}));
app.use('/', express.static(path.join(__dirname, 'dist')));
var port = process.env.PORT || 8080;
app.listen(port);
console.log('server started '+ port);
This answer helped me: https://forum.vuejs.org/t/how-to-handle-vue-routes-with-express-ones/23522/2

Mean Stack Root Routing is not working

Can someone help me why default route is not working in my Mean App, But the next routing works
Here when I open http://localhost:3000 I am not able to see any output, But I have defined route in route.js which is working
var express = require('express');
var cors = require('cors');
var bodyparser = require('body-parser');
var mongoose = require('mongoose');
var path = require('path');
const port = 3000;
app.get('/', function (req, res) {
res.send('Test');
console.log('Opened the root path');
});
When I open the page with http://localhost:3000/main I am able to see the Output and also log written in the console
const express = require('express');
const router = express.Router();
router.get('/main', function (req, res, next) {
res.send('This is the Admin Landing Page');
});
router.get('/install', function (req, res, next) {
res.send('This is the Install Landing Page');
console.log('Opened the Install path');
});
module.exports = router;
It looks like you the code you pasted is the full version, and it's not runnable because:
You did not declare app variable.
You did not start the http server.
It's really hard to tell the root cause what's wrong of your code. Following codes works for me:
const express = require('express');
const port = 3000;
let app = express();
app.get('/', function (req, res) {
res.send('Test');
console.log('Opened the root path');
});
let server = require('http').createServer(app);
server.listen(port, function() {
console.log('Server started');
});

router vs app in express 4.0

I am learning express js 4.0 and building compact CRUD REST API web application with it. In the tutorial, it shows two ways; using app and using router.
//using router
var router = express.Router();
router.get('/', function(req,res){
res.send('hello, world')
});
//using app
app.get('/', function(req,res){
res.send('hello, world')
});
To me, I feel they work same but I don't know why people use router, I think using app is more simple. Can anybody explain what is difference between them?
It allows for modularity. A lot of people have a routes folder that they keep all their route handlers in. And then in their app.js file, they just do something like app.use(<prefix>, <routes>); after they require their router. It keeps your files smaller and more organized.
Example:
app.js
var express = require('express');
var rootRoutes = require('./routes/index');
var userRoutes = require('./routes/user');
var app = express();
app.use('/', rootRoutes);
app.use('/user', userRoutes);
module.exports = app;
routes/index.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.render('index.jade');
});
router.get('/about', function(req, res) {
res.render('about.jade');
});
module.exports = router;
routes/user.js
var express = require('express');
var router = express.Router();
router.get('/:name', function(req, res) {
var userName = req.params.name;
res.render('user.jade', {
userName: userName
});
});
module.exports = router;

express.js 4 and sockets with express router

I'm trying to create a really simple node API using express.js 4 but I need a few 'realtime' events for which I added socket.io. I'm fairly new to both so I'm likely missing something basic but I can't find good docs/tuts on this.
In the express app (created with the express generator) I have something like this based on simple examples and project docs that I read. This works OK and from client apps, I can send/receive the socket events:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var api = require('./routes/api');
var app = express();
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/api', api);
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
// error handlers omitted
module.exports = app;
but I want to use the sockets from my API routes (in the ./routes/api.js file that I 'require' above). For example, someone might use the API to PUT/POST a resource and I want that broadcast to connected socket.io clients.
I cannot see how to use the 'io' variable or organise the code currently in the io.sockets.on('connection' ... function inside express routes. Here's the ./routes/api.js file:
var express = require('express');
var router = express.Router();
var io = ???;
router.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
io.sockets.emit('update', foo); // how?
});
module.exports = router;
One option is to pass it in to req object.
app.js:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var api = require('./routes/api');
var app = express();
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
// Make io accessible to our router
app.use(function(req,res,next){
req.io = io;
next();
});
app.use('/api', api);
// error handlers omitted
module.exports = app;
./routes/api.js:
var express = require('express');
var router = express.Router();
router.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
req.io.sockets.emit('update', foo);
});
module.exports = router;
I've modified your files a little bit, may you check if it works?
You can pass the io you've defined to your routes like below;
require('./routes/api')(app,io);
I didn't test the Socket.IO parts but there is no syntax error and routes also working.
server.js file:
var express = require('express');
var app = express();
var path = require('path');
var logger = require('morgan');
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
require('./routes/api')(app,io);
console.log("Server listening at port 3000");
api.js:
module.exports = function(app,io) {
app.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
console.log("PUT OK!");
io.sockets.emit('update'); // how?
res.json({result: "update sent over IO"});
});
}
Supposing you want to access the SocketIO from anywhere in your application, not just in the router, you could create a singleton for it. This is what works for me:
//socket-singletion.js
var socket = require('socket.io');
var SocketSingleton = (function() {
this.io = null;
this.configure = function(server) {
this.io = socket(server);
}
return this;
})();
module.exports = SocketSingleton;
Then, you need to configure it using your server:
//server config file
var SocketSingleton = require('./socket-singleton');
var http = require('http');
var server = http.createServer(app);
SocketSingleton.configure(server); // <--here
server.listen('3000');
Finally, use it wherever you want:
//router/index.js
var express = require('express');
var router = express.Router();
var SocketSingleton = require('../socket-singleton');
/* GET home page. */
router.get('/', function(req, res, next) {
setTimeout(function(){
SocketSingleton.io.emit('news', {msg: 'success!'});
}, 3000);
res.render('index', { title: 'Express' });
});
module.exports = router;
One more option is to use req.app.
app.js
const express = require('express');
const path = require('path');
const logger = require('morgan');
const api = require('./routes/api');
const app = express();
const io = require('socket.io').listen(app.listen(3000));
// Keep the io instance
app.io = io;
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
// ...
app.use('/api', api);
module.exports = app;
routes/api.js
const express = require('express');
const router = express.Router();
router.put('/foo', function(req, res) {
/*
* API
*/
// Broadcast the updated foo..
req.app.io.sockets.emit('update', foo);
});
module.exports = router;
Refactored Edudjr's answer.
Change the singleton to create a new instance of socket.io server
const { Server } = require('socket.io');
const singleton = (() => {
this.configure = (server) => this.io = new Server(server)
return this
})();
module.exports = singleton
Initialise your express app, the server and the singleton.
// initialise app
const app = express();
const server = require('http').createServer(app);
// configure socket.io
socket.configure(server)
Then in your router
const socket = require('/utils/socket-singleton');
socket.io.emit('event', {message: 'your message here'})
I think best way is to set io as a property of req, like below:
app.use(function(req,res,next){
req.io = io;
next();
});
app.use('/your-sub-link', your-router);