Mateus Cavalcanti13 de set. de 20263 minBackend
APIBackendExpressNode.jsSegurançaZod

Criando APIs robustas com Node.js e Express

Uma API pronta para produção precisa ser previsível sob alta carga, segura contra ataques comuns e fácil de manter ao longo do tempo.

Embora o Express seja um microframework minimalista, adotar convenções rígidas de validação de dados, tratamento de erros e segurança HTTP transforma uma aplicação básica em um serviço backend robusto e escalável.


1. Validação estrita de entrada com Zod

Nunca confie em dados enviados pelo cliente. A melhor abordagem é validar os payloads logo na camada de entrada antes que atinjam as regras de negócio:

import type { Request, Response, NextFunction } from "express";
import { z, type AnyZodObject } from "zod";

// Middleware genérico para validação de requisições
export const validate = (schema: AnyZodObject) => {
  return async (req: Request, res: Response, next: NextFunction) => {
    const result = await schema.safeParseAsync({
      body: req.body,
      query: req.query,
      params: req.params,
    });

    if (!result.success) {
      return res.status(400).json({
        error: "Validation failed",
        details: result.error.flatten().fieldErrors,
      });
    }

    req.body = result.data.body;
    return next();
  };
};

// Schema declarativo de exemplo
export const CreateUserSchema = z.object({
  body: z.object({
    name: z.string().min(2, "Nome deve ter pelo menos 2 caracteres"),
    email: z.string().email("Formato de e-mail inválido"),
    role: z.enum(["admin", "user"]).default("user"),
  }),
});

2. Tratamento centralizado de erros

Erros não capturados podem derrubar o processo do Node.js. Crie um middleware de erro centralizado ao final da cadeia de rotas para padronizar as respostas HTTP e evitar o vazamento de stack traces em ambiente de produção:

import type { Request, Response, NextFunction } from "express";

export class AppError extends Error {
  constructor(
    public readonly statusCode: number,
    public readonly message: string,
    public readonly details?: unknown
  ) {
    super(message);
    Object.setPrototypeOf(this, new.target.prototype);
  }
}

export function errorHandler(
  err: unknown,
  _req: Request,
  res: Response,
  _next: NextFunction
) {
  if (err instanceof AppError) {
    return res.status(err.statusCode).json({
      status: "error",
      message: err.message,
      ...(err.details ? { details: err.details } : {}),
    });
  }

  // Log estruturado do erro interno
  console.error("[InternalError]:", err);

  return res.status(500).json({
    status: "error",
    message: process.env.NODE_ENV === "production" ? "Erro interno do servidor" : String(err),
  });
}

3. Checklist de Segurança e Produção

  1. Cabeçalhos de segurança: Utilize helmet para configurar cabeçalhos defensivos como Content-Security-Policy, X-Content-Type-Options e remoção do X-Powered-By.
  2. Rate Limiting: Proteja endpoints de autenticação e rotas públicas contra ataques de força bruta com express-rate-limit.
  3. CORS configurado de forma explícita: Nunca utilize origin: "*" em ambientes onde autenticação baseada em cookies ou tokens confidenciais é necessária.
  4. Arquitetura modular em camadas:
    • modules/<feature>/<feature>.routes.ts: Definição de rotas e middlewares.
    • modules/<feature>/<feature>.controller.ts: Orquestração de requisição/resposta HTTP.
    • modules/<feature>/<feature>.service.ts: Lógica de negócio pura e desacoplada do Express.
    • modules/<feature>/<feature>.schema.ts: Schemas Zod para tipagem e validação.

Isolando cada responsabilidade, sua API se torna testável, previsível e pronta para escalar com consistência.

Busca Global e Comandos

Navegue por artigos, projetos, certificações ou execute comandos rápidos.