React এর হাতেখড়ি সিরিজে আমরা ProtectedPage কম্পোনেন্ট বানিয়ে পেজ প্রোটেক্ট করতাম — কিন্তু সমস্যা হলো, পেজ প্রথমে লোড হয়ে যায়, তারপর চেক হয় ইউজার লগইন করা কিনা। Next.js-এর Middleware দিয়ে এই চেক পেজে পৌঁছানোরও আগে করা যায় — এই পর্বে শিখব কীভাবে।
Middleware কী?
Middleware হলো একটা ফাংশন, যা প্রতিটা (বা নির্দিষ্ট) রিকোয়েস্ট Next.js-এর পেজ পর্যন্ত পৌঁছানোর আগেই চলে। এটা রিকোয়েস্ট দেখতে পারে, চাইলে সেটাকে অন্য কোথাও রিডাইরেক্ট করতে পারে, বা আটকে দিতে পারে — Cloudflare এর হাতেখড়ি পর্ব ১২-এর WAF Custom Rule-এর ধারণার মতোই, কিন্তু Next.js-এর নিজস্ব লেয়ারে।
middleware.js — প্রজেক্টের রুটে
এই ফাইলটা app/-এর ভেতরে না, বরং প্রজেক্টের একদম রুটে (app/-এর পাশে) থাকে।
my-first-app/ ├── app/ ├── middleware.js ← এখানে, app/-এর বাইরে └── package.json
সবচেয়ে সহজ Middleware
// middleware.js
import { NextResponse } from "next/server";
export function middleware(request) {
console.log("রিকোয়েস্ট এলো:", request.nextUrl.pathname);
return NextResponse.next(); // রিকোয়েস্টকে যেতে দাও
}
NextResponse.next() মানে — "সবকিছু ঠিক আছে, স্বাভাবিকভাবে এগিয়ে যাও"। এটাই ডিফল্ট আচরণ, কিন্তু middleware লেখার সময় সবসময় স্পষ্টভাবে লিখতে হয়।
Auth চেক — Cookie দিয়ে
Firebase এর হাতেখড়ি পর্ব ৩-এর মতোই একটা "কি লগইন করা আছে" চেক, কিন্তু এখানে ব্রাউজারের কুকি পড়ে, ঠিক পর্ব ৫-এর cookies()-এর মতোই একটা ধারণা।
// middleware.js
import { NextResponse } from "next/server";
export function middleware(request) {
const sessionCookie = request.cookies.get("session");
// /dashboard-এ যেতে চাইলে, কিন্তু session না থাকলে
if (request.nextUrl.pathname.startsWith("/dashboard") && !sessionCookie) {
return NextResponse.redirect(new URL("/login", request.url));
}
return NextResponse.next();
}
এখানে ইউজার /dashboard-এ যাওয়ার চেষ্টা করলে, পেজের কোনো কোডই এখনো চলেনি — middleware সবার আগে চেক করে নিয়েছে, আর সেশন না থাকলে সরাসরি /login-এ পাঠিয়ে দিয়েছে।
matcher — কোন রুটে চলবে
ডিফল্টভাবে middleware প্রতিটা রিকোয়েস্টে চলে — এমনকি ছবি, CSS ফাইলেও। এটা অপচয়, তাই config.matcher দিয়ে নির্দিষ্ট করে দেওয়া হয় কোন পাথগুলোতেই শুধু middleware চলবে।
// middleware.js
import { NextResponse } from "next/server";
export function middleware(request) {
const sessionCookie = request.cookies.get("session");
if (!sessionCookie) {
return NextResponse.redirect(new URL("/login", request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ["/dashboard/:path*", "/profile/:path*"], // শুধু এই রুটগুলোতে চলবে
};
:path* মানে — /dashboard, /dashboard/settings, /dashboard/books/1 — সবগুলো ম্যাচ করবে, ঠিক পর্ব ২-এর ডাইনামিক রুটের মতোই একটা প্যাটার্ন।
Firebase Auth-এর সাথে মেলানো — একটা বাস্তব চ্যালেঞ্জ
একটা গুরুত্বপূর্ণ পার্থক্য — Firebase এর হাতেখড়ি পর্ব ৩-এর onAuthStateChanged শুধু ব্রাউজারে কাজ করে, Middleware চলে সার্ভারে। তাই Firebase Auth-এর সাথে Middleware ব্যবহার করতে হলে, লগইনের সময় একটা সেশন কুকি বসাতে হয় (সাধারণত একটা API Route দিয়ে, যা Firebase-এর ID Token যাচাই করে একটা কুকি সেট করে) — সরাসরি Firebase-এর ক্লায়েন্ট state middleware থেকে দেখা যায় না।
// একটা সরলীকৃত ধারণা — লগইন হলে কুকি বসানো (Server Action বা API Route-এ)
"use server";
import { cookies } from "next/headers";
export async function loginAndSetSession(idToken) {
// এখানে বাস্তবে Firebase Admin SDK দিয়ে idToken যাচাই করা হতো
cookies().set("session", idToken, { httpOnly: true, secure: true });
}
এই টপিকটা একটা পূর্ণাঙ্গ Auth ইন্টিগ্রেশন প্যাটার্ন, যা পর্ব ১০-এ Firebase-এর সাথে জোড়া লাগানোর সময় আরও বিস্তারিত দেখব — আপাতত মূল ধারণাটা মনে রাখা যথেষ্ট: middleware সার্ভারে চলে, তাই এটাকে সার্ভারে-পড়া-যায় এমন কিছু (কুকি) দিয়েই কাজ করতে হয়।
অন্যান্য ব্যবহার — শুধু Auth না
- A/B টেস্টিং — এলোমেলোভাবে ইউজারদের দুটো ভিন্ন ভার্সনে ভাগ করা
- Geo-based রিডাইরেক্ট — দেশ অনুযায়ী ভিন্ন ভাষার পেজে পাঠানো (
request.geoদিয়ে) - Rate Limiting — Cloudflare এর হাতেখড়ি পর্ব ১২-এর ধারণারই একটা Next.js-লেয়ার সংস্করণ, যদিও বড় স্কেলে Cloudflare-এর নিজস্ব সিস্টেমই বেশি কার্যকর
ইন্টারেক্টিভ — Middleware সিদ্ধান্ত সিমুলেশন
নিচে বিভিন্ন পরিস্থিতিতে Middleware কী সিদ্ধান্ত নেবে দেখো।
ভালো অভ্যাস
- সবসময় matcher নির্দিষ্ট করুন — প্রতিটা রিকোয়েস্টে middleware চালানো অপ্রয়োজনীয় ও ধীর
- Middleware-এ ভারী কাজ (ডেটাবেজ query) এড়িয়ে চলুন — এটা প্রতিটা রিকোয়েস্টে চলে, তাই দ্রুত হওয়া জরুরি; শুধু কুকি/হেডার চেক করুন
- Middleware-কে একমাত্র নিরাপত্তা স্তর হিসেবে ধরবেন না — Firebase এর হাতেখড়ি পর্ব ৮-এর Security Rules-এর মতো, ডেটাবেজ পর্যায়েও সবসময় আলাদা সুরক্ষা রাখা উচিত
নিজে চেষ্টা করো
Exercise:
- একটা
middleware.jsবানাও যা প্রতিটা রিকোয়েস্টের pathconsole.logকরে। - একটা
/dashboardরুট প্রোটেক্ট করো — কুকি না থাকলে/login-এ রিডাইরেক্ট করাও। config.matcherযোগ করো, দেখো middleware শুধু নির্দিষ্ট রুটেই চলছে কিনাconsole.logদিয়ে যাচাই করো।- ব্রাউজারের DevTools থেকে ম্যানুয়ালি একটা কুকি সেট করে, তারপর প্রোটেক্টেড রুটে গিয়ে দেখো এখন অ্যাক্সেস মিলছে কিনা।
পরের পর্বে যা থাকছে
পরের পর্বে আমরা শিখব Next.js + Firebase — Firebase Auth ও RTDB এই সিরিজে যা শিখেছি তার সাথে কীভাবে সম্পূর্ণভাবে ইন্টিগ্রেট করতে হয়, সেশন কুকি সেটআপসহ।