????? ??????? Middleware ????????? ASP.NET Core-??

????? ??????? Middleware ????????? ASP.NET Core-??

ASP.NET Core 9-?? ???-???? ???????????????? ??????????? Middleware ???????. ?? ???? ?????????, ??????? ?????????? ???????? ??????? HTTP ?????????? ?? ???????? ??????? ?? ???????????? ?????????? ??????????.

???????? ??? ??????, Middleware ???? ?????????? ????? ??????, ??????? "?????????" ???? ???????? - ??? ????? ??????? ?????????? ?? ??????????, ????? ????????? ????? ????? ??????? ???????? ?????????.

????? ???? ?? ?????????????? ????????????, ??? ?????? ????? ????????? ????????, ???????????? ?????????, ?? ?????????? ??????????. Middleware-?? ?????? ?????????? ?? ??????? ?????? ??????? endpoint-?? ???-?????. Middleware ?????????? ????????, ?? ?????? ?????? ???????? ?? ??????????? ????? ??????????????.

Middleware: ?? ???? ?? ????? ????????

Middleware ASP.NET Core-?? ???? ?????????? ??????????, ??????? ??????? HTTP ??????????? ??????????? ????????. ???? ??????? ???????? ?????? ????????, ????? ???????? ???????? ????? ?? ?????? ?????????? ?????? ?????????? ?? ????? ????????? ??????????.

???????????? ?????????, ????? ???????? Middleware ???? ????, ??????? ????? ???????? (HTTP ?????????), ????????? ??? ?? ????????? ?????? ?????. ???? ???? ???????? ??????? ???????? (HTTP ??????).

??????? ?????????? ????, ??? ?? ??????? ??? ???????????? ???????:

  1. ????????? ????? - ??????? HTTP ???????? ???????, ??? ??????? ????? Middleware-? ??????????????
  2. ??????? ????? - ??????? ?????? ????????, ??? ??????? ????? Middleware-???, ????? ??? ??????????????

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// ??????? Middleware 
app.Use(async (context, next) =>
{
    Console.WriteLine("Middleware 1: ???????? ?????????");
    await next.Invoke();  // ????????? ??????? ?????? Middleware-?
    Console.WriteLine("Middleware 1: ?????? ??????");
});

// ????? Middleware 
app.Use(async (context, next) =>
{
    Console.WriteLine("Middleware 2: ???????? ?????????");
    await next.Invoke();  // ????????? ??????? ?????? Middleware-?
    Console.WriteLine("Middleware 2: ?????? ??????");
});

// ???? Middleware - ???????? ?????????
app.Run(async context =>
{
    await context.Response.WriteAsync("Hello World!");
    Console.WriteLine("??????? Middleware: ?????? ??????");
});

app.Run();        

?? ????? ???????????? ???????? ??????????:

Middleware 1: ???????? ?????????
Middleware 2: ???????? ?????????
??????? Middleware: ?????? ??????
Middleware 2: ?????? ??????
Middleware 1: ?????? ??????        

?????? ?? "????????" ??????? ???????? ?????, ??????? ????? Middleware-?, ??????? ?????? ?? ?????? ?????? ???????? ????? ????, ????? ???????????????.

????????????? ???????????? app.Use() ?? app.Run() ???????? ?????. Use ?????? ?????????? ???????? ??????????? ????????? ?????? Middleware-??, ???? Run ????????? ????????? - ?? "???????????" Middleware-?.

????? ???????? ???????? Middleware?

Middleware-?? ?????? ????????? ??? ????:

  1. ???????, ?????? ???????? - ???????? app.Use() ????????
  2. ?????? ??????? - ???? ??????????????? ?? ???????????? ???????????????

????, ?????? Middleware, ??????? ?????????? ???????? URL-???? ????????? ?????????? ??????? (???., ???).

?????? Middleware-?? ??????:

public class LanguageMiddleware
{
    private readonly RequestDelegate _next;

