Middleware và pipeline
Nội dung bài · 5 mục
- 1.Khái niệm
- 2.Ví dụ
- 3.Thử ngay
- 4.Lỗi hay gặp
- 5.Tóm tắt
Để đo mỗi request mất bao lâu, bạn không muốn thêm code đo vào từng action. Việc chung cho mọi request như vậy nên làm ở một chỗ, trước khi request tới controller. Chỗ đó là pipeline.
Khái niệm
🚰 Pipeline: chuỗi các bước mà mọi request đi qua trước khi tới controller, rồi response đi ngược lại qua đúng các bước đó.
🧱 Middleware: một bước trong pipeline, xử lý request, gọi bước tiếp theo, rồi xử lý response.
Ví dụ
using System.Diagnostics;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.Use(async (context, next) =>
{
var watch = Stopwatch.StartNew();
await next();
Console.WriteLine(
$"{context.Request.Path} " +
$"{context.Response.StatusCode} " +
$"{watch.ElapsedMilliseconds}ms");
});
app.MapControllers();
app.Run();app.Use(...)thêm một middleware vào pipeline. Nó nhận một lambda có hai tham số(context, next), thân nhiều câu lệnh đặt trong{ }.- Lambda cũng đánh dấu được
asyncnhư method. contextchứa request và response hiện tại.- Code trước
await next()chạy khi request đi vào. Code sau nó chạy khi response đi ra. Stopwatchđo thời gian, cầnusing System.Diagnostics.- Middleware chạy theo đúng thứ tự được thêm trong
Program.cs.
Thử ngay
Thay phần middleware ở ví dụ bằng hai middleware:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.Use(async (context, next) =>
{
Console.WriteLine("A vào");
await next();
Console.WriteLine("A ra");
});
app.Use(async (context, next) =>
{
Console.WriteLine("B vào");
await next();
Console.WriteLine("B ra");
});
app.MapControllers();
app.Run();Chạy server, gọi curl -i http://localhost:5000/api/products rồi xem cửa sổ
đang chạy server.
Đoán trước khi chạy: bốn dòng in ra theo thứ tự nào?
Xem kết quả
A vào
B vào
B ra
A raRequest đi xuôi A rồi B, tới controller, rồi response đi ngược B rồi A. Middleware thêm trước thì bọc ngoài middleware thêm sau.
Lỗi hay gặp
Quên await next(). Request dừng ở middleware này, controller không bao
giờ chạy. Client nhận response rỗng.
// SAI — không gọi next, request không đi tiếp
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
Console.WriteLine("Có request");
});// ĐÚNG
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
Console.WriteLine("Có request");
await next();
});Sửa response sau khi đã gửi. Sau await next(), response thường đã bắt
đầu gửi về client. Đổi header lúc đó sẽ báo lỗi.
// SAI — header đã gửi đi, không đổi được nữa
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
await next();
context.Response.Headers["X-Shop"] = "An";
});Muốn thêm header thì đặt code đó trước await next().
// ĐÚNG — đổi header khi response chưa gửi
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
context.Response.Headers["X-Shop"] = "An";
await next();
});Tóm tắt
- Pipeline là chuỗi middleware mà mọi request đi qua.
- Middleware xử lý request trước
await next(), xử lý response sau đó. - Thứ tự thêm middleware trong
Program.cslà thứ tự chạy. - Việc chung cho mọi request như đo thời gian, ghi log nên làm ở middleware.
Bình luận
Đang tải bình luận…