Trong message handler, một chuỗi message handlers được nối lại với nhau. Handler đầu nhận HTTP request, xử lý một chút, và pass request cho handler tiếp theo. Tại một điểm nào đó, response được tạo và quay ngược lên chuỗi. Pattern này gọi là delegating handler.
Ngoài built-in Server-side Message Handlers, ta cũng tạo custom Server-Side HTTP Message Handlers. Để tạo custom Server-Side HTTP Message Handler trong ASP.NET Web API, ta dùng DelegatingHandler. Tạo class kế thừa System.Net.Http.DelegatingHandler. Custom class đó override phương thức SendAsync.
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
Phương thức nhận HttpRequestMessage input và async trả về HttpResponseMessage. Implementation điển hình:
- Process request message.
- Call base.SendAsync để gửi request cho inner handler.
- Inner handler trả về response message. (Bước này async.)
- Process response và return cho caller.
Ví dụ: Handler chuẩn (cho request đi tiếp)
public class CustomMessageHandler : DelegatingHandler {
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken) {
Debug.WriteLine("CustomMessageHandler processing the request");
// Gọi inner handler (tiếp theo trong chain)
var response = await base.SendAsync(request, cancellationToken);
Debug.WriteLine("CustomMessageHandler processing the response");
return response;
}
}
Ví dụ: Handler short-circuit (tự tạo response, không gọi inner)
public class CustomMessageHandler : DelegatingHandler {
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken) {
// Tự tạo response
var response = new HttpResponseMessage(HttpStatusCode.OK) {
Content = new StringContent("Skipping the inner handler")
};
// TaskCompletionSource tạo task không chứa delegate
var taskCompletion = new TaskCompletionSource<HttpResponseMessage>();
taskCompletion.SetResult(response);
return taskCompletion.Task;
}
}
Pipeline Execution Flow (Luồng thực thi)
Request Flow (Downstream): Response Flow (Upstream):
┌─────────────────────┐ ┌─────────────────────┐
│ Handler A (Outer) │────Request──▶│ Handler A (Outer) │
│ - Pre-process │ │ - Post-process │
└─────────┬───────────┘ └──────────▲──────────┘
│ │
▼ │
┌─────────────────────┐ ┌──────────┴──────────┐
│ Handler B (Middle) │────Request──▶│ Handler B (Middle) │
│ - Pre-process │ │ - Post-process │
└─────────┬───────────┘ └──────────▲──────────┘
│ │
▼ │
┌─────────────────────┐ ┌──────────┴──────────┐
│ Handler C (Inner) │────Request──▶│ Handler C (Inner) │
│ - Controller │ │ - Create Response │
│ - Action Exec │ │ │
└─────────────────────┘ └─────────────────────┘
Các Built-in Handlers trong Web API
- HttpServer - Top-level handler, nhận request từ host
- HttpRoutingDispatcher - Dispatch request dựa trên route
- HttpControllerDispatcher - Gửi request đến Web API controller
Use Cases thực tế
| Handler | Mục đích | Short-circuit? |
|---|---|---|
| LoggingHandler | Log request/response, timing | Không |
| AuthenticationHandler | Validate token, API key | Có (401 nếu invalid) |
| RateLimitingHandler | Giới hạn request rate | Có (429 nếu vượt limit) |
| CorsHandler | Thêm CORS headers | Không (chỉ modify response) |
| CompressionHandler | Nén response (gzip/deflate) | Không |
| ErrorHandlingHandler | Bắt exception, trả error format chuẩn | Có (khi exception) |
ASP.NET Core Equivalent
Trong ASP.NET Core, Middleware thay thế DelegatingHandler:
// Middleware tương đương
public class CustomMiddleware {
private readonly RequestDelegate _next;
public CustomMiddleware(RequestDelegate next) {
_next = next;
}
public async Task InvokeAsync(HttpContext context) {
// Pre-process
await _next(context); // Call next middleware
// Post-process
}
}
// Register trong Startup
app.UseMiddleware();