    public LanguageMiddleware(RequestDelegate next)
    {
        _next = next; // ???????? ?????? Middleware-?? ???????????
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // ?????? ???? ????????? URL-????: ?lang=ka
        string lang = context.Request.Query["lang"];
        
        if (!string.IsNullOrEmpty(lang))
        {
            try
            {
                // ?????? ???????? ?????????????
                var culture = new System.Globalization.CultureInfo(lang);
                System.Globalization.CultureInfo.CurrentCulture = culture;
                System.Globalization.CultureInfo.CurrentUICulture = culture;
                
                Console.WriteLine($"??? ????????: {lang}");
            }
            catch (Exception)
            {
                Console.WriteLine($"???????? ???? ????: {lang}");
            }
        }

        // ????????? ????????? ?????? Middleware-?
        await _next(context);
    }
}        

????, ??? ???????????? ?? Middleware-?? ??????????, ???????? Extension ??????:

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseLanguage(this IApplicationBuilder app)
    {
        return app.UseMiddleware<LanguageMiddleware>();
    }
}        

?? ??????????? ????? ???????????:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseLanguage(); // ???????? ????? ???? Middleware-?

app.MapGet("/", () => "Hello World!");

app.Run();        

???? ????????? URL-?? ????????? ????????? ?lang=ka ?? ????? ????????? ?????? ????? ??????.

ASP.NET Core 9-?? ????????? Middleware-?? ??????

ASP.NET Core 9-? ????????? ????????????? ?????? ????????? Middleware-?? ????????????. ??, ????????? ???????:

1. Keyed DI ??????????

???? ????????? ??????? ????????? ????????? Middleware-?? ????????????? ?? InvokeAsync ???????, ??? ???? ???? ??????? ????.

// ?????????? ???????????
builder.Services.AddKeyedSingleton<IMyService, MyServiceImpl1>("service1");
builder.Services.AddKeyedSingleton<IMyService, MyServiceImpl2>("service2");

// Middleware-?? ??????????
public class MyMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IMyService _service;

    public MyMiddleware(RequestDelegate next, [FromKeyedServices("service1")] IMyService service)
    {
        _next = next;
        _service = service;
    }

    public async Task InvokeAsync(HttpContext context, [FromKeyedServices("service2")] IMyService scopedService)
    {
        // ????? ???????? ??????????
        await _next(context);
    }
}        

?? ?????????? ???????? ???? ??????????? ????????? ????????????? ??????????? ?????????? ??????????.

2. ExceptionHandler-?? ????????????

ASP.NET Core 9-?? ????????? ???????????? ????? ???????? ???????????? ?????????? HTTP ?????? ????:

app.UseExceptionHandler(new ExceptionHandlerOptions
{
    StatusCodeSelector = ex => ex switch
    {
        TimeoutException => StatusCodes.Status504GatewayTimeout,
        UnauthorizedAccessException => StatusCodes.Status401Unauthorized,
        _ => StatusCodes.Status500InternalServerError
    }
});        

?? ?????????? ???? ?????? HTTP ???????? ?????????? ?????????????? ?? API-?? ???????????? ?????????????.

3. StaticFiles-?? ????????????: MapStaticAssets

????????? ???????? ??????????? ????? ???? ???????? ????? ???????:

// ????? ???
// app.UseStaticFiles();

// ????? ???
app.MapStaticAssets();        

????? ?????? ??????????? ????????????:

  • ????????? ???????????? ETag-????
  • ???? ??????? ??????????? ????????? ???????????
  • ???????? ?????????????? ????????? ??????????

4. ?????????? ?????????? ????????

ASP.NET Core 9-?? ????????? ????????? ?????????? ????????? ?????????? ???????????????? ?? ???????????????:

// ?????????????? ?????????? ????????
app.MapGet("/health", () => "Healthy").DisableHttpMetrics();

// ?? Middleware-?? ?????????? ???????????????
app.Use(async (context, next) =>
{
    if (context.Request.Headers.ContainsKey("x-disable-metrics"))
    {
        var metricsFeature = context.Features.Get<IHttpMetricsTagsFeature>();
        if (metricsFeature != null)
        {
            metricsFeature.MetricsDisabled = true;
        }
    }
    
    await next(context);
});        

?? ????????????? ??????????? ?????? ?????????? ??????????, ????? ????? ????????? ???????? ????????? ??????? ???????? ????.

?????????? ??????????

???? ?????? ????????? ??????? ????????, ???????? ??????????, ????? ????????? ??????? ?????????? Middleware-?? ???????????.

???????? 1: ??????????? ???????? Correlation ID-??

