轻松将 Swagger 与 Node.js REST API 集成
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