轻松将 Swagger 与 Node.js REST API 集成

发布: (2025年12月11日 GMT+8 20:45)
4 min read
原文: Dev.to

Source: Dev.to

Swagger 是记录 REST API 最简便的方式之一。它提供交互式 UI,开发者可以在其中测试接口、了解输入输出,并更快地集成你的 API。

本指南涵盖了在大型 Node.js 后端中集成 Swagger 的完整步骤,以及在开发和生产环境中让 Swagger UI 正常工作的修复方法。

1. 安装 Swagger 库

只需两个包。

npm install swagger-jsdoc swagger-ui-express

2. 创建 Swagger 配置文件

创建 docs/swagger.config.js

import swaggerJSDoc from "swagger-jsdoc";

const swaggerDefinition = {
  openapi: "3.0.0",
  info: {
    title: "Dining System API",
    version: "1.0.0",
    description: "API documentation for Dining System",
  },
  servers: [
    { url: process.env.DEV, description: "Development" },
    { url: process.env.PROD, description: "Production" },
  ],
  components: {
    securitySchemes: {
      bearerAuth: {
        type: "http",
        scheme: "bearer",
        bearerFormat: "JWT",
      },
    },
  },
  tags: [
    { name: "Authentication" },
    { name: "Users" },
    { name: "Vendors" },
    { name: "Bills" },
    { name: "Meal" },
  ],
};

const options = {
  swaggerDefinition,
  apis: ["./docs/routes/*.js"], // Load swagger route docs
};

export default swaggerJSDoc(options);

3. 在 app.js 中集成 Swagger UI

导入 Swagger UI 和规范:

import swaggerUi from "swagger-ui-express";
import swaggerSpec from "./docs/swagger.config.js";

添加 Swagger UI 路由:

const swaggerUiOptions = {
  customCss: ".swagger-ui .topbar { display: none }",
  customSiteTitle: "Dining System API Docs",
  swaggerOptions: {
    persistAuthorization: true,
    displayRequestDuration: true,
    filter: true,
  },
};

app.use(
  "/api-docs",
  swaggerUi.serve,
  swaggerUi.setup(swaggerSpec, swaggerUiOptions)
);

app.get("/api-docs.json", (req, res) => {
  res.setHeader("Content-Type", "application/json");
  res.send(swaggerSpec);
});

4. app.js 示例

import express from "express";
import cors from "cors";
import helmet from "helmet";
import cookieParser from "cookie-parser";
import authRoutes from "./routes/authRoutes.js";
import swaggerUi from "swagger-ui-express";
import swaggerSpec from "./docs/swagger.config.js";
import rateLimit from "express-rate-limit";
import dotenv from "dotenv";

dotenv.config();

const app = express();

// Swagger 应在 Helmet 之前加载
app.use(
  "/api-docs",
  swaggerUi.serve,
  swaggerUi.setup(swaggerSpec, {
    customCss: ".swagger-ui .topbar { display: none }",
    swaggerOptions: { persistAuthorization: true },
  })
);

// 为工具提供 JSON 接口
app.get("/api-docs.json", (req, res) => {
  res.setHeader("Content-Type", "application/json");
  res.send(swaggerSpec);
});

// Helmet 在 Swagger 之后应用
app.use(
  helmet({
    contentSecurityPolicy: false,
  })
);

app.use(cors());
app.use(express.json());
app.use(cookieParser());

const globalLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 300,
  message: { message: "Too many requests, please try again later." },
});
app.use(globalLimiter);

app.get("/", (req, res) => {
  res.send("Dining System API is running...");
});

app.use("/api/auth", authRoutes);
// ... other routes

app.use((err, req, res, next) => {
  console.error("Uncaught Error:", err);
  const payload = { message: err.message || "Internal Server Error" };
  if (process.env.NODE_ENV !== "production") payload.stack = err.stack;
  res.status(err.status || 500).json(payload);
});

export default app;

为什么 Swagger 必须在 Helmet 之前加载

Helmet 会阻止内联脚本,而 Swagger UI 依赖这些脚本。先加载 Swagger 可避免生产环境中 UI 空白的问题。

5. 为每个 API 模块创建单独的 Swagger 文件

不要在 Express 路由文件中混杂 Swagger 注释,而是创建专门的文件夹:

docs/routes/

示例结构:

docs/routes/auth.swagger.js
docs/routes/users.swagger.js
docs/routes/vendors.swagger.js
docs/routes/bills.swagger.js
docs/routes/meal.swagger.js

示例 Swagger 文件(auth.swagger.js):

/**
 * @swagger
 * /api/account-types/list:
 *   get:
 *     summary: Get all account types
 *     tags: [Account Types]
 *     security: [{ bearerAuth: [] }]
 *     responses:
 *       200:
 *         description: OK
 */

Swagger 会通过 apis 配置自动加载这些文件:

apis: ["./docs/routes/*.js"]

6. 重启并测试 Swagger

开发环境

npm run dev

打开 Swagger UI:

http://localhost:5000/api-docs

生产环境(PM2)

git pull
npm install
pm2 restart all

打开 Swagger UI:

http://your-production-url/api-docs

7. 遇到的问题及解决方案

1. 生产环境中 Swagger UI 空白

  • 原因: Helmet 阻止了内联脚本。
  • 解决: 如上所示禁用 CSP(contentSecurityPolicy: false)。

2. 更改后 Swagger 未更新

  • 原因: PM2 仍在运行旧的构建。
  • 解决: 重启服务器。
pm2 restart all

3. Swagger 路由文件未加载

  • 原因: 配置中的文件夹路径错误。
  • 解决: 使用正确的路径。
apis: ["./docs/routes/*.js"]

8. 推荐的文件夹结构

docs/
  swagger.config.js
  routes/
    auth.swagger.js
    users.swagger.js
    vendors.swagger.js
    bills.swagger.js
    meal.swagger.js

routes/
controllers/
models/
app.js
server.js
Back to Blog

相关文章

阅读更多 »

创建您的第一个 MCP 应用

TL;DR MCP 应用为对话代理和其他 MCP 客户端带来交互式 UI。 本教程展示了如何创建一个既简单又强大的应用源代码……

实验性 Hono auth npm 包

我正在构建的东西:我正在创建一个 auth package,开发者可以将其直接放入他们的应用中,而无需编写常规的登录、注册、JWT、电子邮件验证等样板代码。