DEV Community

indrasisdatta
indrasisdatta

Posted on

Using Middleware to Format Express API Response

Middleware in Express allows you to customize and enhance the request-response cycle. One powerful application of middleware is to format the response before it is sent back to the client.

We'll explore how to create a middleware function to expose only specific user fields and restrict fields like password, _id etc.

Route

import { Router } from "express";
const router = Router();
router.get("/profile", getUserProfile, UserResponse);
Enter fullscreen mode Exit fullscreen mode

Controller

We are fetching user details based on request POST param userId.

user returns Mongoose User but we don't want to expose all fields in our response. Therefore, we can assign the response json to res.locals so that it can be passed on to the middleware.
Ref:

/* User profile details */
export const getUserProfile = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  try {
    const { userId } = req;
    if (!userId ) {
      return res.status(400).json({
        status: 0,
        data: null,
        error: "User not found",
      });
    }
    const user = User.findById(userId);
    // Store data here, which can be accessed in middleware
    res.locals.apiResponse = {
      status: 1,
      data: user,
    };
    next(); // this is important so that it's forwarded to UserResponse middleware
  } catch (error) {
    res.status(500).json({ status: API_STATUS.ERROR, error });
  }
};
Enter fullscreen mode Exit fullscreen mode

Creating the middleware

import { NextFunction, Request, Response } from "express";

export const UserResponse = (
  req: Request,
  res: Response,
  Next: NextFunction
) => {
  try {
    if (res.locals?.apiResponse) {
      if (
        res.locals.apiResponse?.status == 1 &&
        typeof res.locals.apiResponse?.data === "object" &&
        res.locals.apiResponse?.data.constructor.modelName === "User"
      ) {
        const tempUser = res.locals.apiResponse?.data.toObject();
        /* Delete all private fields so that only necessary fields are exposed */
        delete tempUser._id;
        delete tempUser.createdAt;
        delete tempUser.updatedAt;
        delete tempUser.password;
        delete tempUser?.__v;
        return res.status(200).json({
          status: res.locals.apiResponse?.status,
          data: tempUser,
        });
      }
    }
    return res.status(200).json(res.locals);
  } catch (error) {
    res.status(500).json({ status: 0, error });
  }
};

Enter fullscreen mode Exit fullscreen mode

Top comments (0)