Классы middleware

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

Для создания компонентов middleware, которые обрабатывают запрос, в прошлых темах использовались так называемые inline middleware. То есть с помощью методов app.Run/app.Use/app.Map/app.MapWhen/app.UseWhen в конвейер обработки запроса встраивались некоторые обработчики в виде лямбда-выражений или полноценных методов. Однако также ASP.NET Core позволяет определять middleware в виде отдельных классов.

Итак, добавим в проект новый класс, который назовем TokenMiddleware и который будет иметь следующий код:

Imports Microsoft.AspNetCore.Http

Public Class TokenMiddleware
    Private ReadOnly nextMiddleware As RequestDelegate

    Public Sub New(nextMiddleware As RequestDelegate)
        Me.nextMiddleware = nextMiddleware
    End Sub

    Public Async Function InvokeAsync(context As HttpContext) As Task

        Dim token = context.Request.Query("token")
        If token <> "12345678" Then
            context.Response.StatusCode = 403
            Await context.Response.WriteAsync("Token is invalid")
        Else
            Await nextMiddleware.Invoke(context)
        End If
    End Function
End Class

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

Также в классе должен быть определен метод, который должен называться либо Invoke, либо InvokeAsync. Причем этот метод должен возвращать объект Task и принимать в качестве параметра контекст запроса - объект HttpContext. Данный метод собственно и будет обрабатывать запрос.

Суть действия класса заключается в том, что мы получаем из запроса параметр "token". Если полученный токен равен строке "12345678", то передаем запрос дальше следующему компоненту, вызвав метод nextMiddleware.Invoke(). Иначе возвращаем пользователю сообщение об ошибке.

Для добавления компонента middleware, который представляет класс, в конвейер обработки запроса применяется метод UseMiddleware(). Так, изменим файл Program.vb следующим образом:

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.UseMiddleware(Of TokenMiddleware)

        app.Run(Async Function(context As HttpContext) As Task
                    Await context.Response.WriteAsync("Hello METANIT.COM")
                End Function)

        app.Run()
    End Sub
End Module

С помощью метода UseMiddleware(Of T) в конструктор объекта TokenMiddleware будет внедряться объект для параметра RequestDelegate next. Поэтому явным образом передавать значение для этого параметра нам не нужно.

Запустим проект. И если мы не передадим через строку запроса параметр token или передадим для него значение, отличное от "12345678", то браузер отобразит ошибку:

Классы middleware в ASP.NET Core и Visual Basic .NET

Если же будет передан корректный токен, то вызов app.UseMiddleware(Of TokenMiddleware)() передаст обработку запроса в компонент middleware из app.Run():

Классы middleware и UseMiddleware в ASP.NET Core и Visual Basic .NET

Метод расширения для встраивания middleware

Также нередко для встраивания подобных компонентов middleware определяются специальные методы расширения. Сделаем что-то подобное и для этого изменим код программы в Program.vb следующим образом:

Imports System.Runtime.CompilerServices
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.UseToken()

        app.Run(Async Function(context As HttpContext) As Task
                    Await context.Response.WriteAsync("Hello METANIT.COM")
                End Function)

        app.Run()
    End Sub

    <Extension()>
    Public Sub UseToken(builder As IApplicationBuilder)
        builder.UseMiddleware(Of TokenMiddleware)()
    End Sub
End Module

Здесь ключевой момент заключается в создании метода расширения

<Extension()>
Public Sub UseToken(builder As IApplicationBuilder)
    builder.UseMiddleware(Of TokenMiddleware)()
End Sub

Сам метод называется UseToken. Здесь создается метод расширения для типа IApplicationBuilder, поэтому параметр именно этого типа передается в качестве первого (и единственного) параметра. И этот метод встраивает компонент TokenMiddleware в конвейер обработки запроса.

Затем мы можем написать так

app.UseToken()

И тем самым встроить TokenMiddleware в конвейер обработки запроса.

Передача параметров

Изменим класс TokenMiddleware, чтобы он извне получал образец токена для сравнения:

Imports Microsoft.AspNetCore.Http

Public Class TokenMiddleware
    Private ReadOnly nextMiddleware As RequestDelegate
    Private pattern As String
    Public Sub New(nextMiddleware As RequestDelegate, pattern As String)
        Me.nextMiddleware = nextMiddleware
        Me.pattern = pattern
    End Sub

    Public Async Function InvokeAsync(context As HttpContext) As Task

        Dim token = context.Request.Query("token")
        If token <> pattern Then
            context.Response.StatusCode = 403
            Await context.Response.WriteAsync("Token is invalid")
        Else
            Await nextMiddleware.Invoke(context)
        End If
    End Function
End Class

Образец токена, с которым идет сравнения, устанавливается через конструктор.

Далее изменим код в файле Program.vb, чтобы передавать в middleware нужные токены:

Imports System.Runtime.CompilerServices
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.UseToken("555555")

        app.Run(Async Function(context As HttpContext) As Task
                    Await context.Response.WriteAsync("Hello METANIT.COM")
                End Function)

        app.Run()
    End Sub

    <Extension()>
    Public Sub UseToken(builder As IApplicationBuilder, pattern As String)
        builder.UseMiddleware(Of TokenMiddleware)(pattern)
    End Sub
End Module

Чтобы передать ножное значение в конструктор TokenMiddleware, в метод builder.UseMiddleware можно передать набор значений - они автоматически передаются в конструктор компонента middleware:

<Extension()>
    Public Sub UseToken(builder As IApplicationBuilder, pattern As String)
        builder.UseMiddleware(Of TokenMiddleware)(pattern)
    End Sub

И при вызове метода расширения UseToken в него можно передать конкретное значение

app.UseToken("555555")
Передача параметров в классы middleware в ASP.NET Core и Visual Basic .NET
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850