TL.MiddlewareLibrary 0.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package TL.MiddlewareLibrary --version 0.1.0
                    
NuGet\Install-Package TL.MiddlewareLibrary -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TL.MiddlewareLibrary" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TL.MiddlewareLibrary" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="TL.MiddlewareLibrary" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TL.MiddlewareLibrary --version 0.1.0
                    
#r "nuget: TL.MiddlewareLibrary, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TL.MiddlewareLibrary@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TL.MiddlewareLibrary&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=TL.MiddlewareLibrary&version=0.1.0
                    
Install as a Cake Tool

<p align="center"> <img src="assets/icon.svg" alt="TL Middleware Icon" width="128" height="128" /> </p>

🚀 TL.MiddlewareLibrary

.NET NuGet Profile License: MIT

Bem-vindo ao ecossistema TL.MiddlewareLibrary! Esta biblioteca modular em C# / .NET disponibiliza middlewares de alta performance para enriquecer, monitorar e proteger o pipeline HTTP de aplicações corporativas em ASP.NET Core (.NET 6, .NET 8 e .NET 9).

Projetada para eliminar código repetitivo, ela centraliza medição de latência com zero alocação, proteção contra rajadas de requisições por IP, cache em memória seguro e padronização automática de erros em formato JSON amigável com rastreamento via traceId.


🎯 Por que Usar a Biblioteca?

Em muitas APIs, acabamos repetindo o mesmo código defensivo em todos os controllers e endpoints:

  • Controladores cheios de blocos try/catch manuais.
  • Cada endpoint ou microsserviço retornando erros em formatos diferentes ({ erro }, { message }, { error_description }), complicando a vida do front-end e mobile.
  • Falhas 500 vazando stack traces ou mensagens técnicas de infraestrutura para o usuário.
  • Falta de controle simples de requisições por cliente e medição precisa de tempo de resposta.

A TL.MiddlewareLibrary resolve isso direto no pipeline do ASP.NET Core, deixando seus controllers e Minimal APIs focados 100% nas regras de negócio.


💡 Antes vs. Depois

Antes (Sem a biblioteca — boilerplate e risco de vazamento)
app.MapGet("/api/produtos/{id:int}", async (int id, IProdutoService service, ILogger<Program> logger) =>
{
    try
    {
        if (id <= 0)
            return Results.BadRequest(new { mensagem = "Id inválido" });

        var produto = await service.ObterPorIdAsync(id);
        if (produto == null)
            return Results.NotFound(new { erro = "Não encontrado" });

        return Results.Ok(produto);
    }
    catch (Exception ex)
    {
        logger.LogError(ex, "Erro ao buscar produto");
        return Results.StatusCode(500, new { erro = ex.Message, stack = ex.StackTrace }); // Vaza stack trace!
    }
});
Depois (Com a TL.MiddlewareLibrary — limpo, seguro e idiomático)
app.MapGet("/api/produtos/{id:int}", async (int id, IProdutoService service) =>
{
    if (id <= 0)
        throw new BadRequestException("O id do produto deve ser maior que zero.");

    var produto = await service.ObterPorIdAsync(id) 
        ?? throw new NotFoundException($"Produto {id} não encontrado.");

    return Results.Ok(produto);
});

O middleware intercepta a exceção de negócio automaticamente, retorna o status HTTP correto (400, 404), formata o JSON amigável e adiciona o traceId para consulta imediata nos logs.


🗺️ O Pipeline em Execução

O diagrama abaixo ilustra o ciclo de vida completo da requisição trafegando pelos 6 middlewares e voltando ao cliente:

graph TD
    Client(["🌐 Cliente HTTP"]) --> A["⏱️ RequestTimingMiddleware"]
    A --> B["🛡️ RateLimitingMiddleware"]
    B --> C["🔐 AuthenticationMiddleware"]
    C --> D["⚡ CachingMiddleware"]
    D --> E["🚨 ExceptionHandlingMiddleware"]
    E --> F["📊 StatusCodeMiddleware"]
    F --> Endpoints["⚙️ Endpoints / Controllers / Minimal APIs"]

    Endpoints --> F
    F --> E
    E --> D
    D --> C
    C --> B
    B --> A
    A --> Client

