Spraxium logoSpraxium

Visão Geral do Pacote HTTP

Mapeie a arquitetura real de @spraxium/http desde a inicialização até a execução da requisição. Comece pelo modelo global de integração antes de aprofundar em roteamento, segurança, bridge e exceções.

O que este pacote controla

@spraxium/http é a fronteira de transporte entre seu bot do Discord e clientes HTTP externos. Ele inicializa um servidor baseado em Hono, aplica middleware e guards compartilhados, transforma metadados de controllers em rotas executáveis e expõe a abstração BotBridge para que controllers interajam com guilds, membros e APIs de moderação sem depender de um modo específico de runtime do Discord. Cada parte desse pipeline, da resolução do plugin ao desligamento gracioso, é gerenciada por um único serviço chamado HttpServer.

O pacote segue um modelo de três camadas. A configuração do plugin define comportamentos como host, porta, modo sharded e política de segurança. Os metadados do módulo declaram os controllers, services, guards e middleware que formam a superfície da API. O HttpServer lê essas duas camadas na inicialização e produz uma aplicação Hono totalmente conectada ao @hono/node-server. Essa separação faz com que decisões de configuração fiquem fora do código, contratos de rota fiquem nos decorators e a ligação de runtime fique escondida atrás de um ciclo de vida previsível.

Entender esse modelo de controle é o ponto central para usar o pacote com eficiência. Todas as outras páginas da categoria HTTP partem dessa base, então dedicar um tempo aqui evita confusão quando você chegar mais adiante em roteamento, segurança ou bridge.

Mapa interno do pacote

Hono como base HTTP

O pacote usa Hono como framework HTTP em vez de Express ou Fastify. Hono é um framework web leve, compatível com edge, que roda em qualquer runtime JavaScript padrão. O HttpServer cria uma instância new Hono() na inicialização, registra nela todos os middleware e handlers de rota, e depois passa app.fetch para @hono/node-server pela função serve() com o host e a porta configurados.

Esse desenho faz com que controllers e middleware interajam com os tipos Context e Next do Hono. Decorators de parâmetro como @HttpParam, @HttpQuery e @HttpHeader leem de ctx.req, enquanto handlers podem retornar objetos simples, serializados automaticamente para JSON, ou instâncias nativas de Response para controle total. Entender essa base em Hono ajuda quando você precisa acessar recursos fora da superfície de decorators, como ler corpos de requisição brutos ou definir headers de resposta customizados via ctx.res.

Modelo global de controle

Use um único caminho global de controle HTTP

Não crie um módulo wrapper local só para HTTP. Use seu AppModule raiz como fonte de metadados em defineHttp() e importe HttpModule uma única vez dentro do AppModule. Várias raízes de metadados geram comportamento ambíguo de guard, middleware e ciclo de vida.

O modelo de controle único significa uma entrada de plugin em spraxium.config.ts, um decorator @HttpClientModule no seu AppModule e uma importação de HttpModule no grafo de módulos. Esse padrão mantém explícito quem controla o ciclo de vida: o servidor faz bind uma vez, a política de guard é declarada uma vez e a ordem de middleware fica visível em um só lugar. Quando equipes dividem responsabilidades, elas adicionam controllers e services aos mesmos metadados de módulo, em vez de criar árvores de módulo concorrentes.

Essa restrição existe porque HttpServer lê os metadados de HttpClientModule a partir da classe referenciada em defineHttp({ module }). Se você criar um segundo módulo com seu próprio HttpClientModule, o servidor vai ignorá-lo porque apenas a referência raiz é resolvida. Manter tudo no AppModule evita desvio silencioso de configuração.

Retrato mínimo de integração

import { defineHttp } from '@spraxium/http';
import { AppModule } from '../src/app.module';

export const httpPlugin = defineHttp({
  enabled: true,
  host: process.env.HTTP_HOST ?? '0.0.0.0',
  port: Number(process.env.HTTP_PORT ?? 3000),
  apiKey: process.env.HTTP_API_KEY ?? '',
  sharding: false,
  security: {
    hidePoweredBy: true,
    cors: { origins: ['https://admin.example.com'], credentials: true },
  },
  module: AppModule,
});

Modos de inicialização: direto vs sharded

O HttpServer suporta dois caminhos de inicialização, dependendo da flag sharding em HttpConfig. Entender a diferença é importante porque isso afeta quando o servidor inicia, qual implementação de bridge é escolhida e se um Client do Discord está disponível no container de DI.

No modo direto (sharding: false), o servidor inicia durante onBoot e exige um Client do Discord injetado. Se o client estiver ausente, a inicialização é abortada com um erro registrado em log. BridgeFactory cria um DirectBotBridge que acessa guilds, membros e bans diretamente pelo cache e pelos métodos de API do client.

