Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Respostas de Erro Estruturadas

Sem tratamento de erros, o Express retorna HTML genérico quando algo dá errado — inútil para um cliente que espera JSON. Vamos definir um formato consistente para a API:

{
  "error": {
    "code": "ROUTE_NOT_FOUND",
    "message": "A rota solicitada não existe."
  }
}

O campo code é um identificador legível por máquina (o frontend pode usar para decidir o que exibir). O message é uma descrição legível por humano, útil para debug.

Middleware de tratamento de erros

No Express, um middleware de erro é uma função com quatro parâmetros — err, req, res, next. O Express identifica o error handler pela aridade da função:

Arquivo: backend/src/errors/errorHandler.ts
import { Request, Response, NextFunction } from "express";

interface AppError extends Error {
  statusCode?: number;
  code?: string;
}

export function errorHandler(
  err: AppError,
  req: Request,
  res: Response,
  next: NextFunction,
) {
  console.error(err);

  const statusCode = err.statusCode ?? 500;
  const code = err.code ?? "INTERNAL_ERROR";
  const message = err.message ?? "Erro interno do servidor.";

  res.status(statusCode).json({
    error: { code, message },
  });
}

Código 5-14: Middleware que captura erros e responde com JSON estruturado.

Quando o controller chama next(err), o Express pula todos os middlewares normais e vai direto para esse handler. O erro é logado no console do servidor (para o desenvolvedor) e uma resposta JSON é enviada ao cliente.

Rota inexistente

Uma requisição para uma rota que não existe precisa retornar 404 com o nosso formato de erro. Adicione este middleware no app.ts, depois das rotas e antes do errorHandler:

app.use(eventsRoutes);

app.use((req: Request, res: Response, next: NextFunction) => {
  const err: AppError = new Error("A rota solicitada não existe.");
  err.statusCode = 404;
  err.code = "ROUTE_NOT_FOUND";
  next(err);
});

app.use(errorHandler);

Código 5-15: Middleware de 404 posicionado entre as rotas e o error handler no app.ts.

Testando:

$ curl -s http://localhost:3000/api/naoexiste | jq
{
  "error": {
    "code": "ROUTE_NOT_FOUND",
    "message": "A rota solicitada não existe."
  }
}

E se o banco de dados estiver fora do ar? O pool.query lança um erro com code = "ECONNREFUSED", que o middleware captura:

$ curl -s http://localhost:3000/api/events | jq
{
  "error": {
    "code": "ECONNREFUSED",
    "message": "connect ECONNREFUSED 127.0.0.1:5432"
  }
}

Repare que o code aqui é o código interno do Node.js, não um código de aplicação. E a mensagem expõe o IP e a porta do banco — em produção, isso seria um problema de segurança. No ambiente de desenvolvimento, essa transparência ajuda: você sabe imediatamente que o PostgreSQL não está rodando. A distinção entre erros públicos e internos vem num capítulo posterior1.


  1. O error handler vai precisar distinguir entre erros que o cliente pode ver (como “rota não encontrada”) e erros internos (como falha de conexão com o banco). Erros internos devem retornar uma mensagem genérica ao cliente e logar os detalhes apenas no servidor. ↩