Um importante aspecto arquitetural precisa ser levado em conta ao enviarmos uma requisição HTTP para uma aplicação ASP.NET Core: diversos middlewares podem ser acionados durante o processamento desta solicitação e, mesmo, logo após a produção do resultado. Vale lembrar que a arquitetura do ASP.NET Core está centrada em uma pilha de execução de middlewares, sendo comum que esses componentes envolvam funcionalidades como autenticação/autorização, CORS (Cross-Origin Resource Sharing), compressão de respostas e logging/monitoramento. Pensando em performance e também em simplificar o processamento de alguns tipos de requisições, o ASP.NET Core traz agora no .NET 8 uma estrutura chamada short-circuit middleware. Esta nova implementação permite que configuremos endpoints que serão acionados imediatamente quando da chegada de uma requisição HTTP, sem que ocorra o acionamento dos middlewares configurados na pilha de execução da aplicação.
Para demonstrar esta nova capacidade criei em um projeto de testes um middleware – classe MiddlewareExecutionNotificator – que gera notificações de alerta, com isto acontecendo antes (linha 16) e após o processamento de uma requisição HTTP (linha 18):
namespace APIContagem.Middlewares;
public class MiddlewareExecutionNotificator
{
private readonly RequestDelegate _next;
public MiddlewareExecutionNotificator(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
var logger = (ILogger<MiddlewareExecutionNotificator>)httpContext
.RequestServices.GetService(typeof(ILogger<MiddlewareExecutionNotificator>))!;
logger.LogWarning("MiddlewareExecutionNotificator - Inicio da execucao");
await _next(httpContext);
logger.LogWarning("MiddlewareExecutionNotificator - Fim da execucao");
}
}
O Extension Method UseMiddlewareExecutionNotificator permitirá que o middleware seja ativado para os endpoints da API de testes:
namespace APIContagem.Middlewares;
public static class MiddlewareExecutionNotificatorExtensions
{
public static IApplicationBuilder UseMiddlewareExecutionNotificator(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<MiddlewareExecutionNotificator>();
}
}
Na listagem seguinte podemos observar:
- A ativação do middleware de testes, por meio de uma chamada ao método UseMiddlewareExecutionNotificator;
- O endpoint /status foi definido como um Health Check (linhas 19 a 23), indicando que a aplicação está funcionando normalmente;
- Já o endpoint /contador fará uma contagem de acessos, sendo incrementado a cada nova requisição.
using APIContagem;
using APIContagem.Middlewares;
using APIContagem.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<Contador>();
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.UseHttpsRedirection();
app.UseMiddlewareExecutionNotificator();
app.MapGet("/status", () =>
{
app.Logger.LogInformation("Acionado endpoint de Health Check");
return "API Contagem - OK";
});
app.MapGet("/contador", (Contador contador) =>
{
int valorAtualContador;
lock (contador)
{
contador.Incrementar();
valorAtualContador = contador.ValorAtual;
}
app.Logger.LogInformation($"Contador - Valor atual: {valorAtualContador}");
return TypedResults.Ok(new ResultadoContador()
{
ValorAtual = contador.ValorAtual,
Local = contador.Local,
Kernel = contador.Kernel,
Framework = contador.Framework,
Mensagem = app.Configuration["Saudacao"]
});
}).Produces<ResultadoContador>().WithOpenApi();
app.Run();

Para ativar o middleware de short-circuit para o endpoint /status basta acionar o método ShortCircuit (linha 23):
using APIContagem;
using APIContagem.Middlewares;
using APIContagem.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<Contador>();
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.UseHttpsRedirection();
app.UseMiddlewareExecutionNotificator();
app.MapGet("/status", () =>
{
app.Logger.LogInformation("Acionado endpoint de Health Check");
return "API Contagem - OK";
}).ShortCircuit();
app.MapGet("/contador", (Contador contador) =>
{
int valorAtualContador;
lock (contador)
{
contador.Incrementar();
valorAtualContador = contador.ValorAtual;
}
app.Logger.LogInformation($"Contador - Valor atual: {valorAtualContador}");
return TypedResults.Ok(new ResultadoContador()
{
ValorAtual = contador.ValorAtual,
Local = contador.Local,
Kernel = contador.Kernel,
Framework = contador.Framework,
Mensagem = app.Configuration["Saudacao"]
});
}).Produces<ResultadoContador>().WithOpenApi();
app.Run();
Novos testes com os endpoints da aplicação resultarão em diferenças. Enquanto as requisições direcionadas a /contador exibirão mensagens (em amarelo) antes e após a execução do código que implementa o endpoint, o mesmo comportamento deixará de acontecer com o endpoint /status:

Temos ainda a possibilidade de utilizar o método MapShortCircuit, definindo um status code e uma lista de rotas em que a execução da pilha de middlewares será ignorada. No exemplo a seguir (linha 45) o status 404 (Not Found) será retornado em tentativas de acesso a arquivos como robots.txt e favicon.ico (os quais normalmente não existem em projetos como APIs REST):
using APIContagem;
using APIContagem.Middlewares;
using APIContagem.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<Contador>();
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.UseHttpsRedirection();
app.UseMiddlewareExecutionNotificator();
app.MapGet("/status", () =>
{
app.Logger.LogInformation("Acionado endpoint de Health Check");
return "API Contagem - OK";
}).ShortCircuit();
app.MapGet("/contador", (Contador contador) =>
{
int valorAtualContador;
lock (contador)
{
contador.Incrementar();
valorAtualContador = contador.ValorAtual;
}
app.Logger.LogInformation($"Contador - Valor atual: {valorAtualContador}");
return TypedResults.Ok(new ResultadoContador()
{
ValorAtual = contador.ValorAtual,
Local = contador.Local,
Kernel = contador.Kernel,
Framework = contador.Framework,
Mensagem = app.Configuration["Saudacao"]
});
}).Produces<ResultadoContador>().WithOpenApi();
app.MapShortCircuit(404, "robots.txt", "favicon.ico");
app.Run();
Observamos na animação seguinte que ao usar o método MapShortCircuit o middleware de testes sequer foi acionado (em tentativas envolvendo o acesso a robots.txt e favicon.ico):

Este projeto foi disponibilizado no GitHub:
https://github.com/renatogroffe/ASPNETCore8-REST_API-Minimal-ShortCircuit_ContagemAcessos
Caso achem útil esta solução, peço por favor um ⭐️ no repositório apoiando. Fica também o convite para que vocês me sigam lá no GitHub!




