- 后端
- 接口测试
- 开发工具
【免费下载链接】prism
Turn any OpenAPI2/3 and Postman Collection file into an API server with mocking, transformations and validations.
导读
@stoplight/prism-http-server是 Prism 的嵌入式 HTTP 服务器包,它允许开发者在 Node.js 代码中直接以编程方式创建 mock 服务:只要给定一份 OpenAPI 2/3 或 Postman Collection 文档,即可通过createServer()启动一个具备路由匹配、请求/响应校验、Mock 数据生成和 CORS 处理的真实 HTTP 服务。本文以packages/http-server/README.md为主干,结合该包与@stoplight/prism-http、@stoplight/prism-core的源码实现,讲解createServer的完整用法、全部配置项的含义与默认行为、逐请求级的响应覆盖机制,以及如何在测试套件中安全地启停服务。读完本文,你将能够在自己的测试或本地开发流程中,用不到 30 行代码搭建一个完全由 OpenAPI 文档驱动的 Mock API 服务器。
Prism Server 是什么:一个可嵌入的 HTTP 层
在 Prism 仓库中,@stoplight/prism-http-server(源码位于 packages/http-server)负责将@stoplight/prism-http的核心处理逻辑暴露为真实可监听的 HTTP 端口。它基于micri构建路由,同时从@stoplight/prism-http导入createInstance来组装完整的请求处理管线。整个包对外只暴露一个入口——createServer,见 packages/http-server/src/index.ts:
export { createServer } from './server';它与 CLI 的关系是:prism mock、prism proxy命令在底层最终也是调用同一个createServer(见 packages/cli/src/util/createServer.ts 中对createHttpServer的引用)。因此,通过编程方式使用本包能获得与 CLI 完全一致的行为,同时拥有完全的控制权——这正是把它嵌入测试或定制工具的价值所在。
⚠️ 重要提示:该包的 API 目前仍处于实验阶段,官方 README 明确声明“当前 API 仍属实验性,可能随时变更,请自行承担使用风险”。
快速上手:最小可运行示例
README 给出的用法非常简洁,下面完整保留并补充必要说明:
const { createServer } = require('@stoplight/prism-http-server'); const { getHttpOperationsFromSpec } = require('@stoplight/prism-cli/dist/operations'); const { createLogger } = require('@stoplight/prism-core'); async function createPrismServer() { const operations = await getHttpOperationsFromSpec('YOUR-URL'); const server = createServer(operations, { components: { logger: createLogger('TestLogger'), }, cors: true, config: { checkSecurity: true, validateRequest: true, validateResponse: true, mock: { dynamic: false }, isProxy: false, errors: false, }, }); await server.listen(4010); return { close: server.close.bind(server), }; } const server = await createPrismServer(); server.close();几个关键点需要展开说明:
getHttpOperationsFromSpec的参数'YOUR-URL'可以是本地文件路径、可 fetch 的远程 URL,或直接传入内存中的规范对象。从 packages/http/src/utils/operations.ts 的源码可以看到,它会自动识别文档类型:存在swagger字段按 OAS2 转换、存在openapi字段按 OAS3 转换、存在item数组且带info.name则按 Postman Collection 转换,否则抛出Unsupported document format。转换过程中还会对$ref进行 dereference 与 bundle,因此传入的 operations 已经是解析完毕、可直接用于路由和 Mock 的标准化结构。createLogger来自@stoplight/prism-core,其实现基于 pino,并注册了一个额外的success自定义日志级别(见 packages/core/src/logger.ts)。server.listen(4010)返回一个 Promise,resolve 的值为服务器实际监听地址字符串(形如http://127.0.0.1:4010),便于日志输出或动态拼接测试 URL。server.close()会先调用closeAllConnections()再关闭服务,确保挂起的连接被妥善处理(见 packages/http-server/src/server.ts 中close方法的实现),适合在测试的afterAll阶段调用。
深入createServer的签名与返回值
createServer的类型定义位于 packages/http-server/src/types.ts:
export interface IPrismHttpServerOpts { components: PickRequired<Partial<PrismHttpComponents>, 'logger'>; config: IHttpConfig; cors: boolean; } export interface IPrismHttpServer { readonly prism: PrismHttpInstance; readonly logger: Logger; close: () => Promise<void>; listen: (port: number, address?: string, backlog?: number) => Promise<string>; }参数与返回值逐项说明:
| 成员 | 类型 | 含义 |
|---|---|---|
components | 必须包含logger | Prism 的组件集合,其中logger是必填项,用于输出请求/校验日志 |
config | IHttpConfig | 全局默认行为配置(详见下一节) |
cors | boolean | 是否启用 CORS 处理 |
prism(getter) | PrismHttpInstance | 底层 Prism 实例,可拿到.request()直接编程调用 |
logger(getter) | Logger | 服务器使用的 pino logger |
listen(port, address?, backlog?) | Promise<string> | 监听端口并返回地址字符串 |
close() | Promise<void> | 关闭所有连接并停止服务 |
从 packages/http-server/src/server.ts 的实现可见,listen在底层对server.once('error')做了监听,端口被占用时 Promise 会以错误消息 reject;因此用它做测试时,需要留意不同测试套件并行运行时不要共用端口(官方测试注释也特别提醒了这一点,见 packages/http-server/src/tests/server.oas.spec.ts)。
配置项全解:config的每个字段
config的类型是IHttpConfig,它由基础配置IPrismBaseConfig(定义于 packages/core/src/types.ts)与mock子配置(IHttpOperationConfig,定义于 packages/http/src/types.ts)组合而成:
| 字段 | 类型 | 默认行为与作用 |
|---|---|---|
checkSecurity | boolean | 是否执行安全方案校验(如 apiKey、basicAuth、bearer、digestAuth),对应validateSecurity组件 |
validateRequest | boolean | 是否对请求体、请求头、查询参数、路径参数做校验,对应validateInput组件 |
validateResponse | boolean | 是否校验生成的响应是否与规范声明的响应一致,对应validateOutput组件 |
errors | boolean | 校验失败时是否以 HTTP 错误(Problem+JSON)形式返回而不是仅记录日志;CLI 中对应--errors标志 |
isProxy | boolean | false表示纯 Mock 模式;true表示代理模式,此时还必须提供upstream: URL |
upstreamProxy | string \| undefined | 代理模式下转发请求时使用的上游代理地址 |
mock.dynamic | boolean | false优先使用规范中的静态 example;true使用 json-schema-faker 基于 schema 动态生成 |
mock.code | number(可选) | 强制 Mock 返回的响应状态码 |
mock.exampleKey | string(可选) | 强制使用指定名称的 example |
mock.ignoreExamples | boolean(可选) | 忽略规范中的 example,静态模式下由 Prism 自行生成示例 |
mock.seed | string(可选) | 动态生成时使用的随机种子,使结果可复现 |
在核心工厂 packages/core/src/factory.ts 中,checkSecurity与validateRequest会被收集合并为输入校验结果;validateResponse则决定是否对 Mock/转发得到的输出再次校验。也就是说,这些开关直接决定了上面那条请求处理管线中哪些环节会真正执行。
mock.dynamic两种模式的差异
dynamic是使用频率最高的配置,值得单独说明。在 packages/http/src/mocker/index.ts 的createPayloadGenerator中可以看到:
return config.dynamic ? generate(resource, resource['__bundled__'], source, config.seed) : generateStatic(resource, source);dynamic: false(静态模式):优先返回规范里写明的examples;没有 example 时,由 Prism 根据 schema 生成一个静态示例。dynamic: true(动态模式):完全忽略 example,用 json-schema-faker 根据 schema 生成数据,同一接口每次调用结果通常不同;配合seed可得到确定性结果。
官方测试 packages/http-server/src/tests/server.oas.spec.ts 验证了这些行为:动态模式下连续两次请求返回不同对象;设置相同seed后两次请求返回严格相同对象;dynamic: true时即使ignoreExamples为真也会走动态生成。
请求处理管线:路由 → 校验 → Mock/转发 → 序列化
createServer内部把每个请求按以下管线处理(完整实现见 packages/http-server/src/server.ts,底层组装见 packages/http/src/index.ts):
- 解析请求体:根据
Content-Type判断,JSON 走json()解析、其余走text()解析,上限均为 10MB;若Content-Length为 0 或两个长度头都缺失,则视为无 body,返回null。 - 构建标准输入:将 method、pathname、query(含多值参数)、headers、body 组装为
IHttpRequest。 - 合并逐请求配置:调用
getHttpConfigFromRequest解析请求级覆盖项,与全局config合并(mock子对象通过merge叠加)。 - 执行 Prism 管线:由工厂
factory依次执行route→validateSecurity/validateInput→mock或forward→validateOutput。 - 发送响应:根据响应头
content-type序列化 body,写回客户端;校验产生的违规项写入sl-violations响应头。
其中路由组件(packages/http/src/router/index.ts)会先按路径片段计算匹配得分、优先选择更具体的端点,再依次匹配 path、method、server;未匹配到路径返回 404(NO_PATH_MATCHED_ERROR)、匹配到路径但方法未定义返回 405(NO_METHOD_MATCHED_ERROR)。校验组件(packages/http/src/validator/index.ts)则负责 body、headers、query、path 及安全方案的规则比对。
请求级覆盖:Prefer头与__查询参数
这是 Prism Server 非常实用的特性:允许单个请求临时覆盖全局配置,而不影响服务本身。解析逻辑位于 packages/http-server/src/getHttpConfigFromRequest.ts:
Prefer头(优先):支持code=404、dynamic=true、seed=...、example=...四种偏好,例如Prefer: code=404, dynamic=false。- 查询参数(
Prefer头缺失时的回退):__code、__dynamic、__seed、__example,以及用于指定 server 的__server。
解析时code必须是三位数字(否则报UNPROCESSABLE_ENTITY422 错误),dynamic必须是true/false。单测 packages/http-server/src/tests/getHttpConfigFromRequest.spec.ts 明确验证了“Prefer头优先于查询参数”的优先级规则。
典型用法示例:
# 强制返回 404 响应 curl http://localhost:4010/pets/123?__code=404 # 指定某个命名 example curl http://localhost:4010/pets/123?__example=cat # 用 Prefer 头动态生成 curl -H "Prefer: dynamic=true, seed=test_seed" http://localhost:4010/pets # 校验请求必须匹配的 server curl http://localhost:4010/pets/10?__server=https://petstore.swagger.io/v2这些行为在 packages/http-server/src/tests/server.oas.spec.ts 中有系统性的端到端验证:__code=499但规范无此响应码且无 default 响应时返回 404 Problem+JSON;请求不存在的 example 同样返回 404;__server传入未在规范中声明的地址则返回 404 并附带NO_SERVER_MATCHED_ERROR的详细错误信息。
CORS 与错误响应格式
当cors: true时,服务器会自动处理 OPTIONS 预检请求:回写Access-Control-Allow-Origin(默认回显请求的origin,否则*)、Access-Control-Allow-Headers、Access-Control-Allow-Credentials: true、Access-Control-Expose-Headers,预检请求返回 204,并设置Vary: origin与Content-Length: 0(后者是为规避 Safari 对 204 的兼容问题)。非预检请求也会统一附加这些头。实现见 packages/http-server/src/server.ts 的setCommonCORSHeaders。
错误响应统一使用 RFC 7807 风格的 Problem+JSON,包含type、title、status、detail四个字段,由ProblemJsonError(定义于 packages/http/src/types.ts)生成。校验失败时还会在响应头写入sl-violations,内容为序列化后的违规明细 JSON(location/severity/code/message),超过约 8KB 上限时会被截断并加上Too many violations!前缀。
响应序列化规则
createServer发送响应前会调用 packages/http-server/src/serialize.ts 按Content-Type选择序列化器:
application/json/application/*+json:JSON.stringify;application/xml/application/*+xml:使用fast-xml-parser的XMLBuilder构建 XML;text/*:字符串原样返回;若试图把复杂对象序列化为文本,则抛出 500 错误(NO_COMPLEX_OBJECT_TEXT);- 未匹配的 Content-Type:字符串直接返回,否则报“找不到序列化器”错误。
这解释了为什么Accept: application/xml的请求可以拿到 XML 形态的 Mock 响应,而纯文本接口的响应体会保持字符串形式。
在测试中管理生命周期:监听与关闭
把 Prism Server 用于测试时,官方测试(packages/http-server/src/tests/server.oas.spec.ts)给出了一套值得参考的模式:
const address = await server.listen(30001, '127.0.0.1'); // 之后用 node-fetch 基于 address 拼接 URL 发起断言 afterAll(() => server.close());几点实践建议:
- 用
server.close.bind(server)传给afterAll/afterEach,避免this指向问题(README 示例即采用该写法)。 - 不同测试套件并行运行时会共享进程,端口必须互不相同,否则
listen会 reject。 listen支持第二个参数address,测试中显式绑定127.0.0.1更稳妥。
匿名安装统计(Anonymized analytics)与关闭方式
@stoplight/prism-http-server在安装时通过 Scarf 收集匿名安装统计,用于帮助维护者了解库的使用情况。注意:统计仅在npm install安装过程中运行,不会在服务运行时上报。官方 README 提供了两种关闭方式,此处原样继承:
- 在项目的
package.json中设置:
{ // ... "scarfSettings": { "enabled": false } // ... }- 或在执行安装时设置环境变量:
SCARF_ANALYTICS=false npm install与 CLI 的对应关系
如果你已经熟悉prism mock命令,可以快速建立映射:CLI 在 packages/cli/src/commands/mock.ts 中暴露的--dynamic/-d、--seed、--ignoreExamples、--errors、--cors、--port、--host等选项,最终都会落入createServer的config与cors参数(见 packages/cli/src/util/createServer.ts 中shared对象的组装逻辑)。也就是说,编程方式与 CLI 是同一套引擎,本文讲解的每个配置字段都能在 CLI 文档中找到对应物。
环境要求与注意事项
- 当前仓库版本为
5.16.0,packages/http-server/package.json 声明要求Node.js >= 24.19.0,请确认运行环境满足要求。 - 包导出入口为
dist/index.js,类型定义在dist/index.d.ts,需先构建(仓库根目录npm run build)或使用发布版本。 - API 仍属实验性,升级大版本时建议关注 CHANGELOG(packages/http-server/CHANGELOG.md)中的破坏性变更说明。
getHttpOperationsFromSpec对输入文档会发起远程$ref解析,请求头带上了User-Agent: PrismMockServer/<version>;如果规范引用了需要鉴权的远程资源,需要提前处理好可访问性。
小结
@stoplight/prism-http-server把 Prism 的完整能力封装成一个可编程的 HTTP 服务:getHttpOperationsFromSpec负责把任意 OAS2/3 或 Postman Collection 文档解析为标准操作集合,createServer负责路由、校验、Mock、序列化与 CORS,Prefer头与__查询参数负责逐请求级的精细控制。理解其配置项与底层管线(route → validate → mock/forward → serialize)之后,无论是单测中的内联 Mock、契约测试,还是本地开发服务器,你都可以用同一套代码以编程方式快速落地。
- 后端
- 接口测试
- 开发工具
【免费下载链接】prism
Turn any OpenAPI2/3 and Postman Collection file into an API server with mocking, transformations and validations.
相关推荐
Prism HTTP Mocking 实战:用 OpenAPI 文档零成本搭建可交互的 Mock API 服务
Prism HTTP Mocking 实战:用 OpenAPI 文档零成本搭建可交互的 Mock API 服务 本文以 docs/guides/01 mocki
后端接口测试开发工具Prism HTTP Client 实战指南:用 @stoplight/prism-http 客户端驱动 Mock 与真实请求
Prism HTTP Client 实战指南:用 @stoplight/prism http 客户端驱动 Mock 与真实请求 Prism 不仅提供开箱即用的
后端接口测试开发工具Prism 多文档服务实战:用 Docker Compose 与 Caddy 反向代理同时 Mock 多个 OpenAPI 文档
Prism 多文档服务实战:用 Docker Compose 与 Caddy 反向代理同时 Mock 多个 OpenAPI 文档 导读 单个 Prism 实例只
后端接口测试开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考