Chapters of Frontend Dev থেকে Full-Stack Backend

Week 1 - API FoundationChapter 3 of 282 min read

Englishবাংলা

Middleware গভীরভাবে - একটা request-এর পুরো যাত্রা

Built-in, third-party আর custom middleware, req object-এ data পাঠানো, route-level middleware

আগের পর্বে middleware-এর ধারণাটা এসেছে। আজ সেটাকে আরেকটু গভীরে দেখি, কারণ interview-তে 'middleware কীভাবে কাজ করে' প্রশ্নটা প্রায় নিশ্চিত। একটা request server-এ ঢোকার পর থেকে response যাওয়া পর্যন্ত যা যা ঘটে, তার প্রায় সবই middleware-এর হাতে।

Express-এ middleware তিন রকমের হয়। Built-in - যেমন express.json(), যেটা না থাকলে req.body সবসময় undefined আসবে। Third-party - যেমন cors বা morgan। আর custom - যেটা আপনি নিজে লিখবেন, যেমন auth check বা role check।

Middleware থেকে controller-এ data পাঠানো

একটা সুন্দর pattern হলো: auth middleware token থেকে user বের করে req.user-এ রেখে দেয়, তারপর controller সেই user ব্যবহার করে। এতে প্রতিটা controller-এ বারবার token decode করার দরকার পড়ে না।

function requireAuth(req, res, next) {
  const token = req.headers.authorization?.split(" ")[1];
  if (!token) return res.status(401).json({ success: false, message: "Login required" });

  const payload = verifyToken(token); // { id, role }
  req.user = payload;
  next();
}

// শুধু এই route-এই auth লাগবে
router.get("/profile", requireAuth, profileController);
router.post("/orders", requireAuth, requireRole("user"), createOrder);

লক্ষ্য করুন - middleware route level-এও বসানো যায়। সব route-এ auth লাগে না; যেখানে লাগে শুধু সেখানেই বসান। আরেকটা ব্যাপার: একটা middleware চাইলে chain এখানেই থামিয়ে দিতে পারে - যেমন login না থাকলে 401 পাঠিয়ে দেওয়া। Response পাঠিয়ে দিলে next() ডাকার দরকার নেই, বরং ডাকলেই ভুল হবে।

Async middleware-এর ফাঁদ

Middleware যদি async হয় আর ভেতরে error হয়, Express নিজে থেকে সেটা ধরতে পারে না (Express 4-এ)। হয় try/catch দিয়ে next(err) পাঠাতে হবে, নয়তো একটা ছোট wrapper ব্যবহার করতে হবে। এই একটা লাইনের wrapper পুরো project-এর সব controller-কে নিরাপদ করে দেয়।

const asyncHandler = (fn) => (req, res, next) => {
  Promise.resolve(fn(req, res, next)).catch(next);
};

// ব্যবহার
router.get("/users", asyncHandler(async (req, res) => {
  const users = await userService.getAll();
  res.json({ success: true, data: users });
}));

সবাই যে ভুলটা করে

সবচেয়ে চোখে পড়া ভুল: express.json() routes-এর পরে বসানো। তখন সব POST request-এ req.body undefined আসে, আর developer ঘণ্টার পর ঘণ্টা খুঁজে বেড়ায় কোথায় ভুল। Body parser সবসময় routes-এর আগে।

আজকের Practice

আপনার project-এ requireAuth middleware লিখুন (আপাতত token শুধু header-এ আছে কিনা check করুন, আসল JWT পরের পর্বগুলোতে আসবে)। একটা protected route বানিয়ে Postman বা curl দিয়ে token ছাড়া আর token দিয়ে - দুইভাবেই test করুন।

Interview-এ কীভাবে বলবেন

Middleware হলো request pipeline-এর ধাপ - প্রতিটা ধাপ হয় next() ডেকে এগিয়ে দেয়, নয়তো response পাঠিয়ে chain থামিয়ে দেয়। আমি auth-এর মতো cross-cutting কাজ middleware-এ রাখি, আর token থেকে পাওয়া user তথ্য req.user-এ রেখে controller-দের কাজ হালকা রাখি।

All chapters of Frontend Dev থেকে Full-Stack Backend