ASP.NET Core-এ Middleware-গুলো একটির পর একটি সারিবদ্ধভাবে সাজানো থাকে, যাকে আমরা Pipeline বলি। যখন ব্রাউজার থেকে কোনো Request আসে, তখন সেটি প্রথম Middleware-এ প্রবেশ করে। প্রথম Middleware তার কাজ শেষ করে চাইলে পরবর্তী Middleware-এর কাছে Request-টি পাঠিয়ে দিতে পারে। এই প্রক্রিয়াটিকেই বলা হয় Middleware Chaining

মূল বৈশিষ্ট্য:

  • Sequential Execution: Middleware গুলো যে ক্রমানুসারে (Order) রেজিস্টার করা হয়, ঠিক সেই ক্রমেই এক্সিকিউট হয়।
  • Two-way Journey: Request একবার Pipeline-এর ভেতর দিয়ে শেষ পর্যন্ত যায় (Incoming path), আবার শেষ থেকে শুরুর দিকে ফিরে আসে (Outgoing path)।

২. app.Use বনাম app.Run

Middleware তৈরি করার জন্য আমরা প্রধানত দুটি মেথড ব্যবহার করি:

ফিচারapp.Useapp.Run
PurposeChaining করার জন্য ব্যবহৃত হয়।Pipeline শেষ বা Terminate করার জন্য ব্যবহৃত হয়।
Parametersদুটি প্যারামিটার নেয়: HttpContext এবং next (RequestDelegate)।একটি প্যারামিটার নেয়: HttpContext
Next Callচাইলে পরবর্তী Middleware-কে কল করতে পারে।পরবর্তী কোনো Middleware-কে কল করতে পারে না।

৩. Middleware Chaining ইমপ্লিমেন্টেশন (C# Code)

ধরা যাক, আমরা তিনটি Middleware ব্যবহার করব। প্রথম দুটি হবে app.Use এবং শেষেরটি হবে app.Run (যাকে Terminal Middleware বলা হয়)।

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
 
// Middleware 1
app.Use(async (context, next) => 
{
    await context.Response.WriteAsync("Hello from Middleware 1\n");
    // পরবর্তী Middleware-কে কল করা হচ্ছে
    await next(context); 
    // Middleware 2 থেকে ফেরার পর নিচের লাইনটি কাজ করবে
    await context.Response.WriteAsync("Back in Middleware 1\n");
});
 
// Middleware 2
app.Use(async (context, next) => 
{
    await context.Response.WriteAsync("Hello from Middleware 2\n");
    // পরবর্তী Middleware-কে কল করা হচ্ছে
    await next(context); 
});
 
// Middleware 3 (Terminal Middleware)
app.Run(async (context) => 
{
    await context.Response.WriteAsync("Hello from Middleware 3 (The End)\n");
});
 
app.Run();
 

কোড বিশ্লেষণ:

  • next(context): এটি একটি Delegate যা পরবর্তী Middleware-কে নির্দেশ করে। এটি কল করলে কন্ট্রোল পরের ধাপে চলে যায়।
  • Context Passing: লক্ষ্য করুন, next মেথড কল করার সময় আমাদের context পাস করতে হচ্ছে। কারণ পরবর্তী Middleware-এর কাজ করার জন্য এই HTTP Context-টি প্রয়োজন।

৪. Short-circuiting কি এবং কেন প্রয়োজন?

সব সময় যে আমাদের পরবর্তী Middleware-কে কল করতে হবে, এমন কোনো বাধ্যবাধকতা নেই। যদি কোনো Middleware সিদ্ধান্ত নেয় যে সে আর রিকোয়েস্ট সামনে পাঠাবে না, তবে তাকে Short-circuiting বলা হয়।

উদাহরণ: ধরুন আপনি একটি Static File (যেমন: image.jpg) রিকোয়েস্ট করেছেন। যদি StaticFileMiddleware ফাইলটি খুঁজে পায়, তবে সে ফাইলটি রিটার্ন করে দেবে এবং পরবর্তী Authorization বা Routing Middleware-এ আর রিকোয়েস্ট পাঠাবে না।

Conditional Chaining-এর উদাহরণ:

app.Use(async (context, next) => 
{
    if (context.Request.Query.ContainsKey("stop")) 
    {
        await context.Response.WriteAsync("Terminated early!");
    }
    else 
    {
        await next(context);
    }
});
 

৫. ডিব্যাগিং ও এক্সিকিউশন অর্ডার

যখন আপনি কোডটি রান করবেন, তখন ব্রাউজারে আউটপুট নিচের মতো দেখাবে:

  1. Hello from Middleware 1
  2. Hello from Middleware 2
  3. Hello from Middleware 3 (The End)
  4. Back in Middleware 1

গুরুত্বপূর্ণ নোট: ট্রান্সক্রিপ্টে উল্লেখ করা হয়েছে যে ব্রাউজার থেকে রিকোয়েস্ট দিলে অনেক সময় ডাবল ব্রেকপয়েন্ট হিট করে। এটি হয় কারণ আধুনিক ব্রাউজারগুলো স্বয়ংক্রিয়ভাবে /favicon.ico ফাইলের জন্য একটি আলাদা রিকোয়েস্ট পাঠায়। এটি নিয়ে চিন্তিত হওয়ার কিছু নেই।


৬. Best Practices ও সাধারণ ভুল

✅ Best Practices:

  • Single Responsibility: প্রতিটি Middleware-কে ছোট রাখুন এবং একটি নির্দিষ্ট কাজ (যেমন: Logging, Authentication, Compression) করতে দিন।
  • Correct Ordering: Middleware-এর ক্রম অত্যন্ত গুরুত্বপূর্ণ। যেমন: Authentication অবশ্যই Authorization-এর আগে থাকতে হবে।
  • Exception Handling: সাধারণত ExceptionHandlingMiddleware সবার আগে রাখা হয় যাতে পরবর্তী যেকোনো স্টেপে এরর হলে তা ধরা যায়।

❌ Common Pitfalls:

  • Forgetting await next(context): যদি আপনি ভুলবশত next কল না করেন, তবে আপনার অ্যাপ্লিকেশন সেখানেই থেমে যাবে এবং ইউজার হয়তো ব্ল্যাংক স্ক্রিন দেখবে।
  • Writing to Response after next: next কল করার পর Response-এ কিছু লিখলে সাবধান থাকতে হবে, কারণ ততক্ষণে হয়তো Response ব্রাউজারে পাঠানো শুরু হয়ে গেছে।

পরবর্তী পদক্ষেপ: যখন আপনার Middleware কোড অনেক বড় হয়ে যায়, তখন সব কোড Program.cs-এ রাখা ঠিক নয়। আমরা পরবর্তী লেসনে শিখব কীভাবে একটি Custom Middleware Class তৈরি করে কোডকে আরও পরিচ্ছন্ন করা যায়।