Middleware là các thành phần phần mềm được lắp ráp vào application pipeline để xử lý request và response.
Mỗi component quyết định có pass request tới component tiếp theo trong pipeline hay không, và có thể thực hiện các action trước và sau khi component tiếp theo được invoke trong pipeline.
Map extensions được dùng như convention để phân nhánh pipeline.
Phương thức mở rộng Map được dùng để match request delegates dựa trên path của request. Map đơn giản chấp nhận một path và một function cấu hình một middleware pipeline riêng biệt.
Trong ví dụ sau, bất kỳ request nào có base path là /maptest sẽ được xử lý bởi pipeline được cấu hình trong phương thức HandleMapTest.
Ví dụ
private static void HandleMapTest(IApplicationBuilder app) {
app.Run(async context => {
await context.Response.WriteAsync("Map Test Successful");
});
}
public void ConfigureMapping(IApplicationBuilder app) {
app.Map("/maptest", HandleMapTest);
}
Ngoài path-based mapping, phương thức MapWhen hỗ trợ predicate-based middleware branching, cho phép xây dựng pipeline riêng biệt một cách linh hoạt.
Bất kỳ predicate kiểu Func<HttpContext, bool> nào cũng có thể dùng để map request tới branch mới của pipeline.
private static void HandleBranch(IApplicationBuilder app) {
app.Run(async context => {
await context.Response.WriteAsync("Branch used.");
});
}
public void ConfigureMapWhen(IApplicationBuilder app) {
app.MapWhen(context => {
return context.Request.Query.ContainsKey("branch");
}, HandleBranch);
app.Run(async context => {
await context.Response.WriteAsync("Hello from main pipeline");
});
}
Maps cũng có thể được nested (lồng nhau):
app.Map("/level1", level1App => {
level1App.Map("/level2a", level2AApp => {
// "/level1/level2a"
});
level1App.Map("/level2b", level2BApp => {
// "/level1/level2b"
});
});
MapWhen vs Map
| Phương thức | Điều kiện match | Use case |
|---|---|---|
| Map | Path prefix (tiền tố đường dẫn) | Phân nhánh theo URL path |
| MapWhen | Predicate (Func<HttpContext, bool>) | Phân nhánh theo điều kiện phức tạp (header, query, claim, v.v.) |
Ví dụ thực tế: Health Check Endpoint
public void Configure(IApplicationBuilder app) {
// Health check endpoint - không cần authentication
app.Map("/health", healthApp => {
healthApp.Run(async context => {
context.Response.ContentType = "application/json";
await context.Response.WriteAsync("{\"status\":\"Healthy\"}");
});
});
// Main pipeline với auth
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
});
}
Ví dụ: Multi-tenant Routing
app.MapWhen(context => {
// Kiểm tra subdomain hoặc header tenant
return context.Request.Host.Host.StartsWith("tenant1.");
}, tenant1App => {
tenant1App.UseMiddleware();
tenant1App.UseEndpoints(e => e.MapControllers());
});
app.MapWhen(context => context.Request.Host.Host.StartsWith("tenant2."), tenant2App => {
tenant2App.UseMiddleware();
tenant2App.UseEndpoints(e => e.MapControllers());
});