📦 Catálogo de Middlewares

💡 Decisões de Arquitetura: Todas as diretrizes de design e trade-offs dos componentes abaixo estão documentadas de forma unificada na ADR-001: Arquitetura, Convenções e Pipeline HTTP.

Middleware Método Fluente O que ele entrega Tópico na ADR
Request Timing app.UseRequestTiming() Mede o tempo total do ciclo de vida com Stopwatch zero-allocation e injeta o header X-Response-Time-Ms. § 2
Rate Limiting app.UseRateLimiting(limit, period) Limita requisições por IP de forma thread-safe, com descarte correto de timers (IDisposable) e resposta 429. § 3
Authentication app.UseAuthenticationMiddleware() Validação antecipada de cabeçalho Authorization antes de onerar a aplicação com processamento pesado. § 1
Caching app.UseCachingMiddleware(duration) Cache em memória inteligente para consultas GET e HEAD (200 OK), isolado por rota e QueryString. § 4
Exception Handling app.UseExceptionHandling() Captura global de falhas não tratadas, mascarando dados sensíveis em erros 500 e gerando traceId. § 5
Status Code app.UseStatusCodeMiddleware() Mapeamento automático de 12 exceções de negócio e garantia estrita de respostas 204 sem corpo. § 6

⚡ Instalação Rápida via CLI

Adicione o pacote ao seu projeto através do .NET CLI:

dotnet add package TL.MiddlewareLibrary --version 0.1.0

💻 Como Configurar no Program.cs

A configuração é simples, fluente e encadeada na ordem recomendada:

using MiddlewareLibrary.Exceptions;
using MiddlewareLibrary.Extensions;

var builder = WebApplication.CreateBuilder(args);

// 1. Serviços necessários
builder.Services.AddMemoryCache(); // Necessário caso utilize o CachingMiddleware

var app = builder.Build();

// 2. Encadeamento fluente do pipeline (Ordem Canônica)
app.UseRequestTiming();                                              // Mede o tempo total da requisição
app.UseRateLimiting(limit: 100, period: TimeSpan.FromMinutes(1));    // Limite de 100 req/min por IP
app.UseAuthenticationMiddleware();                                   // Validação de cabeçalho Authorization
app.UseCachingMiddleware(cacheDuration: TimeSpan.FromMinutes(2));    // Cache de 2 min para GET/HEAD
app.UseExceptionHandling();                                          // Fallback global para falhas 500
app.UseStatusCodeMiddleware();                                       // Tradução de exceções tipadas de negócio

// 3. Seus endpoints limpos e focados no negócio
app.MapGet("/api/saudacao", () => Results.Ok(new { mensagem = "Olá, mundo!" }));

app.Run();

🎮 Executando o Showcase Interativo

Para ver todos os 6 middlewares operando juntos em tempo real com documentação Swagger / OpenAPI interativa:

dotnet run --project examples/MiddlewareLibrary.Showcase

