Сочетание конечных точек с другими middleware

Последнее обновление: 19.05.2022

Конвейер обработки запроса может содержать как конечные точки, так и другие компоненты middleware, которые тоже обрабатывают запрос. Но при сочетании в конвейере конечных точек и других компонентов middleware надо учитывать общий процесс обработки запроса и вызова конечных точек.

Так, если приложение содержит конечные точки, то система маршрутизации на основе процессе URL matching или сопоставления адреса URL с шаблонами маршрута выбирает для обработки определенную конечную точку. Если в приложении есть такая конечная точка, которая соответствует запросу, то компонент middleware Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware устанавливает у объекта HttpContext конечную точку для будущей обработки запроса, которую можно получить с помощью метода HttpContext.GetEndpoint(). Кроме того, устанавливаются значения маршрута, которые можно получить через коллекцию HttpRequest.RouteValues

Однако конечная точка начинает обрабатывать запрос только после того, как все middleware в конвейере начнут обработку запроса. Например, возьмем следующий код приложения:

Imports Microsoft.AspNetCore.Builder
Imports Microsoft.AspNetCore.Http

Module Program
    Sub Main(args As String())

        Dim builder = WebApplication.CreateBuilder(args)
        Dim app = builder.Build()

        app.Use(Async Function(context As HttpContext, nextDelegate As RequestDelegate) As Task
                    Console.WriteLine("First middleware starts")
                    Await nextDelegate.Invoke(context)
                    Console.WriteLine("First middleware ends")
                End Function)

        app.Map("/", Function(context As HttpContext) As String
                         Console.WriteLine("Index endpoint starts and ends")
                         Return "Index Page"
                     End Function)

        app.Use(Async Function(context As HttpContext, nextDelegate As RequestDelegate) As Task
                    Console.WriteLine("Second middleware starts")
                    Await nextDelegate.Invoke(context)
                    Console.WriteLine("Second middleware ends")
                End Function)

        app.Map("/about", Function(context As HttpContext) As String
                              Console.WriteLine("About endpoint starts and ends")
                              Return "About Page"
                          End Function)
        app.Run()
    End Sub
End Module

Здесь до и после первой конечной точки с помощью метода app.Use() в конвейер встроены два middleware. Для получения общей картины выполнения приложения процесс выполнения логгируется на консоль приложения.

Если мы запустим приложение, то при запросе по адресу "/" ожидаемо для обработки запроса будет выбрана первая конечная точка

Сочетание конечных точек endpoint и middleware в конвейере обработки запроса в ASP.NET Core и Visual Basic .NET

Но теперь взглянем на консоль приложения:

Порядок выполнения конечных точек и middleware в конвейере обработки запроса в ASP.NET Core и Visual Basic .NET

Мы видим, что конечная точка выполняется после того, как начнет выполняться компонент middleware, который в конвейере идет после этой конечной точки.

При этом в компонентах middleware также можно обрабатывать запросы по определенным адресам:

Imports Microsoft.AspNetCore.Builder
Imports Microsoft.AspNetCore.Http

Module Program
    Sub Main(args As String())

        Dim builder = WebApplication.CreateBuilder(args)
        Dim app = builder.Build()

        app.Use(Async Function(context As HttpContext, nextDelegate As RequestDelegate) As Task
                    If context.Request.Path.Value = "/date" Then
                        Await context.Response.WriteAsync($"Date: {Now.ToShortDateString()}")
                    Else
                        Await nextDelegate.Invoke(context)
                    End If
                End Function)

        app.Map("/", Function(context As HttpContext) "Index Page")
        app.Map("/about", Function(context As HttpContext) "About Page")
        app.Run()
    End Sub
End Module

Кроме того, middleware могут быть полезны для некоторого постдействия - выполнения некоторых действий, когда конечная точка уже выбрана. Или, наоборот, если ни одна из конечных точек не обработала запрос, и в middleware мы можем обработать эту ситуацию:

Imports Microsoft.AspNetCore.Builder
Imports Microsoft.AspNetCore.Http

Module Program
    Sub Main(args As String())

        Dim builder = WebApplication.CreateBuilder(args)
        Dim app = builder.Build()

        app.Use(Async Function(context As HttpContext, nextDelegate As RequestDelegate) As Task
                    Await nextDelegate.Invoke(context)
                    'постдействие
                    If context.Response.StatusCode = 404 Then
                        Await context.Response.WriteAsync("Resource Not Found")
                    End If
                End Function)

        app.Map("/", Function(context As HttpContext) "Index Page")
        app.Map("/about", Function(context As HttpContext) "About Page")
        app.Run()
    End Sub
End Module

Однако если в конце конвейера располагается терминальный компонент, то он будет выполняться даже если конечная точка соответствует запрошенному пути:

Imports Microsoft.AspNetCore.Builder
Imports Microsoft.AspNetCore.Http

Module Program
    Sub Main(args As String())

        Dim builder = WebApplication.CreateBuilder(args)
        Dim app = builder.Build()

        app.Map("/", Function(context As HttpContext) "Index Page")
        app.Map("/about", Function(context As HttpContext) "About Page")

        app.Run(Async Function(context As HttpContext) As Task
                    context.Response.StatusCode = 404
                    Await context.Response.WriteAsync("Resource not found")
                End Function)

        app.Run()
    End Sub
End Module

В данном случае по результату программы мы видим, что даже при запросах по адресу "/" и "/about" будет выполняться middleware из метода app.Run:

Терминальный middleware и Map в ASP.NET Core и Visual Basic .NET

Почему такое происходит? Опять же потому что, сначала выполняются все middleware в конвейере, и только потом выполняется конечная точка.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850