Middleware Pipeline

লেসন ২০ / ৫০

Middleware কী?

HTTP request pipeline-এর প্রতিটি step। প্রতিটি middleware next-কে call করে অথবা response লিখে short-circuit করে।

Pipeline Order ⭐

app.UseExceptionHandler("/error");     // 1
app.UseHttpsRedirection();              // 2
app.UseStaticFiles();                   // 3
app.UseRouting();                       // 4
app.UseCors();                          // 5
app.UseAuthentication();                // 6
app.UseAuthorization();                 // 7
app.MapControllers();                   // 8 (terminal)

Inline Middleware

app.Use(async (context, next) => {
    Console.WriteLine($"Before: {context.Request.Path}");
    await next();
    Console.WriteLine($"After: {context.Response.StatusCode}");
});

// Terminal — next call করে না
app.Run(async ctx => await ctx.Response.WriteAsync("Hello"));

Custom Middleware Class ⭐

public class RequestLoggingMiddleware {
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestLoggingMiddleware> _logger;

    public RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger) {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext ctx) {
        var sw = Stopwatch.StartNew();
        await _next(ctx);
        sw.Stop();
        _logger.LogInformation("{Method} {Path} → {Code} ({Ms}ms)",
            ctx.Request.Method, ctx.Request.Path,
            ctx.Response.StatusCode, sw.ElapsedMilliseconds);
    }
}

// Register
app.UseMiddleware<RequestLoggingMiddleware>();

API Key Middleware

public class ApiKeyMiddleware {
    private readonly RequestDelegate _next;
    private const string KEY_HEADER = "X-API-Key";
    public ApiKeyMiddleware(RequestDelegate next) => _next = next;

    public async Task InvokeAsync(HttpContext ctx, IConfiguration cfg) {
        if (!ctx.Request.Headers.TryGetValue(KEY_HEADER, out var key)) {
            ctx.Response.StatusCode = 401;
            await ctx.Response.WriteAsync("API key missing");
            return;     // short-circuit
        }
        if (key != cfg["ApiKey"]) {
            ctx.Response.StatusCode = 403;
            await ctx.Response.WriteAsync("Invalid key");
            return;
        }
        await _next(ctx);
    }
}

Map / MapWhen — Branch Pipeline

app.Map("/admin", admin => {
    admin.UseAuthentication();
    admin.UseAuthorization();
    admin.UseMiddleware<AdminAuditMiddleware>();
});

app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/api"), api => {
    api.UseMiddleware<ApiKeyMiddleware>();
});

Built-in Middlewares

  • UseExceptionHandler / UseDeveloperExceptionPage
  • UseHttpsRedirection / UseHsts
  • UseStaticFiles
  • UseRouting / UseEndpoints
  • UseCors
  • UseAuthentication / UseAuthorization
  • UseResponseCaching / UseResponseCompression
  • UseRateLimiter (.NET 7+)