Middleware(ミドルウェア)
ミドルウェアとは
ASP.NET Coreにおける**ミドルウェア(Middleware)**は、HTTPリクエストとレスポンスを処理するためのアプリケーションパイプラインに組み込まれるソフトウェアコンポーネントです。
各ミドルウェアコンポーネントは以下の役割を持ちます:
- リクエストをパイプライン内の次のコンポーネントに渡すかどうかを選択する。
- パイプラインの次のコンポーネントが呼び出される前と後に処理を実行する。
(出典: Microsoft Learn)
リクエストパイプライン
ASP.NET Coreのリクエストパイプラインは、一連のミドルウェアデリゲートとして構成されます。これらは Program.cs で WebApplication ビルダーを使用して構成されます。
処理の流れ
- リクエストが届くと、登録された順序で最初のミドルウェアが呼び出されます。
- ミドルウェアは処理を行い、
next()を呼び出して次のミドルウェアに制御を渡します。 - これを繰り返し、最後のミドルウェア(ターミナルミドルウェア)まで到達します。
- 最後のミドルウェアが処理を終えると、制御は逆順で前のミドルウェアに戻っていきます(レスポンス処理)。
順序の重要性
ミドルウェアの登録順序は非常に重要です。例えば、認証(Authentication)ミドルウェアは、認可(Authorization)ミドルウェアの前に実行される必要があります。
一般的な順序の例:
- 例外ハンドラー (
UseExceptionHandler) - HSTS (
UseHsts) - HTTPSリダイレクト (
UseHttpsRedirection) - 静的ファイル (
UseStaticFiles) - ルーティング (
UseRouting) - CORS (
UseCors) - 認証 (
UseAuthentication) - 認可 (
UseAuthorization) - エンドポイント (
MapControllers,MapRazorPagesなど)
基本的な実装方法
Run
Run はパイプラインの終端(ターミナル)を定義します。これ以降のミドルウェアは実行されません。
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from terminal middleware!");
});
Use
Use はパイプラインの途中に処理を挿入します。next パラメータを使用して次のミドルウェアを呼び出します。
app.Use(async (context, next) =>
{
// 次のミドルウェアを呼び出す前の処理
Console.WriteLine("Before next middleware");
await next.Invoke();
// 次のミドルウェアから戻ってきた後の処理
Console.WriteLine("After next middleware");
});
Map
Map はリクエストパスに基づいてパイプラインを分岐させます。
app.Map("/branch", branchApp =>
{
branchApp.Run(async context =>
{
await context.Response.WriteAsync("This is a branch pipeline.");
});
});
カスタムミドルウェアの作成
再利用可能なミドルウェアを作成する場合、クラスとして定義するのが一般的です。
規約ベースのミドルウェア
特定のインターフェースを実装する必要はありませんが、以下の規約に従う必要があります。
RequestDelegate型の引数を持つパブリックコンストラクターを持つ。HttpContextを引数に取り、Taskを返すInvokeまたはInvokeAsyncという名前のパブリックメソッドを持つ。
public class RequestLoggingMiddleware
{
private readonly RequestDelegate _next;
public RequestLoggingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
Console.WriteLine($"Request: {context.Request.Method} {context.Request.Path}");
await _next(context);
Console.WriteLine($"Response: {context.Response.StatusCode}");
}
}
拡張メソッドの作成
IApplicationBuilder に対する拡張メソッドを作成して、登録を簡単にします。
public static class RequestLoggingMiddlewareExtensions
{
public static IApplicationBuilder UseRequestLogging(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestLoggingMiddleware>();
}
}
使用方法
Program.cs で登録します。
var app = builder.Build();
app.UseRequestLogging(); // カスタムミドルウェアの使用
app.Run();
IMiddleware インターフェース
IMiddleware インターフェースを実装する方法もあります。この場合、ミドルウェアはDIコンテナに登録する必要があります(通常は Transient または Scoped)。
public class FactoryActivatedMiddleware : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
// 処理
await next(context);
}
}
登録:
builder.Services.AddTransient<FactoryActivatedMiddleware>();
// ...
app.UseMiddleware<FactoryActivatedMiddleware>();
標準的なミドルウェア
ASP.NET Coreには多くの組み込みミドルウェアが用意されています。
| ミドルウェア | 説明 |
|---|---|
UseStaticFiles | 静的ファイル(HTML, CSS, JS, 画像など)を提供します。 |
UseRouting | リクエストURLをエンドポイントにマッチングさせます。 |
UseAuthentication | ユーザーのIDを検証します(ログイン処理など)。 |
UseAuthorization | ユーザーがリソースにアクセスする権限を持っているか確認します。 |
UseCors | Cross-Origin Resource Sharing (CORS) を構成します。 |
UseSession | セッション状態を管理します。 |
UseResponseCaching | レスポンスのキャッシュをサポートします。 |
まとめ
- ミドルウェアはリクエストパイプラインを構成する部品です。
- 登録順序が動作に大きく影響します。
Use,Run,Mapを組み合わせてパイプラインを構築します。- 複雑なロジックはクラスベースのカスタムミドルウェアとしてカプセル化することが推奨されます。