Cơ Chế Trung Gian (Middleware)

Tham khảo: https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-8.0

1. Middleware là gì?

Middlewares là các thành phần được lắp ráp vào đường dẫn ứng dụng để xử lý yêu cầu (Request) và phản hồi (Response). Mỗi thành phần:

  • Quyết định xem có chuyển yêu cầu đến thành phần tiếp theo trong đường dẫn hay không.
  • Có thể thực hiện công việc trước hoặc sau thành phần tiếp theo trong đường dẫn.

1.1 Nguyên lý hoạt động của middleware

Nhiều middlewares xếp theo thứ tự tạo thành đường dẫn yêu cầu, dùng để xử lý HTTP request và response. Middleware về cơ bản là một lớp dùng để xử lý HTTP request và response.

Khi HTTP request đi vào đường dẫn yêu cầu, một đối tượng sẽ được tạo ra để mô tả thông tin request và trả lại HTTP response cuối cùng.

Yêu cầu từ một đầu đi vào, theo thứ tự thêm vào qua từng middleware, mỗi middleware đều có thể thực hiện một số thao tác trên yêu cầu rồi chuyển sang middleware tiếp theo hoặc trả về trực tiếp. Đối với phản hồi (HTTP Response) cũng sẽ lặp lại qua các middleware đã đi qua lúc gửi yêu cầu, nhưng theo thứ tự ngược lại.

Lưu ý:

  • Mã trước `next()` sẽ được thực thi ở giai đoạn vào đường dẫn, mã sau `next` sẽ được thực thi ở giai đoạn quay trở lại.
  • Nếu middleware cuối cùng không trả về HTTP Response, sẽ báo lỗi HTTP 404 Not Found.

1.2 Thứ tự của middleware

Dưới đây là cấu trúc hoàn chỉnh của ASP.NET Core MVC và Razor Pages ứng dụng xử lý yêu cầu. "Điểm kết thúc" middleware trong hình thực hiện lọc đường dẫn tương ứng với loại ứng dụng (MVC hoặc Razor Pages).

public void Setup(IWebAppBuilder app, IWebHostEnv env)
{
    if (env.IsDev())
    {
        app.UseErrorPage();
    }
    else
    {
        app.UseGlobalErrorHandler("/Home/Error");
        app.UseHsts();
    }
    
    app.UseHttpsRedir();
    app.UseStaticFiles();
    app.UseRouting();
    app.UseAuth();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

1.3 Các middleware phổ biến

  • Tệp tĩnh middleware: app.UseStaticFiles();
  • Routing middleware: app.UseRouting();
  • Xác thực middleware: app.UseAuthentication();
  • Phân quyền middleware: app.UseAuthorization();
  • CORS middleware: app.UseCors("AllowAllPolicy");
  • Hội thoại middleware: app.UseSession();
  • Nén phản hồi middleware: app.UseResponseCompression();
  • Xử lý ngoại lệ middleware: app.UseExceptionHandler("/Home/Error");
  • Chuyển hướng HTTPS middleware: app.UseHttpsRedirection();
  • HSTS middleware: app.UseHsts();
  • Điểm kết thúc middleware:
    app.Run(async ctx =>
    {
    await ctx.Response.WriteAsync("Hello, World!");
    });
    

2. Map, Use, Run

Map: Dùng để xác định đường dẫn có thể xử lý những yêu cầu nào.

Use và Run: Dùng để xác định đường dẫn, một đường dẫn bao gồm nhiều Use và một Run, mỗi Use giới thiệu một middleware, còn Run thực hiện logic cốt lõi cuối cùng.

2.1 Map phân nhánh đường dẫn middleware

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Map("/branch1", HandleBranchTest1);

app.Map("/branch2", HandleBranchTest2);

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

static void HandleBranchTest1(IWebAppBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Branch Test 1");
    });
}

static void HandleBranchTest2(IWebAppBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Branch Test 2");
    });
}
Yêu cầuPhản hồi
localhost:1234Hello from non-Map delegate.
localhost:1234/branch1Branch Test 1
localhost:1234/branch2Branch Test 2
localhost:1234/branch3Hello from non-Map delegate.

2.2 Sử dụng Use liên kết

public void Setup(IWebAppBuilder app, IWebHostEnv env)
{
    app.Use(async (context, next) =>
    {
        await context.Response.WriteAsync("MiddleWare(1)-In\n");
        await next();
        await context.Response.WriteAsync("MiddleWare(1)-Out\n");
    });
    app.Use(async (context, next) =>
    {
        await context.Response.WriteAsync("MiddleWare(2)-In\n");
        await next();
        await context.Response.WriteAsync("MiddleWare(2)-Out\n");
    });
    
    app.Run(async (context) =>
    {
        await context.Response.WriteAsync("MiddleWare(3)\n"); 
    });
}

3. Tùy chỉnh Middleware

3.1 Use ủy nhiệm

app.Use(async (context, next) =>
{
    var langQuery = context.Request.Query["lang"];
    if (!string.IsNullOrWhiteSpace(langQuery))
    {
        var culture = new CultureInfo(langQuery);

        CultureInfo.CurrentCulture = culture;
        CultureInfo.CurrentUICulture = culture;
    }

    await next(context);
});

app.Run(async (context) =>
{
    await context.Response.WriteAsync(
        $"CurrentCulture.DisplayName: {CultureInfo.CurrentCulture.DisplayName}");
});

3.2 Tùy chỉnh lớp Middleware

using System.Globalization;

namespace Middleware.Example;

public class RequestLangMiddleware
{
    private readonly RequestDelegate _next;

    public RequestLangMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var langQuery = context.Request.Query["lang"];
        if (!string.IsNullOrWhiteSpace(langQuery))
        {
            var culture = new CultureInfo(langQuery);

            CultureInfo.CurrentCulture = culture;
            CultureInfo.CurrentUICulture = culture;
        }

        await _next(context);
    }
}
public static class RequestLangMiddlewareExtensions
{
    public static IWebAppBuilder UseRequestLang(
        this IWebAppBuilder builder)
    {
        return builder.UseMiddleware<RequestLangMiddleware>();
    }
}
app.UseRequestLang();

4. Sự khác biệt giữa Middleware và Filter

- Middleware: Là thành phần được lắp ráp vào đường dẫn ứng dụng để xử lý HTTP request và response.

- Filter: Là thành phần trong ASP.NET Core MVC hoặc Web API ứng dụng để chặn thực thi phương thức hành động.

Thẻ: ASP.NET Core middleware Routing Security performance optimization

Đăng vào ngày 31 tháng 5 lúc 22:27