Node.jsRESTAPIPatterns Node.jsRESTAPIPatterns

Node.js REST API Patterns 是一个专注于使用 Node.js 和 Express.js 构建 RESTful API 的技能,涉及到中间件模式、TypeScript 类型安全、RESTful 设计原则和分层架构。这个技能涵盖了认证、日志记录、错误处理和请求验证等多个关键领域,旨在提高开发速度、减少上市时间、提高可维护性和开发体验。

后端开发 0 次安装 0 次浏览 更新于 3/5/2026

Node.js REST API Patterns

概览

Node.js REST API 是使用 Node.js 和 Express.js 框架构建的 RESTful API,使用中间件模式处理跨领域关注点,如认证、日志记录、错误处理和验证。

Node.js REST API 包括:

  • Express.js: 构建 REST API 的 Web 框架
  • 中间件模式: 可链式调用的中间件用于请求/响应处理
  • TypeScript: 使用 TypeScript 进行类型安全的开
  • RESTful 设计: REST API 设计原则和最佳实践
  • 分层架构: 控制器-服务-仓库模式用于关注点分离

为什么这很重要

  • 提高开发速度: Node.js 可以将开发速度提高 2-3 倍
  • 减少上市时间: 快速开发减少了上市时间
  • 提高可维护性: 分层架构提高了可维护性
  • 增强开发体验: TypeScript 通过类型安全提高了 DX
  • 降低学习曲线: JavaScript 生态系统有社区支持和资源

核心概念

1. 项目结构

src/
├── config/              # 配置文件
│   ├── database.ts
│   ├── env.ts
│   └── constants.ts
├── controllers/          # 请求处理器
│   ├── user.controller.ts
│   └── auth.controller.ts
├── services/             # 业务逻辑
│   ├── user.service.ts
│   └── auth.service.ts
├── repositories/          # 数据访问层
│   ├── user.repository.ts
│   └── base.repository.ts
├── middleware/           # Express 中间件
│   ├── auth.middleware.ts
│   ├── error.middleware.ts
│   └── validation.middleware.ts
├── routes/               # 路由定义
│   ├── index.ts
│   ├── user.routes.ts
│   └── auth.routes.ts
├── types/                # TypeScript 类型
│   └── index.ts
├── utils/                # 工具函数
│   ├── logger.ts
│   └── response.util.ts
├── validators/           # 请求验证模式
│   └── user.validator.ts
├── app.ts                # Express 应用设置
└── server.ts             # 服务器入口点

2. Express.js 设置

import express, { Application } from "express"
import cors from "cors"
import helmet from "helmet"
import morgan from "morgan"
import { errorHandler } from "./middleware/error.middleware"
import routes from "./routes"

export function createApp(): Application {
  const app = express()

  // 安全
  app.use(helmet())

  // CORS
  app.use(cors())

  // 日志记录
  app.use(morgan("combined"))

  // 正文解析
  app.use(express.json())
  app.use(express.urlencoded({ extended: true }))

  // 路由
  app.use("/api", routes)

  // 错误处理(必须是最后)
  app.use(errorHandler)

  return app
}

3. 认证中间件

import { Request, Response, NextFunction } from "express"
import jwt from "jsonwebtoken"

interface JwtPayload {
  userId: string
  email: string
}

declare global {
  namespace Express {
    interface Request {
      user?: JwtPayload
    }
  }
}

export function authMiddleware(req: Request, res: Response, next: NextFunction) {
  const authHeader = req.headers.authorization

  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    throw new UnauthorizedError("No token provided")
  }

  const token = authHeader.substring(7)

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET!) as JwtPayload
    req.user = decoded
    next()
  } catch (error) {
    throw new UnauthorizedError("Invalid token")
  }
}

4. 错误处理中间件

export function errorHandler(
  error: Error,
  req: Request,
  res: Response,
  next: NextFunction
): void {
  logger.error(error, { path: req.path, method: req.method })

  if (error instanceof AppError) {
    return res.status(error.statusCode).json({
      success: false,
      message: error.message,
      ...(error.details && { details: error.details }),
    })
  }

  res.status(500).json({
    success: false,
    message: process.env.NODE_ENV === "production"
      ? "Internal server error"
      : error.message,
  })
}

5. 请求验证

import { AnyZodObject, ZodError } from "zod"

