Like any kind of apps, there are difficult issues to solve when we write Node apps.
In this article, we’ll look at some solutions to common problems when writing Node apps.
Use the Middleware to Check the Authorization Before Entering Each Route in Express
We can add a middleware to a route to check for the proper credentials before entering a route.
For instance, we can write:
const protectedMiddlewares = [authChecker, fetchUser];
const unprotectedMiddlewares = [trackVisistorCount];
app.get("/", unprotectedMiddlewares, (req, res) => {
//...
})
app.get("/dashboard", protectedMiddlewares, (req, res) => {
// ...
})
app.get("/auth", unprotectedMiddlewares, (req, res) => {
//...
})
app.put("/auth", unprotectedMiddlewares, (req, res) => {
//...
})
We have an array of middleware for the protected dashboard
route.
And we have an array of middleware for the unprotected routes.
A middleware may look like the following:
const authChecker = (req, res, next) => {
if (req.session.auth || req.path === '/auth') {
next();
} else {
res.redirect("/auth");
}
}
We have the authChecker
middleware that checks the path of the route and the session.
If there’s a session set, then we call the next middleware which should lead to a protected route handler in the end.
Otherwise, we redirect to the auth
route.
Testing Requests that Redirect with Mocha and Supertest in Node
To test requests that redirect to another route with Supertest running in the Mocha test runner, we can write;
it('should log out the user', (done) => {
request(app)
.post('/login')
.type('form')
.field('user', 'username')
.field('password', 'password')
.end((err, res) => {
if (err) { return done(err); }
request(app)
.get('/')
.end((err, res) => {
if (err) { return done(err); }
res.text.should.include('profile');
done();
});
});
});
We test a login
route for redirection by checking the response text in the second end
callback.
To do that, we made a POST request with the username and password.
Then that callback is called after the redirect is done.
We can get the text from the response to see if it’s the text in the profile
route.
Send Additional HTTP Headers with Express
We can send whatever response headers we want with the setHeader
method of the response object.
For instance, we can write:
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
return next();
});
We set the Access-Control-Allow-Origin
to *
to allow requests from all origins.
Working with Sessions in Express
To work with sessions in an Express app, we can use the expression-middleware.
For instance, we can use it by writing:
const express = require('express');
const session = require('express-session');
const app = express();
app.use(session({
resave: false,
saveUninitialized: false,
secret: 'secret'
}));
app.get('/', (req, res) => {
if (req.session.views) {
++req.session.views;
} else {
req.session.views = 1;
}
res.send(`${req.session.views} views`);
});
app.listen(3000);
We used the express-session
package with a few options.
session
is a function that returns a middleware to let us work with sessions.
resave
means we don’t save a session if it’s not modified is it’s false
.
saveUninitialized
means that we don’t create a session until something is stored if it’s false
.
secret
is the secret for signing the sessions.
Then we can store whatever data we want in the req.session
property.
It’ll persist until the session expires.
We just keep increasing the views
count as we hit the /
route.
The default is the memory store, which should only be used if we don’t have multiple instances.
Otherwise, we need to use persistent sessions.
Get the List of Connected Clients Username using Socket.io
We can get the list of clients connected to a namespace or not by using the clients
method.
For instance, we can write:
const clients = io.sockets.adapter.rooms[roomId];
for (const clientId of Object.keys(clients)) {
console.log(clientId);
const clientSocket = io.sockets.connected[clientId];
}
We get an object with the client IDs as the keys with the io.socket.adapter.rooms
object.
roomId
is the ID of the room we’re in.
Then we can get the socket for the client with the io.socket.connected
object.
Conclusion
We can get the clients with Socket.io.
Also, we can write our own middlewares to check for credentials before proceeding to the route.
express-session lets us work with sessions in our Express app.
We can test redirects with Supertest by checking the response content in the end
callback.