Pular para conteúdo

Rate Limiting

Sistema de rate limiting per-user com 4 políticas configuráveis, aplicado nos endpoint groups via .RequireRateLimiting().

Visão Geral

O rate limiting protege a API contra abuso, limitando o número de requisições por usuário (ou IP) em janelas de tempo. A identificação do usuário segue a cadeia: JWT sub claim, IP remoto, "anonymous".

Resposta ao exceder o limite: HTTP 429 Too Many Requests


Arquivos Principais

Arquivo Descrição
src/Ciba.Shared/Constants/RateLimitPolicies.cs Constantes com nomes das políticas
src/Ciba.Api/Extensions/ServiceCollectionExtensions.cs Configuração das 4 políticas no AddApiRateLimiting()

Políticas

Api (Geral)

Propriedade Valor
Constante RateLimitPolicies.Api ("api")
Algoritmo Sliding Window
Janela 1 minuto
Limite 100 requisições
Segmentos 6 (janelas de 10s)
Fila 0 (rejeita imediatamente)
Partição JWT sub / IP / "anonymous"

Aplicada na maioria dos endpoint groups: - Agents, Conversations, Instances, Tenants, Users, LLM, SystemSettings

Login

Propriedade Valor
Constante RateLimitPolicies.Login ("login")
Algoritmo Fixed Window
Janela 5 minutos
Limite 10 tentativas
Fila 0
Partição IP apenas (JWT indisponível no login)

Aplicada exclusivamente no endpoint de autenticação.

Llm (Playground)

Propriedade Valor
Constante RateLimitPolicies.Llm ("llm")
Algoritmo Fixed Window
Janela 1 minuto
Limite 10 requisições
Fila 0
Partição JWT sub / IP / "anonymous"

Aplicada nos endpoints de Playground (chat, transcrição, descrição de imagem).

SendMessage

Propriedade Valor
Constante RateLimitPolicies.SendMessage ("send-message")
Algoritmo Fixed Window
Janela 1 minuto
Limite 25 mensagens
Fila 0
Partição JWT sub / IP / "anonymous"

Aplicada exclusivamente no endpoint de envio manual de mensagens.


Partition Key

A chave de partição é resolvida com fallback encadeado:

private static string GetPartitionKey(HttpContext context)
{
    return context.User.FindFirst("sub")?.Value
        ?? context.Connection.RemoteIpAddress?.ToString()
        ?? "anonymous";
}
Prioridade Fonte Cenário
1 JWT sub claim Usuário autenticado
2 IP remoto Requisição sem JWT (ex: webhook)
3 "anonymous" Sem JWT e sem IP (edge case)

Exceção: A política Login usa IP diretamente, pois o JWT ainda não existe no momento do login.


Constantes Centralizadas

// src/Ciba.Shared/Constants/RateLimitPolicies.cs
public static class RateLimitPolicies
{
    public const string Api = "api";
    public const string Login = "login";
    public const string Llm = "llm";
    public const string SendMessage = "send-message";
}

As constantes são compartilhadas entre Ciba.Api (configuração) e endpoints (aplicação).


Aplicação nos Endpoints

Cada endpoint group aplica a política via .RequireRateLimiting():

// Exemplo: AgentEndpoints.cs
var group = app.MapGroup(ApiRoutes.Agents.Base)
    .RequireAuthorization()
    .RequireRateLimiting(RateLimitPolicies.Api);

Mapeamento Endpoint -> Política

Endpoint Group Política
Auth Login
Agents Api
Conversations Api
SendMessage SendMessage
Instances Api
Tenants Api
Users Api
LLM Api
SystemSettings Api
Playground Llm

Configuração no DI

// ServiceCollectionExtensions.cs -> AddApiRateLimiting()
services.AddRateLimiter(options =>
{
    options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;

    options.AddPolicy(RateLimitPolicies.Api, context => { ... });
    options.AddPolicy(RateLimitPolicies.Login, context => { ... });
    options.AddPolicy(RateLimitPolicies.Llm, context => { ... });
    options.AddPolicy(RateLimitPolicies.SendMessage, context => { ... });
});

Resumo Visual

Requisição HTTP
    ├── Identificar usuário: JWT sub → IP → "anonymous"
    ├── Selecionar política: endpoint group → RequireRateLimiting(policy)
    ├── Verificar limite: contador da janela < PermitLimit?
    │   ├── Sim → Prossegue normalmente
    │   └── Não → HTTP 429 Too Many Requests

Regras

  1. Sempre usar constantes de RateLimitPolicies -- nunca strings mágicas
  2. Login usa IP -- não há JWT disponível antes da autenticação
  3. QueueLimit = 0 em todas as políticas -- requisições excedentes são rejeitadas imediatamente
  4. Sliding Window apenas para Api -- oferece distribuição mais suave; demais usam Fixed Window
  5. Novas políticas devem ser adicionadas em RateLimitPolicies.cs e configuradas em AddApiRateLimiting()