An Overview of Middlewares

An Overview of Middlewares

An overview of Middleware in Web Development with Mongoose

Middlewares are a powerful concept in web development that allows for the separation of concerns and a more modular design. They act as intermediaries between different parts of an application, handling shared functionality such as routing, authentication, logging, error handling, and data validation. In this blog post, we will take a closer look at middleware and explore how it can be used in web applications, with a specific focus on Mongoose middleware.

One of the most common uses of middleware is to handle routing and request handling in a web application. For example, a middleware might be responsible for parsing incoming requests and determining which code should be executed to handle that request. This allows developers to write clean, modular code that is easy to maintain. Here is an example of a basic middleware that parses incoming requests and logs the request method and path:

app.use((req, res, next) => {
    console.log(`${req.method} request to ${req.path}`);
    next();
});

Another use of middleware is to handle authentication and authorization. For example, a middleware might be used to check if a user is logged in and has the appropriate permissions to access a particular part of an application. This allows developers to write secure code that is protected against unauthorized access. Here is an example of a middleware that checks for a valid JSON web token and returns an error if the web token is invalid:

app.use((req, res, next) => {
    const token = req.headers.authorization;
    if (!token) return res.status(401).send('Access denied. No token provided.');

    try {
        const decoded = jwt.verify(token, process.env.TOKEN_SECRET);
        req.user = decoded;
        next();
    } catch (ex) {
        res.status(400).send('Invalid token.');
    }
});

Middleware can also be used to handle other common functionality such as logging, error handling, and data validation. By using middleware for these tasks, developers can write code that is focused on the core functionality of the application, rather than being bogged down by boilerplate code.

In Mongoose, middlewares are also an important concept and can be used to handle database operations such as validating data before saving it or handling database errors. Mongoose middlewares are added to the schema and are executed before or after certain operations such as save(), update(), or findOneAndUpdate(). Here is an example of a Mongoose middleware that validates the data before saving it to the database:

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true,
        minlength: 5,
        maxlength: 50
    },
    email: {
        type: String,
        required: true,
        unique: true,
        minlength: 5,
        maxlength: 255
    },
    password: {
        type: String,
        required: true,
        minlength: 5,
        maxlength: 1024
    }
});

userSchema.pre('save', function (next) {
    const user = this;
    if (!user.isModified('password')) return next();

    bcrypt.genSalt(10, (err, salt) => {
    if (err) return next(err);

        bcrypt.hash(user.password, salt, (err, hash) => {
            if (err) return next(err);
            user.password = hash;
            next();
        });
    });
});

const User = mongoose.model('User', userSchema);

module.exports = User;

This middleware uses the bcrypt library to hash the user's password before saving it to the database. The middleware checks if the password has been modified, and if it hasn't, it proceeds to the next step. If it is modified, it generates a new salt, hashes the password, saves it to the user object and continues to the next step.

In summary, middlewares are a powerful tool for web developers, allowing them to write clean, modular, and maintainable code. They are especially useful for handling common functionality such as routing, authentication, and error handling, allowing developers to focus on the core functionality of their application.

Mongoose middlewares also provide a way to handle database operations, such as: validating data before saving it or handling database errors. By understanding how to use middleware, developers can create web applications that are easy to maintain and scalable.