????????????, ??? ?????? ??????????????? ???????, ????? ???? ???????? ????????? ???????? ???????. ????? ?????????? ??????? ?????? ????? ?????????? Correlation ID (?????????? ??????????????).

public class LoggingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<LoggingMiddleware> _logger;

    public LoggingMiddleware(RequestDelegate next, ILogger<LoggingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // ?????? ?? ?????? Correlation ID-?
        string correlationId = context.Request.Headers["X-Correlation-ID"];
        if (string.IsNullOrEmpty(correlationId))
        {
            correlationId = Guid.NewGuid().ToString();
            context.Request.Headers["X-Correlation-ID"] = correlationId;
        }
        
        // ???????? ????? ID-? ????????
        context.Response.OnStarting(() => {
            context.Response.Headers["X-Correlation-ID"] = correlationId;
            return Task.CompletedTask;
        });

        // ??????? ????????? ????????
        _logger.LogInformation("[{CorrelationId}] ?????? {Method} {Path}",
            correlationId, context.Request.Method, context.Request.Path);
        
        // ????? ????????
        var stopwatch = Stopwatch.StartNew();
        
        try
        {
            // ?????????? ????????? ???????????
            await _next(context);
            
            // ??????? ?????????? ??????????
            _logger.LogInformation("[{CorrelationId}] ???????? {Method} {Path} ???????? {StatusCode} ({Elapsed}ms)",
                correlationId, context.Request.Method, context.Request.Path, 
                context.Response.StatusCode, stopwatch.ElapsedMilliseconds);
        }
        catch (Exception ex)
        {
            // ??????? ????????
            _logger.LogError(ex, "[{CorrelationId}] ??????? {Method} {Path}",
                correlationId, context.Request.Method, context.Request.Path);
            throw; // ???????? ????????? ?????? Middleware-?
        }
    }
}        

?? ????????:

  • ?????? ?? ?????? ???????? ?????????????? ?????? ?????????????
  • ????????? ????? ?????????????? ???????, ??? ????????? ??????
  • ??????? ????????? ????????, ?????????? ?? ?????????
  • ??????? ????????? ?????????? ????

?? ?????????? ???????? ??????? ???????? ????????? ????????? ??????? ?? ????????????, ?? ?????.

???????? 2: IP ????????? ????????????????

?? ?????? Middleware-?, ??????? ??????? ?? ?????? ?????????? IP ?????????? ????????.

public class IpFilterMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<IpFilterMiddleware> _logger;
    private readonly HashSet<string> _allowedIps;

    public IpFilterMiddleware(RequestDelegate next, ILogger<IpFilterMiddleware> logger, IConfiguration config)
    {
        _next = next;
        _logger = logger;
        
        // ?????????? ?????????? IP-??? ???????????????
        _allowedIps = new HashSet<string>(
            config.GetSection("Security:AllowedIps").Get<string[]>() ?? Array.Empty<string>()
        );
        
        _logger.LogInformation("IP ????????? ????????. ??????????? IP-???: {IpCount}", _allowedIps.Count);
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var ipAddress = context.Connection.RemoteIpAddress?.ToString();
        
        // ?? IP-???? ??? ????????, ????? ????????? ???????
        if (_allowedIps.Count > 0 && !string.IsNullOrEmpty(ipAddress))
        {
            if (!_allowedIps.Contains(ipAddress))
            {
                _logger.LogWarning("???????? ?????????? ??????????????? IP-???: {IpAddress}", ipAddress);
                
                context.Response.StatusCode = StatusCodes.Status403Forbidden;
                await context.Response.WriteAsync("?????? ??????????.");
                return; // ????????? ??????? ??
            }
        }
        
        // ?? IP ????????????, ??????????
        await _next(context);
    }
}        

?? Middleware-??:

  • ?????????? ?????????? IP-??? ???????????????
  • ????????? ?????????? ????????? IP-?
  • ??????? ?? ???????? ????????? ???????????

?? ????????? ?????? ??????????? ??????????????? ????????? ?? API-???? ?????????.

???????? 3: ???????????????? ?????????? ??????????

??????????????? ???????????? ??????? ???????, ?????? ???????????? (tenant) ???????? ?????????. ?? ???????? ???????????? ??????????, URL-?? ????????? ?? ???? ??????????.