Abra seu navegador na URL indicada pelo terminal (ex: http://localhost:5000 ou http://localhost:5299) para explorar a interface Swagger e testar ao vivo:

  • GET /api/demo/ok: Demonstra o cabeçalho X-Response-Time-Ms com tempo de resposta em tempo real.
  • GET /api/demo/cache: Demonstra cache em memória de 30 segundos variando por parâmetro ?categoria=X.
  • GET /api/demo/rate-limit: Teste de saturação retornando status 429 após 5 requisições em 30 segundos.
  • GET /api/demo/auth-protected: Demonstra a validação do cabeçalho Authorization: Bearer <token>.
  • GET /api/demo/exceptions/{tipo}: Disparo de exceções de negócio com tradução automática para ProblemDetails.

⚡ Desempenho & Evidências de Micro-benchmarks

A biblioteca foi projetada com foco em zero-allocation no hot path, pooling de memória e alta vazão concorrente. A solução possui 6 suítes de micro-benchmarks científicos auditados via BenchmarkDotNet:

<p align="center"> <img src="assets/benchmark-terminal.png" alt="Evidência de Execução Real no Terminal com BenchmarkDotNet" width="100%" /> </p>

dotnet run -c Release --project benchmarks/MiddlewareLibrary.Benchmarks

<details> <summary><b>📊 Ver detalhamento técnico e catálogo dos 6 cenários (Clique para expandir)</b></summary>

<br />

Benchmark Métrica Avaliada Destaque Técnico
RequestTimingBenchmarks Stopwatch.StartNew() vs. Stopwatch.GetTimestamp() 0 B de alocação de Heap e tempo na ordem de ~2 ns.
CachingBufferingBenchmarks Stream.CopyToAsync vs. ArrayPool<byte>.Shared (4KB e 32KB) 0 B alocados por chamada reutilizando buffers de memória.
FullPipelineOverheadBenchmarks Overhead total de execução do InvokeAsync por requisição Latência imperceptível adicionada à cadeia do pipeline (< 50 ns).
RateLimitingBenchmarks Vazão e contenção do bloqueio de IP concorrente em memória Operação thread-safe em nanossegundos com zero alocação adicional.
ProblemDetailsSerializationBenchmarks Serialização JSON do ProblemDetails e pattern matching de 12 exceções Resolução instantânea do switch tipado com baixo consumo de CPU.
CacheKeyGenerationBenchmarks Concatenação de Método + Rota + QueryString Otimização na formação de chaves de cache para diferentes tamanhos de URL.

</details>


🛡️ Catálogo de Exceções de Domínio

A biblioteca disponibiliza 12 exceções prontas para uso. Quando lançadas no seu serviço, o StatusCodeMiddleware converte automaticamente para a resposta HTTP correspondente:

Exceção Status HTTP Quando utilizar no seu código de negócio
BadRequestException 400 Dados de entrada inválidos ou regras de validação violadas.
UnauthorizedException 401 Usuário não autenticado ou credenciais ausentes.
ForbiddenException 403 Usuário autenticado, mas sem permissão para acessar o recurso.
NotFoundException 404 Registro, entidade ou recurso não encontrado no banco.
NotAcceptableException 406 O formato solicitado no cabeçalho Accept não é suportado.
ConflictException 409 Conflito de estado (ex: tentativa de cadastrar CPF/E-mail já existente).
UnsupportedMediaTypeException 415 Formato de payload não suportado (ex: XML enviado em API apenas JSON).
LockedException 423 Recurso bloqueado temporariamente por concorrência.
TooManyRequestsException 429 Limite de requisições excedido pelo cliente.
BadGatewayException 502 Falha de resposta em uma API externa ou serviço de terceiros.
GatewayTimeoutException 504 Timeout ao aguardar resposta de serviço dependente.
InsufficientStorageException 507 Falta de espaço em disco ou cota de armazenamento estourada.

🏛️ Arquitetura e Decisões de Engenharia

Para entender detalhadamente as decisões de design, trade-offs e a topologia do pipeline:


🤝 Contribuição

Contribuições são muito bem-vindas! Ao submeter melhorias:

  1. Abra uma issue para discutir a proposta ou relatar algum comportamento inesperado.
  2. Certifique-se de que novos métodos assíncronos retornem Task ou ValueTask (zero async void).
  3. Mantenha a conformidade com as versões suportadas (.NET 6.0, .NET 8.0 e .NET 9.0).
  4. Acompanhe novas funcionalidades com testes automatizados em MiddlewareLibrary.Tests.

📄 Licença

Este projeto é distribuído sob a licença MIT.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net6.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.5.0 106 9/28/2026
0.4.0 89 9/25/2026
0.3.1 100 9/22/2026
0.3.0 102 9/18/2026
0.2.0 114 9/11/2026
0.1.1 114 9/7/2026
0.1.0 108 9/7/2026
0.0.1-beta.2 90 8/28/2026