No modo sharded (sharding: true), o servidor não inicia durante onBoot. Em vez disso, um bloco estático em HttpServer registra um hook em ParentHookRegistry. Quando o processo pai cria os shards, esse hook recebe a instância de ShardingManager e inicia o servidor fora do ciclo normal de boot. BridgeFactory cria um ShardedBotBridge que usa manager.broadcastEval() para alcançar guilds em diferentes shards. Esse modo também armazena a referência do manager em HttpRegistry para que ela sobreviva ao contexto de inicialização estática.

Fluxo de runtime em resumo

Resolver a configuração do plugin

HttpServer lê a entrada do plugin HTTP em ConfigStore por meio de getPluginConfig(defineHttp). Esse objeto carrega host, porta, modo sharded, política de segurança e a referência da classe de módulo. Se nenhuma configuração for encontrada ou enabled estiver como false, o servidor pula totalmente a inicialização e registra um aviso.

Selecionar a estratégia de inicialização

No modo direto, onBoot exige um Client do Discord injetado. No modo sharded, um hook estático de ParentHookRegistry recebe o ShardingManager e chama server.start() fora do ciclo de vida normal. Os dois caminhos convergem para o mesmo método start(), que monta a aplicação Hono.

Criar o BotBridge

BridgeFactory.create() verifica se há um ShardingManager ou Client disponível e retorna o bridge correspondente. A instância do bridge é adicionada ao mapa de dependências da DI para que controllers e services possam injetar BotBridge como parâmetro de construtor.

Aplicar a camada global de segurança

O servidor registra middleware nesta ordem fixa: remoção de X-Powered-By, SecurityHeadersMiddleware, CorsMiddleware, BodyLimitMiddleware e depois qualquer middleware global customizado vindo dos metadados de HttpClientModule. Cada middleware é ligado ao caminho '*' para rodar antes de todos os handlers de rota.

Executar guards globais

Se HttpClientModule declarar guards, GuardExecutor os envolve em um middleware Hono executado em sequência. Quando qualquer guard retorna false, a execução para e o servidor responde com { ok: false, error: 'Unauthorized' } no status 401. Nenhum middleware ou handler adicional é executado.

Registrar controllers e services

RouteRegistry resolve primeiro os services usando ordenação topológica para respeitar a ordem de dependências e depois instancia os controllers com o mapa de dependências resolvido. RouteBuilder lê os metadados de rota de cada controller e faz o binding dos handlers no Hono com as cadeias de middleware de classe e de método já mescladas.

Resolver parâmetros e validar DTOs

Quando uma requisição chega ao handler, ParamResolver lê os metadados dos decorators de parâmetro e extrai valores de params, query, body, headers ou do Context completo do Hono. Se um decorator @HttpBody incluir uma classe DTO, ValidationPipe transforma o body bruto em uma instância tipada e o valida com regras do class-validator antes da execução do handler.

Normalizar erros e devolver a resposta

Handlers que retornam objetos simples são serializados automaticamente para JSON com status 200, ou um status customizado vindo de @HttpStatus. Se um handler retornar um Response nativo, Hono o repassa sem alterações. O handler onError normaliza exceções lançadas: ValidationError retorna 400 com detalhes, qualquer HttpError retorna seu próprio status code e exceções desconhecidas retornam 500 depois do log.

Desligamento gracioso

Durante onShutdown, o servidor fecha a instância subjacente de Server do Node.js e aguarda o escoamento das conexões ativas. O handler de shutdown também é registrado em SIGINT e SIGTERM no modo sharded para garantir que o servidor pare de forma limpa quando o processo pai for encerrado.

Roteiro da documentação

Cada página desta categoria cobre em profundidade uma camada da pilha HTTP. Leia na ordem para obter uma visão completa ou vá direto ao tópico específico quando precisar de uma referência pontual.

  1. Configuração e Setup com Módulo Único, cobrindo defineHttp, HttpConfig e o modelo de controle do módulo.
  2. Arquitetura de Pastas HTTP, cobrindo a organização de arquivos recomendada à medida que o número de endpoints cresce.
  3. Pipeline de Roteamento e Decorators, cobrindo decorators, resolução de parâmetros, validação de DTOs e modelagem de resposta.
  4. Segurança, Guards e Middleware, cobrindo a pilha de hardening, a interface de guard e a composição de middleware.
  5. Modos de Runtime do Bot Bridge, cobrindo o contrato de BotBridge, implementações diretas e sharded e serializers.
  6. Exceções e Tratamento de Erros, cobrindo a hierarquia de HttpError, os detalhes de ValidationError e a camada centralizada de normalização.