Building REST APIs with Express

Express setup, routing and route params, middleware chain, JSON body parsing and validation, error handling, and project structure for maintainable APIs.

BeginnerUpdated 2026-10-3071K views

Minimal API

import express from 'express';

const app = express();

// 内置中间件
app.use(express.json());              // 解析 JSON body
app.use(express.urlencoded({ extended: true }));

app.get('/health', (req, res) => res.json({ ok: true }));

app.listen(3000, () => console.log('api on :3000'));

Routing, Params and Validation

import { Router } from 'express';
import { body, validationResult } from 'express-validator';

const users = Router();

users.get('/:id', (req, res) => {
  res.json({ id: req.params.id, filter: req.query.q });
});

users.post('/',
  body('name').isLength({ min: 2 }),
  body('email').isEmail(),
  (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() });
    res.status(201).json(req.body);
  });

app.use('/api/users', users);        // 挂载路由器

Middleware Chain

An Express app is a stack of middleware: each function receives (req, res, next) and either ends the response or calls next(). This is where logging, auth, CORS and rate limiting live.

// 计时中间件
app.use((req, res, next) => {
  const start = Date.now();
  res.on('finish', () => {
    console.log(req.method, req.originalUrl, res.statusCode, Date.now() - start, 'ms');
  });
  next();
});

// 错误处理中间件(四个参数,放最后)
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(err.status || 500).json({ error: err.message || 'server error' });
});

// 常用生态
// morgan 日志 / helmet 安全头 / cors / express-rate-limit / cookie-session

Project Structure

src/
├── routes/        # 路由定义(Express Router)
├── controllers/   # 请求/响应处理
├── services/      # 业务逻辑(与框架无关)
├── models/        # 数据访问(Prisma / TypeORM)
├── middlewares/   # 自定义中间件
└── app.js         # 组装

Keep controllers thin: move business logic into services and data access into models, so the HTTP layer can be swapped or tested without touching the core.

Friends & Partners