public class TenantMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<TenantMiddleware> _logger;

    public TenantMiddleware(RequestDelegate next, ILogger<TenantMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context, ITenantService tenantService)
    {
        // ???????? ?????????? URL-?? ??????? ???????????
        // ???.: /tenant1/api/products
        var path = context.Request.Path.Value ?? "";
        var segments = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
        
        if (segments.Length > 0)
        {
            string potentialTenant = segments[0];
            
            if (await tenantService.TenantExistsAsync(potentialTenant))
            {
                // ??????? ????????, ???????? ??????????
                var tenant = await tenantService.GetTenantByIdAsync(potentialTenant);
                context.Items["CurrentTenant"] = tenant;
                
                // ??????????? ???? - ????? ???????? ??????
                context.Request.Path = path.Substring(potentialTenant.Length + 1);
                
                _logger.LogInformation("??????? ?????????????: {TenantId}", tenant.Id);
            }
        }
        
        // ?? ??????? ??? ???????????, ???????????? ????????????
        if (!context.Items.ContainsKey("CurrentTenant"))
        {
            context.Items["CurrentTenant"] = await tenantService.GetDefaultTenantAsync();
            _logger.LogInformation("??????????? ???????????? ???????");
        }
        
        await _next(context);
    }
}        

?? Middleware-??:

  • ??????? ??????? URL-?? ??????? ???????????
  • ????????? ???????? ?? ??? ?? ???????
  • ???????? ???????? ??????????? HttpContext.Items ??????????
  • ??????????? URL-?, ??? ????????? ????????? ??????????? ????

??? ???????? ????????????? ?????????????????? ?????????? ????????????????, ????????? ???????? ?? ?????????????? ??????????? ???? ?????????? ?????????.

????????? ?????????? ?? ???????????

Middleware-????? ?????????? ???????? ????????? ????????????? ????????, ??????? ???? ???????????????:

1. ????? ?????????????

Middleware-???? ????????????? ?????????? ??????????????. ?? ????????? ????:

  • ?????????? ??????? (Exception Handling) - ???? ???? ???-???? ???????, ??? ???????? ????? ???????
  • HTTPS ??????????????? - ???? ???? ?????? ??????
  • ????????? ??????? - ???????????
  • ???????? - ?????????????????
  • ?????????????? - ??????????????
  • ??????????? - ??????? ?????? ??????? ????????????

??????????? ????????????? ???????? ??? ??????????????:

app.UseExceptionHandler("/error");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();        

2. ??????????????? ?????????

  • next.Invoke() ?????????? - ??????????, ??? next() ??????????, ?? ?????? ?????????? ??????????
  • ??????? Headers - ???????? ??????? ???????? Response.OnStarting()-??, ????????????? next() ??????????? ??????
  • ??????????? ???? - ????????? ?????????? async/await ?? ??? ??????????? ?????????????? ????
  • Dependency Injection - ????????????? ?????????? Singleton ?????????, ???? InvokeAsync-?? - Scoped ?????????

3. ???????????

  1. ???????????? Middleware-??? ????? Middleware ??????? ??????????. ?????????? ?????? ??, ??? ?????????.
  2. Middleware vs Filter ASP.NET Core-?? ???????? Filters-????, ???????? ?????? ??????? ??????????. ????? ?????? ???????????? Middleware: ?????????, ????? ?????????? ??????? ??????????? Filter: ????????? ??????????? ?? ??????? ??????? ???????????
  3. ?????????? ??????? Pipeline-?? ????????? ????? ???????? ????. ???????? ?????? ?? ?????????? Developer Exception Page ???????????? ????????.
  4. ???????????? ??????????? ????? ?????????? (???., ?????? ????????) ???????? ???????????? ?????????, ?????? ????? ?????? ???????? ????????????. ?????????? ???????? ????? ???????????????.

?? ?????

Middleware ???? ASP.NET Core-?? ???-???? ??????? ??????? ?????????, ??????? ?????????? ???????? ?????????? HTTP ??????????? ????????? ?????????? ???????????? ?? ???????? ????. ASP.NET Core 9-?? ????? ?????????????? ????? ???? ????????? Middleware-?? ??????????? ??????.

要查看或添加评论,请登录

David Shergilashvili的更多文章