NestJS多Swagger文档:如何让接口仅在指定文档显示
解决NestJS中接口在指定Swagger路由隐藏/显示的问题
你遇到的这个需求确实很常见——@ApiExcludeEndpoint是全局生效的,没法针对特定Swagger文档做区分,我这里有几个实用的方案可以解决这个问题:
方案一:自定义装饰器+文档转换过滤(最灵活)
这个方案适合需要在同一个控制器里区分不同Swagger文档显示的场景,实现起来也很直观:
- 创建自定义装饰器,给接口标记需要排除的Swagger文档名称:
import { applyDecorators } from '@nestjs/common'; import { ApiOperation } from '@nestjs/swagger'; // 自定义装饰器:标记接口在哪些Swagger文档中隐藏 export const ApiExcludeForSwagger = (...swaggerNames: string[]) => applyDecorators( ApiOperation({ // 用Swagger自定义扩展字段存储排除规则 'x-exclude-for-swagger': swaggerNames, }), );
- 修改
constructSwagger函数,在生成Swagger文档时过滤指定接口:
利用SwaggerModule.createDocument的transform选项,我们可以在文档生成后,根据当前Swagger配置的名称,自动移除标记了要排除的接口:
const document = SwaggerModule.createDocument(app, documentConfig, { operationIdFactory: (controllerKey: string, methodKey: string) => `[${controllerKey}] ${methodKey}`, include: modules, // 添加文档转换逻辑 transform: (generatedDocument) => { const currentSwaggerName = config.name; // 遍历所有路径和方法,过滤需要隐藏的接口 Object.keys(generatedDocument.paths).forEach(path => { Object.keys(generatedDocument.paths[path]).forEach(method => { const operation = generatedDocument.paths[path][method]; const excludeForList = operation['x-exclude-for-swagger']; // 如果当前Swagger在排除列表中,删除该接口 if (excludeForList?.includes(currentSwaggerName)) { delete generatedDocument.paths[path][method]; } }); // 如果某路径下没有剩余接口,直接删除整个路径 if (Object.keys(generatedDocument.paths[path]).length === 0) { delete generatedDocument.paths[path]; } }); return generatedDocument; }, });
- 在目标接口上使用装饰器:
比如你想让某个接口在API TEST(即test1SwaggerConfig的name)中隐藏,在/api/test2中正常显示:
@ApiExcludeForSwagger('API TEST') @Get('/example') async exampleEndpoint() { return '这个接口在/api/test1中隐藏,但在/api/test2中可见'; }
方案二:拆分控制器到不同模块(最简洁)
如果你的接口可以按Swagger文档的范围来拆分,那这个方案最省心:
- 把需要在
/api/test1中显示的接口放到Test1PublicController,归属Test1Module - 把需要仅在
/api/test2中显示的接口放到Test2ExclusiveController,归属Test2Module - 然后在
test1SwaggerConfig的modules数组里只包含Test1Module,test2SwaggerConfig里同时包含Test1Module和Test2Module
通过Swagger原生的include配置,自然就能实现不同文档显示不同接口的效果,完全不需要额外的过滤逻辑。
方案三:动态调整Swagger的include配置(折中方案)
如果不想拆分控制器,也可以在constructSwagger中根据当前Swagger配置,动态筛选要包含的控制器方法:
比如给控制器方法添加自定义元数据标记归属的Swagger文档,然后在生成文档时,通过反射获取元数据,只包含符合当前Swagger配置的方法。不过这个实现起来比方案一复杂,灵活性也稍差,一般更推荐方案一。
我自己在项目中用过方案一,适配性很强,完全能满足“同一接口在不同Swagger文档中显示/隐藏”的需求。
内容的提问来源于stack exchange,提问作者Nikitonu4
相关产品推荐
相关产品推荐