export function validate(schema: AnyZodObject) {
  return (req: Request, res: Response, next: NextFunction) => {
    const result = schema.safeParse(req.body)

    if (!result.success) {
      const errors = result.error.errors.map((err) => ({
        field: err.path.join("."),
        message: err.message,
      }))

      return res.status(400).json({
        success: false,
        message: "Validation failed",
        errors,
      })
    }

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

6. 控制器模式

export class UserController {
  constructor(private userService: UserService) {}

  async getAll(req: Request, res: Response, next: NextFunction) {
    try {
      const users = await this.userService.findAll()
      res.json({ success: true, data: users })
    } catch (error) {
      next(error)
    }
  }

  async getById(req: Request, res: Response, next: NextFunction) {
    try {
      const user = await this.userService.findById(req.params.id)
      res.json({ success: true, data: user })
    }
    catch (error) {
      next(error)
    }
  }

  async create(req: Request, res: Response, next: NextFunction) {
    try {
      const user = await this.userService.create(req.body)
      res.status(201).json({ success: true, data: user })
    } catch (error) {
      next(error)
    }
  }
}

7. 服务层模式

export class UserService {
  constructor(private userRepository: UserRepository) {}

  async findAll() {
    return this.userRepository.findAll()
  }

  async findById(id: string) {
    const user = await this.userRepository.findById(id)
    if (!user) {
      throw new NotFoundError("User not found")
    }
    return user
  }

  async create(data: CreateUserDto) {
    const existing = await this.userRepository.findByEmail(data.email)
    if (existing) {
      throw new ConflictError("Email already exists")
    }
    return this.userRepository.create(data)
  }

  async update(id: string, data: UpdateUserDto) {
    await this.findById(id)
    return this.userRepository.update(id, data)
  }

  async delete(id: string) {
    await this.findById(id)
    await this.userRepository.delete(id)
  }
}

8. 仓库模式

export class UserRepository extends BaseRepository<User> {
  constructor(prisma: PrismaClient) {
    super(prisma)
  }

  async findAll() {
    return this.prisma.user.findMany()
  }

  async findById(id: string) {
    return this.prisma.user.findUnique({ where: { id } })
  }

  async findByEmail(email: string) {
    return this.prisma.user.findUnique({ where: { email } })
  }

  async create(data: CreateUserDto) {
    return this.prisma.user.create({
      data: {
        ...data,
        password: await hashPassword(data.password),
      },
    })
  }

  async update(id: string, data: UpdateUserDto) {
    return this.prisma.user.update({
      where: { id },
      data,
    })
  }

  async delete(id: string) {
    return this.prisma.user.delete({ where: { id } })
  }
}

9. 依赖注入

class DIContainer {
  private static instance: DIContainer
  private repositories: Map<string, any>
  private services: Map<string, any>
  private controllers: Map<string, any>

  private constructor() {
    this.repositories = new Map()
    this.services = new Map()
    this.controllers = new Map()
    this.initialize()
  }

  private initialize() {
    this.repositories.set("user", new UserRepository(prisma))
    this.services.set("user", new UserService(this.repositories.get("user")))
    this.controllers.set("user", new UserController(this.services.get("user")))
  }

  getController(name: string) {
    return this.controllers.get(name)
  }
}

export const container = DIContainer.getInstance()

快速开始

  1. 初始化项目:

    npm init -y
    npm install express typescript @types/express
    
  2. 创建基本应用:

    import express from "express"
    const app = express()
    app.get("/", (req, res) => res.json({ hello: "world" }))
    app.listen(3000)
    
  3. 添加中间件:

    npm install helmet cors morgan
    
  4. 设置 TypeScript:

    npx tsc --init
    
  5. 启动服务器:

    npm run dev
    

生产清单

  • [ ] 使用 TypeScript 进行类型安全
  • [ ] 实现分层架构
  • [ ] 使用中间件处理跨领域关注点
  • [ ] 实现适当的错误处理
  • [ ] 添加请求验证
  • [ ] 实现认证和授权
  • [ ] 使用环境变量进行配置
  • [ ] 添加日志记录和监控
  • [ ] 为所有层编写单元测试
  • [ ] 为 API 端点编写集成测试
  • [ ] 使用 async/await 进行异步操作
  • [ ] 实现适当的 CORS 配置
  • [ ] 添加速率限制
  • [ ] 使用安全头(Helmet)
  • [ ] 为所有 API 文档化

反模式

  1. 阻塞事件循环: 正确使用 async/await
  2. 内存泄漏: 正确管理连接和计时器
  3. 未捕获异常: 实现全局错误处理程序
  4. 无验证: 始终验证所有输入
  5. 无日志记录: 记录所有请求和错误
  6. 无测试: 编写全面的测试
  7. 无文档: 为所有 API 文档化

集成点

  • Express REST: 03-backend-api/express-rest
  • 中间件: 03-backend-api/middleware
  • 错误处理: 03-backend-api/error-handling
  • 验证: 03-backend-api/validation
  • 认证: 10-authentication-authorization
  • 数据库优化: 04-database/database-optimization

进一步阅读