Receber por email
← Voltar para o catálogo

api-framework-express

Express.js routes, middleware, error handling, request/response patterns

11estrelas
Atualizado há 7 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add agents-inc/skills

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/api-framework-express/svg)](https://www.skillteca.com.br/skills/api-framework-express)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

API Development with Express.js

Quick Guide: Express uses middleware-based request processing. The three non-negotiable patterns: modular routing via express.Router(), centralized error handling with 4-argument middleware (err, req, res, next), and correct middleware ordering (security first, error handler last). Express 5 (now stable, default on npm) auto-forwards async errors; Express 4 requires manual next(err) or a wrapper.

<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST define error-handling middleware with 4 arguments: (err, req, res, next) - Express identifies error handlers by arity)

(You MUST register error handlers AFTER all routes and other middleware)

(You MUST call next(err) to forward async errors in Express 4 - Express 5 auto-forwards rejected promises)

(You MUST use express.json() and express.urlencoded() for body parsing - req.body is undefined without them)

</critical_requirements>

Auto-detection: Express.js, express, app.use, app.get, app.post, app.put, app.delete, express.Router, req.params, req.query, req.body, res.json, res.status, middleware, next(), error handler, router.use, express.static, express.json, express.urlencoded

When to use:

  • Building REST APIs with composable middleware patterns
  • Need modular route organization with express.Router()
  • Require centralized error handling across all routes
  • Building APIs that need body parsing, static files, or cookie handling
  • Creating route guards for authentication/authorization

When NOT to use:

  • Need auto-generated OpenAPI documentation from schemas
  • Building edge/serverless functions where cold start matters
  • Need strict end-to-end type safety with schema validation
  • GraphQL APIs (use a dedicated GraphQL server)

Key patterns covered:

  • Middleware chain with app.use() and next()
  • Modular routes with express.Router()
  • Error handling with 4-argument middleware
  • Async error forwarding (Express 4 vs 5)
  • Request validation middleware
  • Route parameters and query string handling
  • Route guards for authentication/authorization
  • Middleware ordering (security, CORS, rate limit, parsing, routes, errors)

Detailed Resources:

  • [examples/core.md](examples/core.md) - App setup, error handler, async handler, body parsing
  • [examples/middleware.md](examples/middleware.md) - Logging, validation, auth guards, middleware ordering
  • [examples/routing.md](examples/routing.md) - Modular routes, parameters, response helpers, versioned APIs
  • [reference.md](reference.md) - Decision frameworks, anti-patterns, production checklist

<philosophy>

Philosophy

Middleware-first architecture. Express processes requests through a chain of middleware functions. Each middleware can modify request/response objects, end the response, or call next() to continue the chain. Everything in Express is middleware - body parsers, auth guards, loggers, error handlers.

Express 4 vs 5: Express 5 (stable since 2025, now default on npm) auto-forwards errors from rejected promises in async handlers. Express 4 requires explicit try/catch + next(err) or a wrapper utility. Both versions require the 4-argument signature for error handlers.

</philosophy>

<patterns>

Core Patterns

Pattern 1: Application Setup

Register body parsers early, mount route modules, register error handler last. See [examples/core.md](examples/core.md) for full implementation.

const app: Express = express();

// Body parsing
app.use(express.json({ limit: JSON_LIMIT }));
app.use(express.urlencoded({ extended: true }));

// Mount route modules
app.use("/api/users", userRoutes);
app.use("/api/products", productRoutes);

// Error handler MUST be last
app.use(errorHandler);

export { app };

Why good: Body parsers before routes so req.body is populated, error handler last to catch all errors, modular route mounting

Pattern 2: Modular Routes with express.Router()

One Router per resource, mounted at a path prefix. See [examples/routing.md](examples/routing.md) for CRUD examples with parameters.

// src/routes/user-routes.ts
const router = Router();

router.get("/", async (req, res, next) => {
  try {
    const users = await getUsersFromDatabase();
    res.status(HTTP_OK).json({ data: users });
  } catch (error) {
    next(error);
  }
});

export { router as userRoutes };

Why good: Router isolates related routes, named export, explicit error forwarding

Pattern 3: Error Handling Middleware (4 Arguments)

Express identifies error handlers by the 4-argument signature (err, req, res, next). This is the most critical Express pattern to get right. See [examples/core.md](examples/core.md) for full implementation.

// CRITICAL: Must have exactly 4 arguments
const errorHandler = (
  err: AppError,
  req: Request,
  res: Response,
  next: NextFunction,
): void => {
  if (res.headersSent) {
    next(err);
    return;
  }

  const statusCode = err.statusCode || HTTP_INTERNAL_ERROR;
  res.status(statusCode).json({
    error: { message: err.message, code: err.code || "INTERNAL_ERROR" },
  });
};

Why good: 4 arguments for Express to recognize as error handler, checks headersSent to avoid double-response, consistent error shape

Common mistake: 3-argument function (err, req, res) is treated as regular middleware - err becomes req, completely wrong behavior

Pattern 4: Async Error Handling

Express 5 auto-forwards rejected promises. Express 4 requires explicit forwarding. See [examples/core.md](examples/core.md) for the asyncHandler wrapper.

// Express 5: async errors auto-forwarded
router.get("/:id", async (req, res) => {
  const product = await getProductById(req.params.id);
  res.status(HTTP_OK).json({ data: product });
});

// Express 4: MUST forward manually
router.get("/:id", async (req, res, next) => {
  try {
    const product = await getProductById(req.params.id);
    res.status(HTTP_OK).json({ data: product });
  } catch (error) {
    next(error); // Required in Express 4
  }
});

Why this matters: In Express 4, unhandled async rejections cause the request to hang until timeout. Express 5 fixes this but many projects still run Express 4.

Pattern 5: Request Validation Middleware

Validate req.body in middleware before the route handler processes it. See [examples/middleware.md](examples/middleware.md) for full validation patterns.

const validateUserCreate = (
  req: Request,
  res: Response,
  next: NextFunction,
): void => {
  const { name, email } = req.body;
  const errors: string[] = [];

  if (!name || name.length < MIN_NAME_LENGTH) errors.push("Name is required");
  if (!email || !email.includes("@")) errors.push("Valid email is required");

  if (errors.length > 0) {
    res
      .status(HTTP_BAD_REQUEST)
      .json({ error: { message: "Validation failed", details: errors } });
    return;
  }
  next();
};

// Apply: router.post("/", validateUserCreate, createHandler);

Why good: Validation separated from business logic, early return on failure, reusable across routes

Pattern 6: Route Guards (Authentication/Authorization)

Protect routes with middleware that validates access. See [examples/middleware.md](examples/middleware.md) for full auth guard implementation.

// Extend Request with user data
interface AuthenticatedRequest extends Request {
  user?: { id: string; role: string };
}

const requireAuth = (
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction,
): void => {
  const token = req.headers.authorization?.replace("Bearer ", "");
  if (!token) {
    res
      .status(HTTP_UNAUTHORIZED)
      .json({ error: { message: "Authentication required" } })
Compartilhar X LinkedIn