有没有办法从NestJS应用程序中收集所有方法及其路径?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有没有办法从NestJS应用程序中收集所有方法及其路径?相关的知识,希望对你有一定的参考价值。
我需要编写中间件来处理请求,但是应该排除一些路径。我不想手动硬编码所有这些,所以我有一个想法:
创建特殊的装饰器,它将标记要排除的方法,如下所示:
import ReflectMetadata from '@nestjs/common';
export const Exclude = () =>
ReflectMetadata('exclude', 'true');
有没有办法创建NestJS应用程序以某种方式递归获取所有方法,用这个装饰器注释,自动添加他们的路径,以排除在我的中间件?
我发布了一个可重用的模块,用于在处理程序或Injectable类上发现元数据,专门用于支持此模式。您可以从NPM中获取@nestjs-plus/common
,然后使用DiscoveryService
根据您提供的MetaData令牌自动检索所有匹配的处理程序或类。源代码是available on Github。我将在短期内继续更新文档,但它已经包含在存储库中的几个示例用法。
在引擎盖下,它使用MetaDataScanner,但在易于使用的API中包装起来。查看您发布的代码片段可以帮助您减少针对特定用例的大量样板。您可以在@nestjs-plus/rabbitmq
模块(来自同一存储库)中查看更多高级用法,了解如何将其用于glue together advanced functionality。
编辑:我已更新库以支持发现控制器和控制器方法的方案,以支持您的方案。 There's a complete test suite that mimics your setup with the @Roles
decorator you can check out.。在导入中包含DiscoveryModule
并注入DiscoverService
之后,您可以使用简化的methodsAndControllerMethodsWithMeta
API找到所有控制器方法。
// Inject the service
constructor(private readonly discover: DiscoveryService)
// Discover all controller methods decorated with guest roles or
// belonging to controllers with guest roles
const allMethods = this.discover.methodsAndControllerMethodsWithMeta<string[]>(
rolesMetaKey,
x => x.includes('guest')
);
在你发现了所有你想要的方法后,你可以用它们做任何你想做的事情,在你的情况下建立一个他们的RequestMethod
和path
的集合。
const fullPaths = allGuestMethods.map(x =>
const controllerPath = Reflect.getMetadata(
PATH_METADATA,
x.component.metatype
);
const methodPath = Reflect.getMetadata(PATH_METADATA, x.handler);
const methodHttpVerb = Reflect.getMetadata(
METHOD_METADATA,
x.handler
);
return
verb: methodHttpVerb,
path: `$controllerPath/$methodPath`
);
哪个会给你这样的东西(取自链接的测试套件)。
expect(fullPaths).toContainEqual(verb: RequestMethod.GET, path: 'guest/route-path-one');
expect(fullPaths).toContainEqual(verb: RequestMethod.GET, path: 'super/route-path-two');
expect(fullPaths).toContainEqual(verb: RequestMethod.POST, path: 'admin/route-path-three');
随意提供有关方法/ API的反馈。
所以...帮助自己。
在深入了解NestJS资源后,我发现了一种方法,对于那些感兴趣的人来说,这是方向:
import * as pathToRegexp from 'path-to-regexp';
import INestApplication, RequestMethod from '@nestjs/common';
import NestContainer from '@nestjs/core/injector/container';
import MetadataScanner from '@nestjs/core/metadata-scanner';
import PATH_METADATA, MODULE_PATH, METHOD_METADATA from '@nestjs/common/constants';
const trimSlashes = (str: string) =>
if (str != null && str.length)
while (str.length && str[str.length - 1] === '/')
str = str.slice(0, str.length - 1);
return str || '';
;
const joinPath = (...p: string[]) =>
'/' + trimSlashes(p.map(trimSlashes).filter(x => x).join('/'));
// ---------------8<----------------
const app = await NestFactory.create(AppModule);
// ---------------8<----------------
const excludes = Object.create(null);
const container: NestContainer = (app as any).container; // this is "protected" field, so a bit hacky here
const modules = container.getModules();
const scanner = new MetadataScanner();
modules.forEach(( routes, metatype , moduleName) =>
let modulePath = metatype ? Reflect.getMetadata(MODULE_PATH, metatype) : undefined;
modulePath = modulePath ? modulePath + globalPrefix : globalPrefix;
routes.forEach(( instance, metatype , controllerName) =>
const controllerPath = Reflect.getMetadata(PATH_METADATA, metatype);
const isExcludeController = Reflect.getMetadata('exclude', metatype) === 'true';
const instancePrototype = Object.getPrototypeOf(instance);
scanner.scanFromPrototype(instance, instancePrototype, method =>
const targetCallback = instancePrototype[method];
const isExcludeMethod = Reflect.getMetadata('exclude', targetCallback) === 'true';
if (isExcludeController || isExcludeMethod)
const requestMethod: RequestMethod = Reflect.getMetadata(METHOD_METADATA, targetCallback);
const routePath = Reflect.getMetadata(PATH_METADATA, targetCallback);
// add request method to map, if doesn't exist already
if (!excludes[RequestMethod[requestMethod]])
excludes[RequestMethod[requestMethod]] = [];
// add path to excludes
excludes[RequestMethod[requestMethod]].push(
// transform path to regexp to match it later in middleware
pathToRegexp(joinPath(modulePath, controllerPath, routePath)),
);
);
);
);
// now you can use `excludes` map in middleware
以上是关于有没有办法从NestJS应用程序中收集所有方法及其路径?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在没有 typeorm 的情况下创建 NestJS API,但使用普通的 expressJS/mysql 方法?