REST API文档是一种指南,它说明了客户端如何在应用程序中使用这些REST API。该文档详细介绍了可用的接口端点、发送请求的方法以及预期会收到的响应内容。此外,它还可能包含与特定应用程序范围相关的概念说明。
如果没有API文档,应用程序的开发就被视为不完整的,因为开发者无法构建能够与之交互的软件,这样一来,该应用程序实际上就失去了其实际用途。
在本文中,您将学习如何制作美观的REST API文档,并且还能了解如何使用OpenAPI规范以及Node.js项目中的Scalar工具来免费测试这些API。您将会使用asteasolutions/zod-to-openapi生成OpenAPI规范,然后利用Scalar根据该规范创建网页。
为了充分理解本文的内容,您应该具备使用Express或NestJS开发REST API的经验,同时也应该熟悉REST API文档的编写方法以及zod这个工具的使用方法。
目录
适用于Node.js的REST API文档工具
目前已经存在多种用于编写REST API文档的工具,这些工具根据不同的使用场景各具优缺点。有些工具完全可以免费使用,而有些则采用免费增值模式;其中一些工具提供了测试API的功能,另一些则仅提供展示文档的界面。
在Node.js项目中,一些最常用的REST API文档工具如下:
-
Swagger
-
Postman
-
Redoc
Swagger
若要在Express框架中使用Swagger来编写REST API文档,你需要安装swagger-jsdoc和swagger-express-ui这两个插件。swagger-jsdoc会整理并解析代码库中带有JSDoc注释的文档内容,从而生成OpenAPI规范文档;而swagger-express-ui则会利用这些生成的文档来创建网页,用于展示API文档并测试相关接口。
Swagger的一大优势在于它支持OpenAPI规范这一行业标准。Swagger可以免费使用,拥有活跃的开源社区,并且对许多编程语言和框架都提供了良好的支持。不过,它仅适用于REST API文档的编写。
它的主要缺点在于:开发者需要手动编写JSDoc注释或YAML格式的文档内容,这个过程相对繁琐,而且开发者很容易忘记添加某些必要的注释;此外,JSDoc注释有时会干扰对功能代码的理解;最后,一些开发者也认为它的用户界面不够直观、使用起来比较麻烦。
Postman
Postman是一款基于云端的桌面API客户端工具,它允许开发人员和技术文档编写者来创建、测试、协作并发布API文档。与Swagger不同,使用Postman的大部分功能并不需要深厚的编程经验;此外,它不仅适用于REST API文档的编写,还可以用于生成GraphQL、WebSocket和gRPC等类型的API文档。
Postman并不遵循OpenAPI规范,但它提供了用户界面来填写API文档的详细信息。不过,文档编写过程属于手动操作,有时生成的内容可能与实际部署的应用程序的功能不符。对于团队协作而言,Postman并非免费工具;此外,它也无法完全展示浏览器与API之间的交互行为,例如CORS和流式传输等功能。
Redoc
ReDoc是一款开源工具,它可以根据OpenAPI(尤其是Swagger)规范自动生成API文档。ReDoc支持GraphQL、AsyncAPI等技术,并且生成的文档效果比Swagger更美观。而redoc-express插件则可以帮助使用Express框架的开发者利用ReDoc来编写REST API文档。
asteasolutions/zod-to-openapi是一个TypeScript库,它能够根据zod提供的模式生成OpenAPI规范。该工具提供了类型化的方法,这些方法可以作为记录API组件的规范指南,从而避免使用代码注释来完成同样的工作。这样一来: 这些库方法能明确指出哪些内容需要被记录,以及应该如何进行记录。 整个代码库中的文档格式会保持一致。 这样的文档生成方式不会影响代码的可读性。 下面是一个使用zod-to-openapi来记录创建用户的POST请求的示例: Scalar是一个工具,它能够根据OpenAPI文档生成美观、结构清晰且易于搜索的API文档。生成的文档还支持对API进行测试,因此Scalar实际上同时具备API文档生成器和轻量级API客户端的功能。下图展示了一例由Scalar生成的文档示例: zod-to-openapi负责将代码转换为OpenAPI规范,而Scalar则利用这些规范来生成结构清晰、易于阅读的文档网页,并同时支持对API进行测试。 当您将zod-to-openapi与Scalar结合在一起,用于为您的Express应用程序生成REST API文档时,将会获得许多显著的优势。以下是一些具体的好处: 请求路径、方法、头部信息、路径参数以及查询参数, 请求与响应数据结构的格式规范, 认证相关要求, 那些无法通过其他组件来处理的信息的描述, zod-to-openapi提供了将上述所有内容纳入文档编写的方法,并能生成符合OpenAPI规范格式的文档,而Scalar则会利用这些文档来生成相应的网页。 zod-to-openapi是开源项目,可供免费使用。由于其创建者与Ruby on Rails、Laravel等项目的开发者一样,在日常工作中也在使用它,因此该项目短期内不会被停止支持或废弃。 Scalar同样也是开源软件。虽然它提供付费版本,但付费版本中的功能主要适用于企业级应用;而免费版本已经具备了生成高质量REST API文档所需的所有基本功能。 从用户体验的角度来看,结合使用zod-to-openapi和Scalar能够带来以下诸多好处: zod-to-openapi提供的一系列方法能够确保开发者不会遗漏或忽略对API关键组件的文档描述。同时,由于这些方法的参数具有类型约束,因此这些组件的文档格式也能严格符合OpenAPI规范。 使用zod-to-openapi时,无需通过注释或YAML文件来记录API信息,而是直接利用该工具提供的方法来完成文档编写。这样就能避免代码中充斥大量注释,也省去了手动更新庞大的OpenAPI规范文件所带来的繁琐工作。 当使用zod-to-openapi和Scalar时,应用程序运行时会自动生成API文档。zod-to-openapi负责对这些文档内容进行整理和编译,而Scalar则会将这些文档转换成可以在同一应用程序的API接口页面上展示的网页形式。因此,完全不需要手动执行任何命令来生成文档。 高精度与自动生成的特性还有一个重要好处,那就是无需将API文档编写工作分配给技术文档编写者和后端开发人员。因为文档信息直接嵌入在代码中,所以这种机制能够显著提升API文档编写的效率,使开发流程更加流畅。 虽然Swagger的用户界面功能完备,但一些开发者认为其在显示详细接口信息时的呈现效果较为简单。ReDoc在视觉设计上有所改进,但没有提供API测试功能;而Scalar则提供了比ReDoc更精致、更直观的用户界面,并且具有更多的自定义选项。 除了出色的设计之外,Scalar还能自动生成多种编程语言的代码示例,这使得开发者能够根据自己所使用的具体技术栈,更加高效地实现API集成工作。 Scalar的UI提供了搜索功能,使开发人员能够快速找到API文档中的特定内容。它还配备了AI聊天界面,帮助用户了解不同的API端点如何满足他们的具体需求。这种方式比手动阅读整个文档要高效得多。 最后,你还可以通过UI来测试API端点。当你进行经过身份验证的API请求时,UI会缓存认证令牌,这样在后续请求中就无需重新输入或粘贴这些令牌了。 zod-to-openapi和Scalar都支持Markdown格式。使用Markdown,你可以添加概念性说明,以及关于那些无法通过默认文档组件(如标题栏或请求体)来呈现的API端点的更多信息。 你可以在文档中嵌入图片、添加表格,并对文本进行格式化处理。利用Markdown,你还可以编写解释API相关概念的注释。 在本节中,你将创建一个使用zod-to-openapi和Scalar来生成API文档的Express CRUD项目。为了便于练习,请从GitHub上克隆orimdominic/freeCodeCamp-zod-to-openapi-scalar处的Express入门项目。 克隆项目后,请按照以下步骤操作: 使用你喜欢的Node.js包管理器安装该项目所需的依赖项 使用 如果应用程序成功运行,你将在终端中看到如下输出: 该项目包含两个模块:Users和Pets。 每个模块的路由配置都定义在 使用你喜欢的Node.js包管理器安装asteasolutions/zod-to-openapi。如果你使用的是npm,在终端中运行以下命令: 安装完成后,在 将以下代码片段复制并粘贴到 ` “zod-to-openapi v8”要求使用 zod v4;如果您使用的是 zod v3,那么应该使用 zod-to-openapi 的 v7.3.4 版本。 在加载任何使用 另一种方法是,在 zod v4 的模型中使用 与类型化的 在 当 一旦完成了这样的配置,当使用注册系统来记录API端点信息时, 在本节中,你将配置Scalar,并将其与 Scalar提供了一个Express API参考库,这使得将其与OpenAPI规范及Express框架结合使用变得更加方便。你可以使用自己喜欢的Node.js包管理器来安装 将下面的代码片段复制并粘贴到 在上面的代码片段中,`generateOpenAPIDocument`函数是从`src/lib/openapi.ts`文件导入的,而`apiReference`模块则是从`@scalar/express-api-reference`路径导入的。当这个函数被执行时,它会生成OpenAPI规范文档,这些文档会被存储在`apiDocJsonContent`变量中,以便后续进行缓存处理,从而提升应用程序的性能。 接下来会创建一个`GET /docs`路由,而Scalar框架中的`apiReference`功能模块将作为这个路由的控制器。每当有人访问`GET /docs`这个路由时,`apiReference`模块就会使用`apiDocJsonContent`变量来生成相应的网页内容并返回给用户。 完成这样的配置后,可以使用`npm run serve`命令来运行应用程序,然后通过浏览器访问`http://localhost:3000/docs`这个地址,你应该会看到一个类似于下图所示的用户界面: 为了查看当前的代码库内容,可以执行`git checkout set-up-openapi-scalar`命令。 ## 记录应用程序中的端点信息 你已经完成了将zod框架与OpenAPI规范进行集成,并且也将它与Scalar框架连接了起来;同时,你还把相关的路由配置到了后端应用程序中。在这一节中,你需要编写代码来记录应用程序中的各个端点信息,这样就可以生成OpenAPI规范文档,并将这些文档显示在用户界面上了。 以创建用户的路由为例,在`src/modules/users/router.ts`文件中,可以使用以下代码片段来导入所需的模块和类型定义: “`typescript 将下面的代码复制并粘贴到创建用户路由的相应位置,这样就可以记录这个端点的详细信息了: “`typescript 访问文档页面后,你应该会看到一个类似于下图所示的网页界面: 点击“测试请求”按钮 在出现的对话框中填写请求数据 然后点击“发送”按钮 配置完成之后,你可以在浏览器中访问 如果你在Express或NestJS项目中使用了Helmet,那么在尝试渲染Scalar文档的用户界面时,你可能会遇到与内容安全策略相关的问题。为了解决这些错误,请将代码中的 Helmet CSP配置更新为以下内容: 在本文撰写时,Scalar尚未完全支持为基于事件驱动架构的API生成异步API规范,不过这一功能目前仍在开发中。你可以通过文档中提供的GitHub链接来关注其开发进度,以便及时了解它的发布情况。 你已经了解了zod-to-openapi这个工具,它能够让你更轻松地为REST API生成OpenAPI规范,而无需编写大量的注释或复杂的YAML文件。你还学会了如何利用生成的规范文档来渲染美观的API文档用户界面,这些界面同时也可以作为轻量级的API客户端使用。如果你的项目需要改进文档质量,不妨尝试使用这个工具。 如果有任何疑问或需要进一步说明,请随时在LinkedIn上与我联系。感谢你阅读到这里,希望这些内容能帮助你实现目标。如果你认为这篇文章对他人也有帮助,欢迎分享给更多人哦!祝好!zod-to-openapi与Scalar在REST API文档生成中的应用
// CreateUser和User都是zod模式定义的类型
registry.registerPath({
method: "post",
path: "/api/users",
summary: "创建用户",
tags: ["users"],
request: {
body: {
content: {
"application/json": {
schema: schema.CreateUser,
},
},
description: "用于创建用户的请求数据",
required: true,
},
},
responses: {
201: {
description: "用户创建成功",
content: {
"application/json": {
schema: z.object({
message: z.string(),
data: schema.User,
}),
},
},
},
},
});
zod-to-openapi与Scalar如何协同工作

