Search code examples
node.jsexpressmiddleware

Express middleware to configure response


I want to create a middleware that automatically formats my output and returns it in a format that looks like

{
   "successful": "true",
   "message": "Successfully created",
   "data": {
         "name": "Joe",
         "year": 1
    }
}

Currently I'm just returning a json of the data itself (name, year, etc.)

I want to add the "successful", "message", etc.

Here's some snippets of my code below:

routes/student.js

var student_controller = require('../controllers/studentController');
router.get('/list', student_controller.student_list);

controllers/student.js

var Student = require('../models/student');

exports.student_list = function(req, res, next) {
    Student.find()
        .exec(function(err, list_students) {
            if (err) {return next(err);}
            res.json(list_students);
        });
};

app.js

var studentRouter = require('./routes/student');
app.use('/student', studentRouter);

How do I make this middleware, and in which file(s) should I be calling it?


Solution

  • The response can be intercepted by overriding response.json function. By doing so, and adding our custom function, every time, response.json() is called, our intercepting function is triggered.

    middleware/response.filter.js:

    // Response Interceptor Middleware
    export default (request, response, next) => {
        try {
            const oldJSON = response.json;
            response.json = (data) => {
                // For Async call, handle the promise and then set the data to `oldJson`
                if (data && data.then != undefined) {
                    // Resetting json to original to avoid cyclic call.
                    return data.then((responseData) => {
                        // Custom logic/code. -----> Write your logic to add success wrapper around the response
                        response.json = oldJSON;
                        return oldJSON.call(response, responseData);
                    }).catch((error) => {
                        next(error);
                    });
                } else {
                    // For non-async interceptor functions
                    // Resetting json to original to avoid cyclic call.
                    // Custom logic/code.
                    response.json = oldJSON;
                    return oldJSON.call(response, finalResponse);
                }
            }
        } catch (error) {
            next(error);
        }
    }
    

    In the Server.js file, register the middleware:

    // Server.js file
    import externalResponseFilter from "./middleware/response.filter.js:";
    
    // Create Express server
    const app = express();
    
    // Response interceptor - Initialization.
    app.use(externalResponseFilter);
    

    And in the controller where you are returning the response, return with response.json() function instead of response.send().

    Let me know if any additional explanation is required.