Ответ
В ASP.NET Core конвейер обработки HTTP-запроса (pipeline) строится с помощью методов расширения для IApplicationBuilder. Эти методы добавляют компоненты middleware, которые выполняются последовательно. Вот ключевые методы:
1. Use — Добавление общего middleware
Добавляет middleware, который может обработать запрос и/или передать управление следующему компоненту в конвейере.
app.Use(async (HttpContext context, RequestDelegate next) =>
{
// Логика, выполняемая ДО следующего middleware (например, логирование, установка заголовков)
LogRequest(context.Request.Path);
await next(context); // Вызов следующего middleware в цепочке
// Логика, выполняемая ПОСЛЕ следующего middleware (например, модификация ответа)
LogResponse(context.Response.StatusCode);
});
2. Run — Терминальный middleware
Добавляет middleware, который завершает выполнение конвейера (не вызывает next). Все middleware, зарегистрированные после Run, никогда не выполнятся для данного пути.
app.Run(async context =>
{
await context.Response.WriteAsync("Это конечная точка. Конвейер завершен здесь.");
});
// Этот middleware уже не будет вызван для запроса, попавшего в `Run` выше.
app.Use(...);
3. Map — Ветвление конвейера по пути запроса
Создает отдельную ветку конвейера, которая выполняется только если путь запроса начинается с указанного сегмента.
app.Map("/api", apiApp =>
{
// Этот вложенный конвейер сработает только для путей, начинающихся с /api
apiApp.UseMiddleware<ApiAuthenticationMiddleware>();
apiApp.UseRouting();
apiApp.UseEndpoints(endpoints => endpoints.MapControllers());
});
app.Map("/admin", adminApp =>
{
// Отдельный конвейер для админки
adminApp.UseMiddleware<AdminAuthMiddleware>();
adminApp.UseStaticFiles();
adminApp.Run(async ctx => await ctx.Response.WriteAsync("Admin Area"));
});
4. MapWhen — Ветвление по условию
Более гибкий метод, который создает ветку на основе произвольного условия (предиката) над HttpContext.
app.MapWhen(context => context.Request.Query.ContainsKey("debug"), debugApp =>
{
// Этот конвейер выполнится только если в запросе есть query-параметр 'debug'
debugApp.UseMiddleware<DebugInfoMiddleware>();
});
5. UseWhen — Условное выполнение middleware с возвратом
Позволяет выполнить дополнительный middleware на основе условия, после которого выполнение возвращается в основной конвейер. В отличие от Map, не создает изолированную ветку.
app.UseWhen(context => context.Request.Headers.ContainsKey("X-Forwarded-For"), appBuilder =>
{
appBuilder.UseMiddleware<ReverseProxyHeaderMiddleware>();
});
// Middleware, зарегистрированные здесь, выполнятся ВСЕГДА, после ReverseProxyHeaderMiddleware (если условие сработало).
app.UseRouting();
Принцип работы: Конвейер строится в Program.cs или Startup.Configure. Порядок регистрации middleware критически важен. Middleware выполняется в порядке регистрации для входящего запроса и в обратном порядке для исходящего ответа (если используется await next()), образуя паттерн «вложенности» (nested pattern).
Типичная последовательность в реальном приложении:
app.UseExceptionHandler("/error"); // Глобальный обработчик исключений (первым, чтобы ловить все)
app.UseHttpsRedirection();
app.UseStaticFiles(); // Обслуживание статических файлов
app.UseRouting(); // Маршрутизация
app.UseAuthentication(); // Аутентификация
app.UseAuthorization(); // Авторизация
app.MapControllers(); // Сопоставление контроллеров (терминальный для API)
app.MapRazorPages(); // Сопоставление Razor Pages (терминальный для UI)