使用zod-to-openapi和Scalar生成REST API文档的好处
OpenAPI规范的支持
开源且免费使用
更优质的文档编写体验
zod-to-openapi提供的方法为文档编写提供了有力保障
避免使用注释和YAML文件带来的麻烦
高精度且自动生成的文档
对开发者友好的用户界面
Markdown支持
如何创建API文档
配置项目
serve脚本启动服务器# 安装依赖项
npm run install
# 启动应用程序
npm run serve
> freecodecamp-zod-to-openapi-scalar@1.0.0 serve
> node --experimental-strip-types --watch src/index.ts
正在监听3000端口
router.ts文件中,而相应的路由控制器则位于各模块文件夹下的src/modules目录中的controllers.ts文件里。这些控制器并不包含业务逻辑,它们只是会返回由Faker库生成的JSON数据作为响应。如何配置zod-to-openapi
npm install @asteasolutions/zod-to-openapi
src文件夹下创建一个名为lib的文件夹,再在该文件夹中创建一个名为openapi.ts的文件。这个文件将用于配置zod-to-openapi,以便整理API文档并生成OpenAPI规范。src/lib/openapi.ts` 文件中:import z from "zod";
import {
extendZodWithOpenApi,
OpenApiGeneratorV3,
OpenAPIRegistry,
} from "@asteasolutions/zod-to-openapi";
extendZodWithOpenApi(z);
export const registry = new OpenAPIRegistry();
export const bearerAuth = registry.registerComponent("securitySchemes", "bearerAuth", {
type: "http",
scheme: "bearer",
bearerFormat: "JWT",
});
export function generateOpenAPIDocument() {
const generator = new OpenApiGeneratorV3(registry.definitions);
return generator.generateDocument({
openapi: "3.1.1",
info: {
title: "Users API",
version: "1.0.0",
description: `后端API文档,用于用户管理应用。`,
},
tags: [
{
name: "users",
description: "用于管理员执行的操作。",
},
],
servers: [
{
url: "http://localhost:3000",
description: "本地服务器。"
},
],
});
}
extendZodWithOpenApi 是 zod-to-openapi 提供的一个方法,它通过为 Zod 模型添加 openapi 方法来增强这些模型的功能。这个 openapi 方法允许您为请求体、响应数据、参数及其属性添加额外的文档说明,而这些信息会在使用 Scalar 渲染的 API 文档中显示出来。openapi 方法的文件之前,务必先调用 extendZodWithOpenApi,否则在 Zod 对象上使用 openapi 方法时会引发错误。meta 方法来添加额外文档。例如,下面代码片段中的 schemaOne 和 schemaTwo 是完全相同的:const schemaOne = z
.string()
.openapi({ description: '用户名称', example: 'Test' });
const schemaTwo = z
.string()
.meta({description: '用户名称', example: 'Test' });
openapi 方法不同,meta 方法是未经类型定义的。因此,它无法提供自动完成功能、建议信息或关于文档组件的指导。OpenAPIRegistry 是一个用于整理 API 文档的工具,这些文档随后会被传递给 OpenAPI 规范生成器。我们通过创建一个 OpenAPIRegistry 实例,然后将其导出并在需要使用它的模块中导入它,从而利用这个工具来记录 API 端点及其相关组件。export const registry = new OpenAPIRegistry();
bearerAuth 是由 registry 创建的一个组件,用于表示 JWT 认证机制。当在某个 API 端点的文档中包含 bearerAuth 时,用户界面会提供一个输入框,用于提交认证令牌,从而实现身份验证后的请求。
registerComponent方法中,"securitySchemes"用于注册一个安全方案组件。"bearerAuth"是registerComponent方法的第一个参数,它代表了该组件的名称,你可以将其更改为自己喜欢的名称。这个组件会显示在认证令牌输入框的右上角,如上图所示。registerComponent方法的第三个参数是一个用于定义该组件的对象。generateOpenAPIDocument函数被执行时,它会汇总项目中所有的API定义信息,通过generator.generateDocument生成OpenAPI规范,并以JSON格式返回该规范。generator.generateDocument中的tags属性用于将API端点分类组织到文档界面的不同章节中。例如,所有在注册信息中带有Users标签的API端点都会被放在文档界面的Users章节下。description内容可以使用Markdown格式在模板字符串中编写。servers属性用于存储与应用程序相连的所有服务器。如果你拥有多台服务器,那么可以在文档界面中选择其中某一台作为基础URL,以便通过它发送API请求。generateOpenAPIDDocument函数就会生成相应的OpenAPI规范并返回出来。如何使用Scalar生成文档界面
generateOpenAPIDDocument函数的返回值关联起来。同时,你还需要将Scalar与Express路由连接起来,这样应用程序就能通过该路由提供文档界面了。scalar/express-api-reference包。如果使用npm,可以按照以下命令进行安装:npm install @scalar/express-api-reference
src/app.js文件中:import express from "express";
import router from "./router.ts";
import { generateOpenAPIDocument } from "./lib/openapi.ts";
import { apiReference } from "@scalar/express-api-reference";
const app = express();
app.use(express.json(), express.urlencoded({ extended: true }));
app.get("/", function (req, res) {
return res.send("OK");
});
app.use("/api", router);
const apiDocJsonContent = generateOpenAPIDDocument();
app.use(
"/docs", // 文档界面路由
apiReference({
content: apiDocJsonContent,
title: "Users API",
pageTitle: "Users API",
}),
);
export default app;
import z from “zod”;
import { registry } from “../../lib/openapi.ts”;
import {
UserSchema,
UserListItemSchema,
UpdateUserSchema,
CreateUserSchema,
} from “./types.ts”;
“`
registry.registerPath({
method: “post”,
path: “/api/users”,
summary: “创建用户”,
tags: [“users”],
request: {
body: {
content: {
“application/json”: {
schema: CreateUserSchema,
},
},
description: “用于创建用户的请求数据”,
required: true,
},
},
responses: {
201: {
description: “用户创建成功”,
content: {
“application/json”: {
schema: z.object({
message: z.string().openapi({ example: “用户创建成功” }),
data: UserSchema,
}),
},
},
},
},
});
“`registry.registerPath中某些输入字段的UI显示效果在上面的图片中已经标示出来。API接口描述中的文字被加了斜体,是因为这些描述值实际上是模板字符串中的Markdown格式。
通过使用registry.registerPath注册用于创建用户的路由路径并填写相应的参数值,你就可以将这些路由的文档信息添加到注册表定义中,这样这些信息就会包含在OpenAPI规范中。
若要通过文档UI来测试这些接口端点,请按照以下步骤操作:
若要为通过id来获取用户信息的路由(GET /api/users/:id)编写文档说明,请从src/lib/openapi.ts文件中导入bearerAuth模块,然后将下面的代码片段添加到该路由的定义位置。registry.registerPath({
method: "get",
path: "/api/users/{userId}",
summary: "根据id获取用户信息",
tags: ["Users"],
security: [{ [bearerAuth.name]: [] }],
request: {
params: z.object({ userId: z.int() }),
},
responses: {
200: {
description: "用户信息已检索到",
content: { "application/json": { schema: UserSchema } },
},
},
});
当request.params字段使用Zod对象进行定义时,文档网页上会生成相应的输入界面,让用户能够为诸如userId这样的路径参数输入值。下面的图片中展示了这一功能:

如果你想查看本节中所有接口端点的完整文档代码,可以在终端中执行git checkout complete-project命令来切换到complete-project分支。该分支中包含了用于上传用户照片的接口的文档示例,这些示例展示了如何为那些支持文件上传的接口编写文档说明。如何在NestJS项目中使用Scalar
Scalar提供了一个可以与NestJS集成的库。你可以将swagger/nestjs生成的Swagger文档提供给Scalar的NestJS集成库,从而生成相应的文档界面。
在你的NestJS项目的根目录下,安装Scalar的NestJS集成库:npm install @scalar/nestjs-api-reference
然后使用下面的代码片段更新你的NestJS项目中的main.ts文件:import { NestFactory } from '@nestjs/core';
import { apiReference } from '@scalar/nestjs-api-reference';
import { DocumentBuilder, SwaggerModule } from '@nestjsswagger';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const options = new DocumentBuilder()
.setTitle('猫咪示例')
."description:猫咪相关的API说明")
.setVersion('1.0')
.addTag('cats')
.addBearerAuth()
.build();
const openApiSpecification = SwaggerModule.createDocument(app, options);
// 将文档集成到NestJS应用中
app.use(
'/api/docs', // 文档路由
apiReference({
content: openApiSpecification,
}),
)
await app.listen(3000);
console.log(`应用程序正在以下地址运行:${await app.getUrl()}`);
}
bootstrap();
/api/docs路径,从而查看你的NestJS应用程序的Scalar文档。当与Helmet一起使用时如何解决内容安全策略错误
{
directives: {
defaultSrc: [`'self'`],
styleSrc: [`'self'`, `'unsafe-inline'`],
imgSrc: [`'self'`, 'data:', 'validator.swagger.io'],
scriptSrc: [`'self'`, `https: 'unsafe-inline'`],
},
}
缺乏异步API文档功能
总结




