From 75d5d64ec7cc3fd4ba46e915533b47e17ce5dcb9 Mon Sep 17 00:00:00 2001 From: codytseng Date: Mon, 10 Oct 2022 22:56:30 +0800 Subject: [PATCH 01/18] fix(core): let the middleware can get the params in the global prefix --- packages/core/middleware/middleware-module.ts | 56 ++++++++++--------- packages/core/middleware/utils.ts | 1 + packages/core/nest-application.ts | 2 + .../exclude-route-metadata.interface.ts | 5 ++ packages/core/test/application-config.spec.ts | 6 +- .../test/router/route-path-factory.spec.ts | 3 + 6 files changed, 46 insertions(+), 27 deletions(-) diff --git a/packages/core/middleware/middleware-module.ts b/packages/core/middleware/middleware-module.ts index 0085484ffc9..563d78e2764 100644 --- a/packages/core/middleware/middleware-module.ts +++ b/packages/core/middleware/middleware-module.ts @@ -8,6 +8,7 @@ import { NestMiddleware } from '@nestjs/common/interfaces/middleware/nest-middle import { addLeadingSlash, isUndefined, + stripEndSlash, } from '@nestjs/common/utils/shared.utils'; import { ApplicationConfig } from '../application-config'; import { InvalidMiddlewareException } from '../errors/exceptions/invalid-middleware.exception'; @@ -276,38 +277,41 @@ export class MiddlewareModule { ) { const prefix = this.config.getGlobalPrefix(); const excludedRoutes = this.config.getGlobalPrefixOptions().exclude; - if ( - (Array.isArray(excludedRoutes) && - isRouteExcluded(excludedRoutes, path, method)) || - ['*', '/*', '(.*)', '/(.*)'].includes(path) + let paths: string[]; + if (['*', '/*', '/*/', '(.*)', '/(.*)'].includes(path)) { + const basePath = stripEndSlash(addLeadingSlash(prefix)); + paths = [basePath + addLeadingSlash(path)]; + if (Array.isArray(excludedRoutes)) { + paths.push(...excludedRoutes.map(route => route.path)); + } + } else if ( + Array.isArray(excludedRoutes) && + isRouteExcluded(excludedRoutes, path, method) ) { - path = addLeadingSlash(path); + paths = [addLeadingSlash(path)]; } else { - const basePath = addLeadingSlash(prefix); - if (basePath?.endsWith('/') && path?.startsWith('/')) { - // strip slash when a wildcard is being used - // and global prefix has been set - path = path?.slice(1); - } - path = basePath + path; + const basePath = stripEndSlash(addLeadingSlash(prefix)); + paths = [basePath + addLeadingSlash(path)]; } const isMethodAll = isRequestMethodAll(method); const requestMethod = RequestMethod[method]; const router = await applicationRef.createMiddlewareFactory(method); - router( - path, - isMethodAll - ? proxy - : ( - req: TRequest, - res: TResponse, - next: () => void, - ) => { - if (applicationRef.getRequestMethod(req) === requestMethod) { - return proxy(req, res, next); - } - return next(); - }, + paths.forEach(path => + router( + path, + isMethodAll + ? proxy + : ( + req: TRequest, + res: TResponse, + next: () => void, + ) => { + if (applicationRef.getRequestMethod(req) === requestMethod) { + return proxy(req, res, next); + } + return next(); + }, + ), ); } } diff --git a/packages/core/middleware/utils.ts b/packages/core/middleware/utils.ts index 19418afc892..15c38850515 100644 --- a/packages/core/middleware/utils.ts +++ b/packages/core/middleware/utils.ts @@ -11,6 +11,7 @@ export const mapToExcludeRoute = ( routes: RouteInfo[], ): ExcludeRouteMetadata[] => { return routes.map(({ path, method }) => ({ + path, pathRegex: pathToRegexp(path), requestMethod: method, })); diff --git a/packages/core/nest-application.ts b/packages/core/nest-application.ts index ed7484c4d56..0a0de279097 100644 --- a/packages/core/nest-application.ts +++ b/packages/core/nest-application.ts @@ -335,11 +335,13 @@ export class NestApplication (route: string | RouteInfo): ExcludeRouteMetadata => { if (isString(route)) { return { + path: route, requestMethod: RequestMethod.ALL, pathRegex: pathToRegexp(addLeadingSlash(route)), }; } return { + path: route.path, requestMethod: route.method, pathRegex: pathToRegexp(addLeadingSlash(route.path)), }; diff --git a/packages/core/router/interfaces/exclude-route-metadata.interface.ts b/packages/core/router/interfaces/exclude-route-metadata.interface.ts index 1c143512f3d..ac247191b30 100644 --- a/packages/core/router/interfaces/exclude-route-metadata.interface.ts +++ b/packages/core/router/interfaces/exclude-route-metadata.interface.ts @@ -1,6 +1,11 @@ import { RequestMethod } from '@nestjs/common'; export interface ExcludeRouteMetadata { + /** + * Route path + */ + path: string; + /** * Regular expression representing the route path. */ diff --git a/packages/core/test/application-config.spec.ts b/packages/core/test/application-config.spec.ts index 9418b13db19..cff91bb118c 100644 --- a/packages/core/test/application-config.spec.ts +++ b/packages/core/test/application-config.spec.ts @@ -23,7 +23,11 @@ describe('ApplicationConfig', () => { it('should set global path options', () => { const options: GlobalPrefixOptions = { exclude: [ - { pathRegex: new RegExp(/health/), requestMethod: RequestMethod.GET }, + { + path: '/health', + pathRegex: new RegExp(/health/), + requestMethod: RequestMethod.GET, + }, ], }; appConfig.setGlobalPrefixOptions(options); diff --git a/packages/core/test/router/route-path-factory.spec.ts b/packages/core/test/router/route-path-factory.spec.ts index 84b9275a77b..4c110651d01 100644 --- a/packages/core/test/router/route-path-factory.spec.ts +++ b/packages/core/test/router/route-path-factory.spec.ts @@ -247,6 +247,7 @@ describe('RoutePathFactory', () => { sinon.stub(applicationConfig, 'getGlobalPrefixOptions').returns({ exclude: [ { + path: '/random', pathRegex: pathToRegexp('/random'), requestMethod: RequestMethod.ALL, }, @@ -265,6 +266,7 @@ describe('RoutePathFactory', () => { sinon.stub(applicationConfig, 'getGlobalPrefixOptions').returns({ exclude: [ { + path: '/cats', pathRegex: pathToRegexp('/cats'), requestMethod: RequestMethod.ALL, }, @@ -283,6 +285,7 @@ describe('RoutePathFactory', () => { sinon.stub(applicationConfig, 'getGlobalPrefixOptions').returns({ exclude: [ { + path: '/cats', pathRegex: pathToRegexp('/cats'), requestMethod: RequestMethod.GET, }, From b7f458f3feaeb5d0d082922c55731aff53f735fa Mon Sep 17 00:00:00 2001 From: codytseng Date: Tue, 11 Oct 2022 15:33:36 +0800 Subject: [PATCH 02/18] test: add the middleware get the params from global prefix test --- .../global-prefix/e2e/global-prefix.spec.ts | 17 +++++++++++++++++ .../global-prefix/src/app.controller.ts | 5 +++++ .../global-prefix/src/app.module.ts | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts b/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts index 131d2dd0343..ecd16f200e6 100644 --- a/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts +++ b/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts @@ -119,6 +119,23 @@ describe('Global prefix', () => { await request(server).get('/api/v1/middleware/foo').expect(404); }); + it(`should get the params in the global prefix`, async () => { + app.setGlobalPrefix('/api/:version', { + exclude: ['/hello/:name'], + }); + + server = app.getHttpServer(); + await app.init(); + + await request(server) + .get('/api/v1/middlewareParam') + .expect(200, { '0': 'middlewareParam', version: 'v1' }); + + await request(server) + .get('/hello/foo') + .expect(200, 'Hello: Data attached in middleware'); + }); + afterEach(async () => { await app.close(); }); diff --git a/integration/nest-application/global-prefix/src/app.controller.ts b/integration/nest-application/global-prefix/src/app.controller.ts index 912c0d76cc9..98a2e275685 100644 --- a/integration/nest-application/global-prefix/src/app.controller.ts +++ b/integration/nest-application/global-prefix/src/app.controller.ts @@ -21,4 +21,9 @@ export class AppController { postTest(): string { return 'test'; } + + @Get('middlewareParam') + getMiddlewareParam(@Req() req): string { + return req.extras?.param; + } } diff --git a/integration/nest-application/global-prefix/src/app.module.ts b/integration/nest-application/global-prefix/src/app.module.ts index 85d1e6ac481..e18364d3ddd 100644 --- a/integration/nest-application/global-prefix/src/app.module.ts +++ b/integration/nest-application/global-prefix/src/app.module.ts @@ -19,7 +19,7 @@ export class AppModule { .apply((req, res, next) => res.status(201).end(MIDDLEWARE_PARAM_VALUE)) .forRoutes({ path: MIDDLEWARE_VALUE + '/*', method: RequestMethod.POST }) .apply((req, res, next) => { - req.extras = { data: 'Data attached in middleware' }; + req.extras = { data: 'Data attached in middleware', param: req.params }; next(); }) .forRoutes({ path: '*', method: RequestMethod.GET }); From c437ac97d0cffaee73424027ee818b6e8262e355 Mon Sep 17 00:00:00 2001 From: codytseng Date: Sat, 15 Oct 2022 10:50:25 +0800 Subject: [PATCH 03/18] fix(core): add leading slash to excluded paths --- packages/core/middleware/middleware-module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/middleware/middleware-module.ts b/packages/core/middleware/middleware-module.ts index 563d78e2764..af453ce27d3 100644 --- a/packages/core/middleware/middleware-module.ts +++ b/packages/core/middleware/middleware-module.ts @@ -282,7 +282,7 @@ export class MiddlewareModule { const basePath = stripEndSlash(addLeadingSlash(prefix)); paths = [basePath + addLeadingSlash(path)]; if (Array.isArray(excludedRoutes)) { - paths.push(...excludedRoutes.map(route => route.path)); + paths.push(...excludedRoutes.map(route => addLeadingSlash(route.path))); } } else if ( Array.isArray(excludedRoutes) && From 3d1632693c3be5910862c3c9cc8cdaa2390f2f95 Mon Sep 17 00:00:00 2001 From: codytseng Date: Sat, 15 Oct 2022 11:08:25 +0800 Subject: [PATCH 04/18] style(core): add missing period --- .../core/router/interfaces/exclude-route-metadata.interface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/router/interfaces/exclude-route-metadata.interface.ts b/packages/core/router/interfaces/exclude-route-metadata.interface.ts index ac247191b30..b7f93b60098 100644 --- a/packages/core/router/interfaces/exclude-route-metadata.interface.ts +++ b/packages/core/router/interfaces/exclude-route-metadata.interface.ts @@ -2,7 +2,7 @@ import { RequestMethod } from '@nestjs/common'; export interface ExcludeRouteMetadata { /** - * Route path + * Route path. */ path: string; From cc7e829804bf93f0934c87e2bc68c795f6777d3a Mon Sep 17 00:00:00 2001 From: codytseng Date: Sat, 19 Nov 2022 18:11:09 +0800 Subject: [PATCH 05/18] feat: version-aware middleware --- packages/core/middleware/middleware-module.ts | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/packages/core/middleware/middleware-module.ts b/packages/core/middleware/middleware-module.ts index 5ba7990b2a9..d9495410c9b 100644 --- a/packages/core/middleware/middleware-module.ts +++ b/packages/core/middleware/middleware-module.ts @@ -274,31 +274,35 @@ export class MiddlewareModule { next: () => void, ) => void, ) { - const prefix = this.config.getGlobalPrefix(); + const prefixPath = stripEndSlash( + addLeadingSlash(this.config.getGlobalPrefix()), + ); + const applicationVersioningConfig = this.config.getVersioning(); + let versionPath = ''; + if (version && applicationVersioningConfig?.type === VersioningType.URI) { + const versionPrefix = this.routePathFactory.getVersionPrefix( + applicationVersioningConfig, + ); + versionPath = addLeadingSlash(versionPrefix + version.toString()); + } const excludedRoutes = this.config.getGlobalPrefixOptions().exclude; let paths: string[]; if (['*', '/*', '/*/', '(.*)', '/(.*)'].includes(path)) { - const basePath = stripEndSlash(addLeadingSlash(prefix)); - paths = [basePath + addLeadingSlash(path)]; + paths = [prefixPath + versionPath + addLeadingSlash(path)]; if (Array.isArray(excludedRoutes)) { - paths.push(...excludedRoutes.map(route => addLeadingSlash(route.path))); + paths.push( + ...excludedRoutes.map( + route => versionPath + addLeadingSlash(route.path), + ), + ); } } else if ( Array.isArray(excludedRoutes) && isRouteExcluded(excludedRoutes, path, method) ) { - paths = [addLeadingSlash(path)]; + paths = [versionPath + addLeadingSlash(path)]; } else { - const basePath = stripEndSlash(addLeadingSlash(prefix)); - paths = [basePath + addLeadingSlash(path)]; - } - - const applicationVersioningConfig = this.config.getVersioning(); - if (version && applicationVersioningConfig.type === VersioningType.URI) { - const versionPrefix = this.routePathFactory.getVersionPrefix( - applicationVersioningConfig, - ); - path = `/${versionPrefix}${version.toString()}${path}`; + paths = [prefixPath + versionPath + addLeadingSlash(path)]; } const isMethodAll = isRequestMethodAll(method); From 4a27d263c508dcec006a13afc2d123b66567cc92 Mon Sep 17 00:00:00 2001 From: codytseng Date: Sun, 20 Nov 2022 00:25:59 +0800 Subject: [PATCH 06/18] test: update the middleware get the params from global prefix test --- .../global-prefix/e2e/global-prefix.spec.ts | 17 ------- .../global-prefix/src/app.controller.ts | 5 -- .../global-prefix/src/app.module.ts | 2 +- .../middleware/e2e/middleware.spec.ts | 46 +++++++++++++++++++ .../middleware/src/app.controller.ts | 15 ++++++ .../middleware/src/app.module.ts | 24 ++++++++++ .../nest-application/middleware/tsconfig.json | 40 ++++++++++++++++ 7 files changed, 126 insertions(+), 23 deletions(-) create mode 100644 integration/nest-application/middleware/e2e/middleware.spec.ts create mode 100644 integration/nest-application/middleware/src/app.controller.ts create mode 100644 integration/nest-application/middleware/src/app.module.ts create mode 100644 integration/nest-application/middleware/tsconfig.json diff --git a/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts b/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts index ecd16f200e6..131d2dd0343 100644 --- a/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts +++ b/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts @@ -119,23 +119,6 @@ describe('Global prefix', () => { await request(server).get('/api/v1/middleware/foo').expect(404); }); - it(`should get the params in the global prefix`, async () => { - app.setGlobalPrefix('/api/:version', { - exclude: ['/hello/:name'], - }); - - server = app.getHttpServer(); - await app.init(); - - await request(server) - .get('/api/v1/middlewareParam') - .expect(200, { '0': 'middlewareParam', version: 'v1' }); - - await request(server) - .get('/hello/foo') - .expect(200, 'Hello: Data attached in middleware'); - }); - afterEach(async () => { await app.close(); }); diff --git a/integration/nest-application/global-prefix/src/app.controller.ts b/integration/nest-application/global-prefix/src/app.controller.ts index 98a2e275685..912c0d76cc9 100644 --- a/integration/nest-application/global-prefix/src/app.controller.ts +++ b/integration/nest-application/global-prefix/src/app.controller.ts @@ -21,9 +21,4 @@ export class AppController { postTest(): string { return 'test'; } - - @Get('middlewareParam') - getMiddlewareParam(@Req() req): string { - return req.extras?.param; - } } diff --git a/integration/nest-application/global-prefix/src/app.module.ts b/integration/nest-application/global-prefix/src/app.module.ts index e18364d3ddd..85d1e6ac481 100644 --- a/integration/nest-application/global-prefix/src/app.module.ts +++ b/integration/nest-application/global-prefix/src/app.module.ts @@ -19,7 +19,7 @@ export class AppModule { .apply((req, res, next) => res.status(201).end(MIDDLEWARE_PARAM_VALUE)) .forRoutes({ path: MIDDLEWARE_VALUE + '/*', method: RequestMethod.POST }) .apply((req, res, next) => { - req.extras = { data: 'Data attached in middleware', param: req.params }; + req.extras = { data: 'Data attached in middleware' }; next(); }) .forRoutes({ path: '*', method: RequestMethod.GET }); diff --git a/integration/nest-application/middleware/e2e/middleware.spec.ts b/integration/nest-application/middleware/e2e/middleware.spec.ts new file mode 100644 index 00000000000..97e93247bf3 --- /dev/null +++ b/integration/nest-application/middleware/e2e/middleware.spec.ts @@ -0,0 +1,46 @@ +import { + INestApplication, + RequestMethod, + VersioningType, +} from '@nestjs/common'; +import { Test } from '@nestjs/testing'; +import * as request from 'supertest'; +import { AppModule } from '../src/app.module'; + +describe('Middleware', () => { + let server; + let app: INestApplication; + + beforeEach(async () => { + const module = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = module.createNestApplication(); + app.enableVersioning({ type: VersioningType.URI }); + }); + + it(`should get the params in the global prefix`, async () => { + app.setGlobalPrefix('/api/:tenantId'); + + server = app.getHttpServer(); + await app.init(); + + await request(server) + .get('/api/test/foo') + .expect(200, { + param: { '0': 'foo', tenantId: 'test' }, + }); + + await request(server) + .get('/api/test/v2/foo') + .expect(200, { + version: 'v2', + param: { '0': 'foo', tenantId: 'test' }, + }); + }); + + afterEach(async () => { + await app.close(); + }); +}); diff --git a/integration/nest-application/middleware/src/app.controller.ts b/integration/nest-application/middleware/src/app.controller.ts new file mode 100644 index 00000000000..ff0bebfd856 --- /dev/null +++ b/integration/nest-application/middleware/src/app.controller.ts @@ -0,0 +1,15 @@ +import { Controller, Get, Req, Version } from '@nestjs/common'; + +@Controller() +export class AppController { + @Get('foo') + async foo(@Req() req) { + return req.extras; + } + + @Version('2') + @Get('foo') + async fooV2(@Req() req) { + return req.extras; + } +} diff --git a/integration/nest-application/middleware/src/app.module.ts b/integration/nest-application/middleware/src/app.module.ts new file mode 100644 index 00000000000..ac171384866 --- /dev/null +++ b/integration/nest-application/middleware/src/app.module.ts @@ -0,0 +1,24 @@ +import { MiddlewareConsumer, Module, RequestMethod } from '@nestjs/common'; +import { AppController } from './app.controller'; + +@Module({ + controllers: [AppController], +}) +export class AppModule { + configure(consumer: MiddlewareConsumer) { + consumer + .apply((req, res, next) => { + req.extras = { param: req.params }; + next(); + }) + .forRoutes({ path: '*', method: RequestMethod.GET }) + .apply((req, res, next) => { + req.extras = { + version: 'v2', + param: req.params, + }; + next(); + }) + .forRoutes({ path: '*', method: RequestMethod.GET, version: '2' }); + } +} diff --git a/integration/nest-application/middleware/tsconfig.json b/integration/nest-application/middleware/tsconfig.json new file mode 100644 index 00000000000..957e23bb21f --- /dev/null +++ b/integration/nest-application/middleware/tsconfig.json @@ -0,0 +1,40 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": false, + "noImplicitAny": false, + "removeComments": true, + "noLib": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "target": "es6", + "sourceMap": true, + "allowJs": true, + "outDir": "./dist", + "paths": { + "@nestjs/common": ["../../../packages/common"], + "@nestjs/common/*": ["../../../packages/common/*"], + "@nestjs/core": ["../../../packages/core"], + "@nestjs/core/*": ["../../../packages/core/*"], + "@nestjs/microservices": ["../../../packages/microservices"], + "@nestjs/microservices/*": ["../../../packages/microservices/*"], + "@nestjs/websockets": ["../../../packages/websockets"], + "@nestjs/websockets/*": ["../../../packages/websockets/*"], + "@nestjs/testing": ["../../../packages/websockets"], + "@nestjs/testing/*": ["../../../packages/websockets/*"], + "@nestjs/platform-express": ["../../../packages/platform-express"], + "@nestjs/platform-express/*": ["../../../packages/platform-express/*"], + "@nestjs/platform-socket.io": ["../../../packages/platform-socket.io"], + "@nestjs/platform-socket.io/*": ["../../../packages/platform-socket.io/*"], + "@nestjs/platform-ws": ["../../../packages/platform-ws"], + "@nestjs/platform-ws/*": ["../../../packages/platform-ws/*"] + } + }, + "include": [ + "src/**/*", + "e2e/**/*" + ], + "exclude": [ + "node_modules", + ] +} \ No newline at end of file From fdc5f342191246ef941d22dd9378e0c5916c439c Mon Sep 17 00:00:00 2001 From: codytseng Date: Wed, 23 Nov 2022 16:07:13 +0800 Subject: [PATCH 07/18] feat: move test --- .../e2e/middleware-with-versioning.spec.ts | 24 ++++++++++ .../global-prefix/e2e/global-prefix.spec.ts | 11 +++++ .../global-prefix/src/app.controller.ts | 5 ++ .../global-prefix/src/app.module.ts | 5 ++ .../middleware/e2e/middleware.spec.ts | 46 ------------------- .../middleware/src/app.controller.ts | 15 ------ .../middleware/src/app.module.ts | 24 ---------- .../nest-application/middleware/tsconfig.json | 40 ---------------- 8 files changed, 45 insertions(+), 125 deletions(-) delete mode 100644 integration/nest-application/middleware/e2e/middleware.spec.ts delete mode 100644 integration/nest-application/middleware/src/app.controller.ts delete mode 100644 integration/nest-application/middleware/src/app.module.ts delete mode 100644 integration/nest-application/middleware/tsconfig.json diff --git a/integration/hello-world/e2e/middleware-with-versioning.spec.ts b/integration/hello-world/e2e/middleware-with-versioning.spec.ts index c8d800a900e..a16645b6859 100644 --- a/integration/hello-world/e2e/middleware-with-versioning.spec.ts +++ b/integration/hello-world/e2e/middleware-with-versioning.spec.ts @@ -77,6 +77,26 @@ describe('Middleware', () => { }); }); + describe('when using default URI versioning with the global prefix', () => { + beforeEach(async () => { + app = await createAppWithVersioning( + { + type: VersioningType.URI, + defaultVersion: VERSION_NEUTRAL, + }, + async (app: INestApplication) => { + app.setGlobalPrefix('api'); + }, + ); + }); + + it(`forRoutes({ path: '/versioned', version: '1', method: RequestMethod.ALL })`, () => { + return request(app.getHttpServer()) + .get('/api/v1/versioned') + .expect(200, VERSIONED_VALUE); + }); + }); + describe('when using HEADER versioning', () => { beforeEach(async () => { app = await createAppWithVersioning({ @@ -133,6 +153,7 @@ describe('Middleware', () => { async function createAppWithVersioning( versioningOptions: VersioningOptions, + beforeInit?: (app: INestApplication) => Promise, ): Promise { const app = ( await Test.createTestingModule({ @@ -141,6 +162,9 @@ async function createAppWithVersioning( ).createNestApplication(); app.enableVersioning(versioningOptions); + if (beforeInit) { + await beforeInit(app); + } await app.init(); return app; diff --git a/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts b/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts index 131d2dd0343..74f8e9ad6fc 100644 --- a/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts +++ b/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts @@ -119,6 +119,17 @@ describe('Global prefix', () => { await request(server).get('/api/v1/middleware/foo').expect(404); }); + it(`should get the params in the global prefix`, async () => { + app.setGlobalPrefix('/api/:tenantId'); + + server = app.getHttpServer(); + await app.init(); + + await request(server) + .get('/api/test/params') + .expect(200, { '0': 'params', tenantId: 'test' }); + }); + afterEach(async () => { await app.close(); }); diff --git a/integration/nest-application/global-prefix/src/app.controller.ts b/integration/nest-application/global-prefix/src/app.controller.ts index 912c0d76cc9..d826cd0dbc2 100644 --- a/integration/nest-application/global-prefix/src/app.controller.ts +++ b/integration/nest-application/global-prefix/src/app.controller.ts @@ -7,6 +7,11 @@ export class AppController { return 'Hello: ' + req.extras?.data; } + @Get('params') + getParams(@Req() req): any { + return req.middlewareParams; + } + @Get('health') getHealth(): string { return 'up'; diff --git a/integration/nest-application/global-prefix/src/app.module.ts b/integration/nest-application/global-prefix/src/app.module.ts index 85d1e6ac481..f182915c40e 100644 --- a/integration/nest-application/global-prefix/src/app.module.ts +++ b/integration/nest-application/global-prefix/src/app.module.ts @@ -22,6 +22,11 @@ export class AppModule { req.extras = { data: 'Data attached in middleware' }; next(); }) + .forRoutes({ path: '*', method: RequestMethod.GET }) + .apply((req, res, next) => { + req.middlewareParams = req.params; + next(); + }) .forRoutes({ path: '*', method: RequestMethod.GET }); } } diff --git a/integration/nest-application/middleware/e2e/middleware.spec.ts b/integration/nest-application/middleware/e2e/middleware.spec.ts deleted file mode 100644 index 97e93247bf3..00000000000 --- a/integration/nest-application/middleware/e2e/middleware.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { - INestApplication, - RequestMethod, - VersioningType, -} from '@nestjs/common'; -import { Test } from '@nestjs/testing'; -import * as request from 'supertest'; -import { AppModule } from '../src/app.module'; - -describe('Middleware', () => { - let server; - let app: INestApplication; - - beforeEach(async () => { - const module = await Test.createTestingModule({ - imports: [AppModule], - }).compile(); - - app = module.createNestApplication(); - app.enableVersioning({ type: VersioningType.URI }); - }); - - it(`should get the params in the global prefix`, async () => { - app.setGlobalPrefix('/api/:tenantId'); - - server = app.getHttpServer(); - await app.init(); - - await request(server) - .get('/api/test/foo') - .expect(200, { - param: { '0': 'foo', tenantId: 'test' }, - }); - - await request(server) - .get('/api/test/v2/foo') - .expect(200, { - version: 'v2', - param: { '0': 'foo', tenantId: 'test' }, - }); - }); - - afterEach(async () => { - await app.close(); - }); -}); diff --git a/integration/nest-application/middleware/src/app.controller.ts b/integration/nest-application/middleware/src/app.controller.ts deleted file mode 100644 index ff0bebfd856..00000000000 --- a/integration/nest-application/middleware/src/app.controller.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Controller, Get, Req, Version } from '@nestjs/common'; - -@Controller() -export class AppController { - @Get('foo') - async foo(@Req() req) { - return req.extras; - } - - @Version('2') - @Get('foo') - async fooV2(@Req() req) { - return req.extras; - } -} diff --git a/integration/nest-application/middleware/src/app.module.ts b/integration/nest-application/middleware/src/app.module.ts deleted file mode 100644 index ac171384866..00000000000 --- a/integration/nest-application/middleware/src/app.module.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { MiddlewareConsumer, Module, RequestMethod } from '@nestjs/common'; -import { AppController } from './app.controller'; - -@Module({ - controllers: [AppController], -}) -export class AppModule { - configure(consumer: MiddlewareConsumer) { - consumer - .apply((req, res, next) => { - req.extras = { param: req.params }; - next(); - }) - .forRoutes({ path: '*', method: RequestMethod.GET }) - .apply((req, res, next) => { - req.extras = { - version: 'v2', - param: req.params, - }; - next(); - }) - .forRoutes({ path: '*', method: RequestMethod.GET, version: '2' }); - } -} diff --git a/integration/nest-application/middleware/tsconfig.json b/integration/nest-application/middleware/tsconfig.json deleted file mode 100644 index 957e23bb21f..00000000000 --- a/integration/nest-application/middleware/tsconfig.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "declaration": false, - "noImplicitAny": false, - "removeComments": true, - "noLib": false, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "target": "es6", - "sourceMap": true, - "allowJs": true, - "outDir": "./dist", - "paths": { - "@nestjs/common": ["../../../packages/common"], - "@nestjs/common/*": ["../../../packages/common/*"], - "@nestjs/core": ["../../../packages/core"], - "@nestjs/core/*": ["../../../packages/core/*"], - "@nestjs/microservices": ["../../../packages/microservices"], - "@nestjs/microservices/*": ["../../../packages/microservices/*"], - "@nestjs/websockets": ["../../../packages/websockets"], - "@nestjs/websockets/*": ["../../../packages/websockets/*"], - "@nestjs/testing": ["../../../packages/websockets"], - "@nestjs/testing/*": ["../../../packages/websockets/*"], - "@nestjs/platform-express": ["../../../packages/platform-express"], - "@nestjs/platform-express/*": ["../../../packages/platform-express/*"], - "@nestjs/platform-socket.io": ["../../../packages/platform-socket.io"], - "@nestjs/platform-socket.io/*": ["../../../packages/platform-socket.io/*"], - "@nestjs/platform-ws": ["../../../packages/platform-ws"], - "@nestjs/platform-ws/*": ["../../../packages/platform-ws/*"] - } - }, - "include": [ - "src/**/*", - "e2e/**/*" - ], - "exclude": [ - "node_modules", - ] -} \ No newline at end of file From 758cd2d8b1e6c81100c6b278f13b94d8e025982f Mon Sep 17 00:00:00 2001 From: codytseng Date: Wed, 23 Nov 2022 18:18:32 +0800 Subject: [PATCH 08/18] refactor: wrap get paths logic into a private function --- packages/core/middleware/middleware-module.ts | 71 +++++++++------- .../core/router/utils/exclude-route.util.ts | 3 +- .../test/middleware/middleware-module.spec.ts | 85 ++++++++++++++++++- 3 files changed, 125 insertions(+), 34 deletions(-) diff --git a/packages/core/middleware/middleware-module.ts b/packages/core/middleware/middleware-module.ts index d9495410c9b..4c14291c9c8 100644 --- a/packages/core/middleware/middleware-module.ts +++ b/packages/core/middleware/middleware-module.ts @@ -267,44 +267,15 @@ export class MiddlewareModule { private async registerHandler( applicationRef: HttpServer, - { path, method, version }: RouteInfo, + routeInfo: RouteInfo, proxy: ( req: TRequest, res: TResponse, next: () => void, ) => void, ) { - const prefixPath = stripEndSlash( - addLeadingSlash(this.config.getGlobalPrefix()), - ); - const applicationVersioningConfig = this.config.getVersioning(); - let versionPath = ''; - if (version && applicationVersioningConfig?.type === VersioningType.URI) { - const versionPrefix = this.routePathFactory.getVersionPrefix( - applicationVersioningConfig, - ); - versionPath = addLeadingSlash(versionPrefix + version.toString()); - } - const excludedRoutes = this.config.getGlobalPrefixOptions().exclude; - let paths: string[]; - if (['*', '/*', '/*/', '(.*)', '/(.*)'].includes(path)) { - paths = [prefixPath + versionPath + addLeadingSlash(path)]; - if (Array.isArray(excludedRoutes)) { - paths.push( - ...excludedRoutes.map( - route => versionPath + addLeadingSlash(route.path), - ), - ); - } - } else if ( - Array.isArray(excludedRoutes) && - isRouteExcluded(excludedRoutes, path, method) - ) { - paths = [versionPath + addLeadingSlash(path)]; - } else { - paths = [prefixPath + versionPath + addLeadingSlash(path)]; - } - + const { method } = routeInfo; + const paths = this.getPaths(routeInfo); const isMethodAll = isRequestMethodAll(method); const requestMethod = RequestMethod[method]; const router = await applicationRef.createMiddlewareFactory(method); @@ -326,4 +297,40 @@ export class MiddlewareModule { ), ); } + + private getPaths({ path, method, version }: RouteInfo) { + const prefixPath = stripEndSlash( + addLeadingSlash(this.config.getGlobalPrefix()), + ); + const excludedRoutes = this.config.getGlobalPrefixOptions().exclude; + + const applicationVersioningConfig = this.config.getVersioning(); + let versionPath = ''; + if (version && applicationVersioningConfig?.type === VersioningType.URI) { + const versionPrefix = this.routePathFactory.getVersionPrefix( + applicationVersioningConfig, + ); + versionPath = addLeadingSlash(versionPrefix + version.toString()); + } + + if (['*', '/*', '/*/', '(.*)', '/(.*)'].includes(path)) { + return Array.isArray(excludedRoutes) + ? [ + prefixPath + versionPath + addLeadingSlash(path), + ...excludedRoutes.map( + route => versionPath + addLeadingSlash(route.path), + ), + ] + : [prefixPath + versionPath + addLeadingSlash(path)]; + } + + if ( + Array.isArray(excludedRoutes) && + isRouteExcluded(excludedRoutes, path, method) + ) { + return [versionPath + addLeadingSlash(path)]; + } + + return [prefixPath + versionPath + addLeadingSlash(path)]; + } } diff --git a/packages/core/router/utils/exclude-route.util.ts b/packages/core/router/utils/exclude-route.util.ts index 798260bf23a..8670f18f438 100644 --- a/packages/core/router/utils/exclude-route.util.ts +++ b/packages/core/router/utils/exclude-route.util.ts @@ -1,4 +1,5 @@ import { RequestMethod } from '@nestjs/common'; +import { addLeadingSlash } from '@nestjs/common/utils/shared.utils'; import { ExcludeRouteMetadata } from '../interfaces/exclude-route-metadata.interface'; export const isRequestMethodAll = (method: RequestMethod) => { @@ -15,7 +16,7 @@ export function isRouteExcluded( isRequestMethodAll(route.requestMethod) || route.requestMethod === requestMethod ) { - return route.pathRegex.exec(path); + return route.pathRegex.exec(addLeadingSlash(path)); } return false; }); diff --git a/packages/core/test/middleware/middleware-module.spec.ts b/packages/core/test/middleware/middleware-module.spec.ts index 65e87b6b1d3..36a4a4f14f3 100644 --- a/packages/core/test/middleware/middleware-module.spec.ts +++ b/packages/core/test/middleware/middleware-module.spec.ts @@ -1,6 +1,8 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, VersioningType } from '@nestjs/common'; +import { addLeadingSlash } from '@nestjs/common/utils/shared.utils'; import { RoutePathFactory } from '@nestjs/core/router/route-path-factory'; import { expect } from 'chai'; +import pathToRegexp = require('path-to-regexp'); import * as sinon from 'sinon'; import { Controller } from '../../../common/decorators/core/controller.decorator'; import { RequestMapping } from '../../../common/decorators/http/request-mapping.decorator'; @@ -196,4 +198,85 @@ describe('MiddlewareModule', () => { expect(createMiddlewareFactoryStub.calledOnce).to.be.true; }); }); + describe('getPaths', () => { + it(`should return correct paths`, () => { + (middlewareModule as any).config.enableVersioning({ + type: VersioningType.URI, + }); + + const paths = (middlewareModule as any).getPaths({ + path: '*', + method: RequestMethod.ALL, + }); + expect(paths).to.eql(['/*']); + + const versioningPaths = (middlewareModule as any).getPaths({ + path: '*', + method: RequestMethod.ALL, + version: '1', + }); + expect(versioningPaths).to.eql(['/v1/*']); + }); + it(`should return correct paths when set global prefix`, () => { + (middlewareModule as any).config.enableVersioning({ + type: VersioningType.URI, + }); + (middlewareModule as any).config.setGlobalPrefix('api'); + + const paths = (middlewareModule as any).getPaths({ + path: '*', + method: RequestMethod.ALL, + }); + expect(paths).to.eql(['/api/*']); + + const versioningPaths = (middlewareModule as any).getPaths({ + path: '*', + method: RequestMethod.ALL, + version: '1', + }); + expect(versioningPaths).to.eql(['/api/v1/*']); + }); + it(`should return correct paths when set global prefix and global prefix options`, () => { + (middlewareModule as any).config.enableVersioning({ + type: VersioningType.URI, + }); + (middlewareModule as any).config.setGlobalPrefix('api'); + (middlewareModule as any).config.setGlobalPrefixOptions({ + exclude: [ + { + path: 'foo', + requestMethod: RequestMethod.ALL, + pathRegex: pathToRegexp(addLeadingSlash('foo')), + }, + ], + }); + + const allPaths = (middlewareModule as any).getPaths({ + path: '*', + method: RequestMethod.ALL, + }); + expect(allPaths).to.eql(['/api/*', '/foo']); + + const allVersioningPaths = (middlewareModule as any).getPaths({ + path: '*', + method: RequestMethod.ALL, + version: '1', + }); + expect(allVersioningPaths).to.eql(['/api/v1/*', '/v1/foo']); + + const excludedPaths = (middlewareModule as any).getPaths({ + path: 'foo', + method: RequestMethod.ALL, + version: '1', + }); + expect(excludedPaths).to.eql(['/v1/foo']); + + const normalPaths = (middlewareModule as any).getPaths({ + path: 'bar', + method: RequestMethod.ALL, + version: '1', + }); + expect(normalPaths).to.eql(['/api/v1/bar']); + }); + }); }); From 7d1fa9a21629be8301f795d71e645cd788e7b7dc Mon Sep 17 00:00:00 2001 From: codytseng Date: Wed, 23 Nov 2022 18:23:00 +0800 Subject: [PATCH 09/18] test: global prefix options --- packages/core/test/nest-application.spec.ts | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/packages/core/test/nest-application.spec.ts b/packages/core/test/nest-application.spec.ts index 19f9825b3f4..b9af1f6489b 100644 --- a/packages/core/test/nest-application.spec.ts +++ b/packages/core/test/nest-application.spec.ts @@ -1,4 +1,7 @@ +import { RequestMethod } from '@nestjs/common'; +import { addLeadingSlash } from '@nestjs/common/utils/shared.utils'; import { expect } from 'chai'; +import pathToRegexp = require('path-to-regexp'); import { ApplicationConfig } from '../application-config'; import { NestContainer } from '../injector/container'; import { NestApplication } from '../nest-application'; @@ -51,4 +54,33 @@ describe('NestApplication', () => { ).to.equal(1); }); }); + describe('Global Prefix', () => { + it('should get correct global prefix options', () => { + const applicationConfig = new ApplicationConfig(); + const container = new NestContainer(applicationConfig); + const instance = new NestApplication( + container, + new NoopHttpAdapter({}), + applicationConfig, + {}, + ); + instance.setGlobalPrefix('api', { + exclude: ['foo', { path: 'bar', method: RequestMethod.GET }], + }); + expect((instance as any).config.getGlobalPrefixOptions()).to.eql({ + exclude: [ + { + path: 'foo', + requestMethod: RequestMethod.ALL, + pathRegex: pathToRegexp(addLeadingSlash('foo')), + }, + { + path: 'bar', + requestMethod: RequestMethod.GET, + pathRegex: pathToRegexp(addLeadingSlash('bar')), + }, + ], + }); + }); + }); }); From 60772c39e1b9dd03500f29a64c7c6db8e9c7e5cd Mon Sep 17 00:00:00 2001 From: codytseng Date: Wed, 23 Nov 2022 22:34:25 +0800 Subject: [PATCH 10/18] feat: use `mapToExcludeRoute()` when set global prefix --- packages/core/middleware/utils.ts | 27 ++++++++++++++----- packages/core/nest-application.ts | 24 +++-------------- .../test/middleware/middleware-module.spec.ts | 11 ++------ packages/core/test/middleware/utils.spec.ts | 23 ++++++++++++++++ packages/core/test/nest-application.spec.ts | 16 ++++------- 5 files changed, 54 insertions(+), 47 deletions(-) diff --git a/packages/core/middleware/utils.ts b/packages/core/middleware/utils.ts index 15c38850515..d9365e90f35 100644 --- a/packages/core/middleware/utils.ts +++ b/packages/core/middleware/utils.ts @@ -1,6 +1,10 @@ import { RequestMethod } from '@nestjs/common'; import { HttpServer, RouteInfo, Type } from '@nestjs/common/interfaces'; -import { isFunction } from '@nestjs/common/utils/shared.utils'; +import { + addLeadingSlash, + isFunction, + isString, +} from '@nestjs/common/utils/shared.utils'; import { iterate } from 'iterare'; import * as pathToRegexp from 'path-to-regexp'; import { v4 as uuid } from 'uuid'; @@ -8,13 +12,22 @@ import { ExcludeRouteMetadata } from '../router/interfaces/exclude-route-metadat import { isRouteExcluded } from '../router/utils'; export const mapToExcludeRoute = ( - routes: RouteInfo[], + routes: (string | RouteInfo)[], ): ExcludeRouteMetadata[] => { - return routes.map(({ path, method }) => ({ - path, - pathRegex: pathToRegexp(path), - requestMethod: method, - })); + return routes.map(route => { + if (isString(route)) { + return { + path: route, + requestMethod: RequestMethod.ALL, + pathRegex: pathToRegexp(addLeadingSlash(route)), + }; + } + return { + path: route.path, + requestMethod: route.method, + pathRegex: pathToRegexp(addLeadingSlash(route.path)), + }; + }); }; export const filterMiddleware = = any>( diff --git a/packages/core/nest-application.ts b/packages/core/nest-application.ts index 891eac2804c..c35b6a046c3 100644 --- a/packages/core/nest-application.ts +++ b/packages/core/nest-application.ts @@ -7,13 +7,11 @@ import { NestHybridApplicationOptions, NestInterceptor, PipeTransform, - RequestMethod, VersioningOptions, VersioningType, WebSocketAdapter, } from '@nestjs/common'; import { - RouteInfo, GlobalPrefixOptions, NestApplicationOptions, } from '@nestjs/common/interfaces'; @@ -31,7 +29,6 @@ import { } from '@nestjs/common/utils/shared.utils'; import { iterate } from 'iterare'; import { platform } from 'os'; -import * as pathToRegexp from 'path-to-regexp'; import { AbstractHttpAdapter } from './adapters'; import { ApplicationConfig } from './application-config'; import { MESSAGES } from './constants'; @@ -39,8 +36,8 @@ import { optionalRequire } from './helpers/optional-require'; import { NestContainer } from './injector/container'; import { MiddlewareContainer } from './middleware/container'; import { MiddlewareModule } from './middleware/middleware-module'; +import { mapToExcludeRoute } from './middleware/utils'; import { NestApplicationContext } from './nest-application-context'; -import { ExcludeRouteMetadata } from './router/interfaces/exclude-route-metadata.interface'; import { Resolver } from './router/interfaces/resolver.interface'; import { RoutePathFactory } from './router/route-path-factory'; import { RoutesResolver } from './router/routes-resolver'; @@ -336,22 +333,9 @@ export class NestApplication public setGlobalPrefix(prefix: string, options?: GlobalPrefixOptions): this { this.config.setGlobalPrefix(prefix); if (options) { - const exclude = options?.exclude.map( - (route: string | RouteInfo): ExcludeRouteMetadata => { - if (isString(route)) { - return { - path: route, - requestMethod: RequestMethod.ALL, - pathRegex: pathToRegexp(addLeadingSlash(route)), - }; - } - return { - path: route.path, - requestMethod: route.method, - pathRegex: pathToRegexp(addLeadingSlash(route.path)), - }; - }, - ); + const exclude = options?.exclude + ? mapToExcludeRoute(options.exclude) + : []; this.config.setGlobalPrefixOptions({ ...options, exclude, diff --git a/packages/core/test/middleware/middleware-module.spec.ts b/packages/core/test/middleware/middleware-module.spec.ts index 36a4a4f14f3..4130d66e344 100644 --- a/packages/core/test/middleware/middleware-module.spec.ts +++ b/packages/core/test/middleware/middleware-module.spec.ts @@ -1,8 +1,6 @@ import { Injectable, VersioningType } from '@nestjs/common'; -import { addLeadingSlash } from '@nestjs/common/utils/shared.utils'; import { RoutePathFactory } from '@nestjs/core/router/route-path-factory'; import { expect } from 'chai'; -import pathToRegexp = require('path-to-regexp'); import * as sinon from 'sinon'; import { Controller } from '../../../common/decorators/core/controller.decorator'; import { RequestMapping } from '../../../common/decorators/http/request-mapping.decorator'; @@ -19,6 +17,7 @@ import { MiddlewareContainer } from '../../middleware/container'; import { MiddlewareModule } from '../../middleware/middleware-module'; import { RouterExceptionFilters } from '../../router/router-exception-filters'; import { NoopHttpAdapter } from '../utils/noop-adapter.spec'; +import { mapToExcludeRoute } from './../../middleware/utils'; describe('MiddlewareModule', () => { let middlewareModule: MiddlewareModule; @@ -242,13 +241,7 @@ describe('MiddlewareModule', () => { }); (middlewareModule as any).config.setGlobalPrefix('api'); (middlewareModule as any).config.setGlobalPrefixOptions({ - exclude: [ - { - path: 'foo', - requestMethod: RequestMethod.ALL, - pathRegex: pathToRegexp(addLeadingSlash('foo')), - }, - ], + exclude: mapToExcludeRoute(['foo']), }); const allPaths = (middlewareModule as any).getPaths({ diff --git a/packages/core/test/middleware/utils.spec.ts b/packages/core/test/middleware/utils.spec.ts index 754878c2254..bfc75be68a2 100644 --- a/packages/core/test/middleware/utils.spec.ts +++ b/packages/core/test/middleware/utils.spec.ts @@ -1,4 +1,5 @@ import { RequestMethod, Type } from '@nestjs/common'; +import { addLeadingSlash } from '@nestjs/common/utils/shared.utils'; import { expect } from 'chai'; import * as sinon from 'sinon'; import { @@ -10,6 +11,7 @@ import { mapToExcludeRoute, } from '../../middleware/utils'; import { NoopHttpAdapter } from '../utils/noop-adapter.spec'; +import pathToRegexp = require('path-to-regexp'); describe('middleware utils', () => { const noopAdapter = new NoopHttpAdapter({}); @@ -17,6 +19,27 @@ describe('middleware utils', () => { class Test {} function fnMiddleware(req, res, next) {} + describe('mapToExcludeRoute', () => { + it('should return exclude route metadata', () => { + const stringRoute = 'foo'; + const routeInfo = { + path: 'bar', + method: RequestMethod.GET, + }; + expect(mapToExcludeRoute([stringRoute, routeInfo])).to.eql([ + { + path: stringRoute, + requestMethod: RequestMethod.ALL, + pathRegex: pathToRegexp(addLeadingSlash(stringRoute)), + }, + { + path: routeInfo.path, + requestMethod: routeInfo.method, + pathRegex: pathToRegexp(addLeadingSlash(routeInfo.path)), + }, + ]); + }); + }); describe('filterMiddleware', () => { let middleware: any[]; beforeEach(() => { diff --git a/packages/core/test/nest-application.spec.ts b/packages/core/test/nest-application.spec.ts index b9af1f6489b..72231d13b5b 100644 --- a/packages/core/test/nest-application.spec.ts +++ b/packages/core/test/nest-application.spec.ts @@ -1,10 +1,9 @@ import { RequestMethod } from '@nestjs/common'; -import { addLeadingSlash } from '@nestjs/common/utils/shared.utils'; import { expect } from 'chai'; -import pathToRegexp = require('path-to-regexp'); import { ApplicationConfig } from '../application-config'; import { NestContainer } from '../injector/container'; import { NestApplication } from '../nest-application'; +import { mapToExcludeRoute } from './../middleware/utils'; import { NoopHttpAdapter } from './utils/noop-adapter.spec'; describe('NestApplication', () => { @@ -68,18 +67,13 @@ describe('NestApplication', () => { exclude: ['foo', { path: 'bar', method: RequestMethod.GET }], }); expect((instance as any).config.getGlobalPrefixOptions()).to.eql({ - exclude: [ - { - path: 'foo', - requestMethod: RequestMethod.ALL, - pathRegex: pathToRegexp(addLeadingSlash('foo')), - }, + exclude: mapToExcludeRoute([ + 'foo', { path: 'bar', - requestMethod: RequestMethod.GET, - pathRegex: pathToRegexp(addLeadingSlash('bar')), + method: RequestMethod.GET, }, - ], + ]), }); }); }); From 151a67b752bc1da2c74bd8933c73ce122a11e730 Mon Sep 17 00:00:00 2001 From: codytseng Date: Thu, 24 Nov 2022 09:32:09 +0800 Subject: [PATCH 11/18] refactor: `applicationConfig` instead `(instance as any).config` --- packages/core/test/nest-application.spec.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/core/test/nest-application.spec.ts b/packages/core/test/nest-application.spec.ts index 72231d13b5b..b1e44ee6585 100644 --- a/packages/core/test/nest-application.spec.ts +++ b/packages/core/test/nest-application.spec.ts @@ -63,17 +63,12 @@ describe('NestApplication', () => { applicationConfig, {}, ); + const excludeRoute = ['foo', { path: 'bar', method: RequestMethod.GET }]; instance.setGlobalPrefix('api', { - exclude: ['foo', { path: 'bar', method: RequestMethod.GET }], + exclude: excludeRoute, }); - expect((instance as any).config.getGlobalPrefixOptions()).to.eql({ - exclude: mapToExcludeRoute([ - 'foo', - { - path: 'bar', - method: RequestMethod.GET, - }, - ]), + expect(applicationConfig.getGlobalPrefixOptions()).to.eql({ + exclude: mapToExcludeRoute(excludeRoute), }); }); }); From daa20540002c569c3a7ec8ecca00578f7c8a6651 Mon Sep 17 00:00:00 2001 From: codytseng Date: Thu, 24 Nov 2022 11:49:42 +0800 Subject: [PATCH 12/18] style: keep up with current standards --- packages/core/test/middleware/utils.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/test/middleware/utils.spec.ts b/packages/core/test/middleware/utils.spec.ts index bfc75be68a2..a1c91d77bde 100644 --- a/packages/core/test/middleware/utils.spec.ts +++ b/packages/core/test/middleware/utils.spec.ts @@ -11,7 +11,7 @@ import { mapToExcludeRoute, } from '../../middleware/utils'; import { NoopHttpAdapter } from '../utils/noop-adapter.spec'; -import pathToRegexp = require('path-to-regexp'); +import * as pathToRegexp from 'path-to-regexp'; describe('middleware utils', () => { const noopAdapter = new NoopHttpAdapter({}); From ecba3bafde15dd7b3b31974a00888e819ab39e22 Mon Sep 17 00:00:00 2001 From: codytseng Date: Thu, 24 Nov 2022 14:37:59 +0800 Subject: [PATCH 13/18] refactor: create a separate class to retrieve the paths --- packages/core/middleware/middleware-module.ts | 56 ++--------- .../middleware/route-info-path-extractor.ts | 54 +++++++++++ packages/core/nest-application.ts | 6 +- .../test/middleware/middleware-module.spec.ts | 84 +---------------- .../route-info-path-extractor.spec.ts | 93 +++++++++++++++++++ 5 files changed, 163 insertions(+), 130 deletions(-) create mode 100644 packages/core/middleware/route-info-path-extractor.ts create mode 100644 packages/core/test/middleware/route-info-path-extractor.spec.ts diff --git a/packages/core/middleware/middleware-module.ts b/packages/core/middleware/middleware-module.ts index 4c14291c9c8..b55f78f40d5 100644 --- a/packages/core/middleware/middleware-module.ts +++ b/packages/core/middleware/middleware-module.ts @@ -1,15 +1,11 @@ -import { HttpServer, VersioningType } from '@nestjs/common'; +import { HttpServer } from '@nestjs/common'; import { RequestMethod } from '@nestjs/common/enums/request-method.enum'; import { MiddlewareConfiguration, - RouteInfo, NestMiddleware, + RouteInfo, } from '@nestjs/common/interfaces/middleware'; -import { - addLeadingSlash, - isUndefined, - stripEndSlash, -} from '@nestjs/common/utils/shared.utils'; +import { isUndefined } from '@nestjs/common/utils/shared.utils'; import { ApplicationConfig } from '../application-config'; import { InvalidMiddlewareException } from '../errors/exceptions/invalid-middleware.exception'; import { RuntimeException } from '../errors/exceptions/runtime.exception'; @@ -21,13 +17,13 @@ import { Injector } from '../injector/injector'; import { InstanceWrapper } from '../injector/instance-wrapper'; import { InstanceToken, Module } from '../injector/module'; import { REQUEST_CONTEXT_ID } from '../router/request/request-constants'; -import { RoutePathFactory } from '../router/route-path-factory'; import { RouterExceptionFilters } from '../router/router-exception-filters'; import { RouterProxy } from '../router/router-proxy'; -import { isRequestMethodAll, isRouteExcluded } from '../router/utils'; +import { isRequestMethodAll } from '../router/utils'; import { MiddlewareBuilder } from './builder'; import { MiddlewareContainer } from './container'; import { MiddlewareResolver } from './resolver'; +import { RouteInfoPathExtractor } from './route-info-path-extractor'; import { RoutesMapper } from './routes-mapper'; export class MiddlewareModule { @@ -38,11 +34,10 @@ export class MiddlewareModule { private routerExceptionFilter: RouterExceptionFilters; private routesMapper: RoutesMapper; private resolver: MiddlewareResolver; - private config: ApplicationConfig; private container: NestContainer; private httpAdapter: HttpServer; - constructor(private readonly routePathFactory: RoutePathFactory) {} + constructor(private routeInfoPathExtractor: RouteInfoPathExtractor) {} public async register( middlewareContainer: MiddlewareContainer, @@ -60,7 +55,6 @@ export class MiddlewareModule { this.routesMapper = new RoutesMapper(container); this.resolver = new MiddlewareResolver(middlewareContainer); - this.config = config; this.injector = injector; this.container = container; this.httpAdapter = httpAdapter; @@ -275,7 +269,7 @@ export class MiddlewareModule { ) => void, ) { const { method } = routeInfo; - const paths = this.getPaths(routeInfo); + const paths = this.routeInfoPathExtractor.getPaths(routeInfo); const isMethodAll = isRequestMethodAll(method); const requestMethod = RequestMethod[method]; const router = await applicationRef.createMiddlewareFactory(method); @@ -297,40 +291,4 @@ export class MiddlewareModule { ), ); } - - private getPaths({ path, method, version }: RouteInfo) { - const prefixPath = stripEndSlash( - addLeadingSlash(this.config.getGlobalPrefix()), - ); - const excludedRoutes = this.config.getGlobalPrefixOptions().exclude; - - const applicationVersioningConfig = this.config.getVersioning(); - let versionPath = ''; - if (version && applicationVersioningConfig?.type === VersioningType.URI) { - const versionPrefix = this.routePathFactory.getVersionPrefix( - applicationVersioningConfig, - ); - versionPath = addLeadingSlash(versionPrefix + version.toString()); - } - - if (['*', '/*', '/*/', '(.*)', '/(.*)'].includes(path)) { - return Array.isArray(excludedRoutes) - ? [ - prefixPath + versionPath + addLeadingSlash(path), - ...excludedRoutes.map( - route => versionPath + addLeadingSlash(route.path), - ), - ] - : [prefixPath + versionPath + addLeadingSlash(path)]; - } - - if ( - Array.isArray(excludedRoutes) && - isRouteExcluded(excludedRoutes, path, method) - ) { - return [versionPath + addLeadingSlash(path)]; - } - - return [prefixPath + versionPath + addLeadingSlash(path)]; - } } diff --git a/packages/core/middleware/route-info-path-extractor.ts b/packages/core/middleware/route-info-path-extractor.ts new file mode 100644 index 00000000000..67b170d8353 --- /dev/null +++ b/packages/core/middleware/route-info-path-extractor.ts @@ -0,0 +1,54 @@ +import { VersioningType } from '@nestjs/common'; +import { RouteInfo } from '@nestjs/common/interfaces'; +import { + addLeadingSlash, + stripEndSlash, +} from '@nestjs/common/utils/shared.utils'; +import { ApplicationConfig } from '../application-config'; +import { isRouteExcluded } from '../router/utils'; +import { RoutePathFactory } from './../router/route-path-factory'; + +export class RouteInfoPathExtractor { + private routePathFactory: RoutePathFactory; + + constructor(private readonly applicationConfig: ApplicationConfig) { + this.routePathFactory = new RoutePathFactory(applicationConfig); + } + + public getPaths({ path, method, version }: RouteInfo) { + const prefixPath = stripEndSlash( + addLeadingSlash(this.applicationConfig.getGlobalPrefix()), + ); + const excludedRoutes = + this.applicationConfig.getGlobalPrefixOptions().exclude; + + const applicationVersioningConfig = this.applicationConfig.getVersioning(); + let versionPath = ''; + if (version && applicationVersioningConfig?.type === VersioningType.URI) { + const versionPrefix = this.routePathFactory.getVersionPrefix( + applicationVersioningConfig, + ); + versionPath = addLeadingSlash(versionPrefix + version.toString()); + } + + if (['*', '/*', '/*/', '(.*)', '/(.*)'].includes(path)) { + return Array.isArray(excludedRoutes) + ? [ + prefixPath + versionPath + addLeadingSlash(path), + ...excludedRoutes.map( + route => versionPath + addLeadingSlash(route.path), + ), + ] + : [prefixPath + versionPath + addLeadingSlash(path)]; + } + + if ( + Array.isArray(excludedRoutes) && + isRouteExcluded(excludedRoutes, path, method) + ) { + return [versionPath + addLeadingSlash(path)]; + } + + return [prefixPath + versionPath + addLeadingSlash(path)]; + } +} diff --git a/packages/core/nest-application.ts b/packages/core/nest-application.ts index c35b6a046c3..8545b5c0df5 100644 --- a/packages/core/nest-application.ts +++ b/packages/core/nest-application.ts @@ -36,10 +36,10 @@ import { optionalRequire } from './helpers/optional-require'; import { NestContainer } from './injector/container'; import { MiddlewareContainer } from './middleware/container'; import { MiddlewareModule } from './middleware/middleware-module'; +import { RouteInfoPathExtractor } from './middleware/route-info-path-extractor'; import { mapToExcludeRoute } from './middleware/utils'; import { NestApplicationContext } from './nest-application-context'; import { Resolver } from './router/interfaces/resolver.interface'; -import { RoutePathFactory } from './router/route-path-factory'; import { RoutesResolver } from './router/routes-resolver'; const { SocketModule } = optionalRequire( @@ -83,7 +83,9 @@ export class NestApplication this.selectContextModule(); this.registerHttpServer(); - this.middlewareModule = new MiddlewareModule(new RoutePathFactory(config)); + this.middlewareModule = new MiddlewareModule( + new RouteInfoPathExtractor(config), + ); this.routesResolver = new RoutesResolver( this.container, diff --git a/packages/core/test/middleware/middleware-module.spec.ts b/packages/core/test/middleware/middleware-module.spec.ts index 4130d66e344..ad5c4d69db3 100644 --- a/packages/core/test/middleware/middleware-module.spec.ts +++ b/packages/core/test/middleware/middleware-module.spec.ts @@ -1,5 +1,5 @@ -import { Injectable, VersioningType } from '@nestjs/common'; -import { RoutePathFactory } from '@nestjs/core/router/route-path-factory'; +import { Injectable } from '@nestjs/common'; +import { RouteInfoPathExtractor } from '@nestjs/core/middleware/route-info-path-extractor'; import { expect } from 'chai'; import * as sinon from 'sinon'; import { Controller } from '../../../common/decorators/core/controller.decorator'; @@ -17,7 +17,6 @@ import { MiddlewareContainer } from '../../middleware/container'; import { MiddlewareModule } from '../../middleware/middleware-module'; import { RouterExceptionFilters } from '../../router/router-exception-filters'; import { NoopHttpAdapter } from '../utils/noop-adapter.spec'; -import { mapToExcludeRoute } from './../../middleware/utils'; describe('MiddlewareModule', () => { let middlewareModule: MiddlewareModule; @@ -41,7 +40,9 @@ describe('MiddlewareModule', () => { beforeEach(() => { const appConfig = new ApplicationConfig(); - middlewareModule = new MiddlewareModule(new RoutePathFactory(appConfig)); + middlewareModule = new MiddlewareModule( + new RouteInfoPathExtractor(appConfig), + ); (middlewareModule as any).routerExceptionFilter = new RouterExceptionFilters( new NestContainer(), @@ -197,79 +198,4 @@ describe('MiddlewareModule', () => { expect(createMiddlewareFactoryStub.calledOnce).to.be.true; }); }); - describe('getPaths', () => { - it(`should return correct paths`, () => { - (middlewareModule as any).config.enableVersioning({ - type: VersioningType.URI, - }); - - const paths = (middlewareModule as any).getPaths({ - path: '*', - method: RequestMethod.ALL, - }); - expect(paths).to.eql(['/*']); - - const versioningPaths = (middlewareModule as any).getPaths({ - path: '*', - method: RequestMethod.ALL, - version: '1', - }); - expect(versioningPaths).to.eql(['/v1/*']); - }); - it(`should return correct paths when set global prefix`, () => { - (middlewareModule as any).config.enableVersioning({ - type: VersioningType.URI, - }); - (middlewareModule as any).config.setGlobalPrefix('api'); - - const paths = (middlewareModule as any).getPaths({ - path: '*', - method: RequestMethod.ALL, - }); - expect(paths).to.eql(['/api/*']); - - const versioningPaths = (middlewareModule as any).getPaths({ - path: '*', - method: RequestMethod.ALL, - version: '1', - }); - expect(versioningPaths).to.eql(['/api/v1/*']); - }); - it(`should return correct paths when set global prefix and global prefix options`, () => { - (middlewareModule as any).config.enableVersioning({ - type: VersioningType.URI, - }); - (middlewareModule as any).config.setGlobalPrefix('api'); - (middlewareModule as any).config.setGlobalPrefixOptions({ - exclude: mapToExcludeRoute(['foo']), - }); - - const allPaths = (middlewareModule as any).getPaths({ - path: '*', - method: RequestMethod.ALL, - }); - expect(allPaths).to.eql(['/api/*', '/foo']); - - const allVersioningPaths = (middlewareModule as any).getPaths({ - path: '*', - method: RequestMethod.ALL, - version: '1', - }); - expect(allVersioningPaths).to.eql(['/api/v1/*', '/v1/foo']); - - const excludedPaths = (middlewareModule as any).getPaths({ - path: 'foo', - method: RequestMethod.ALL, - version: '1', - }); - expect(excludedPaths).to.eql(['/v1/foo']); - - const normalPaths = (middlewareModule as any).getPaths({ - path: 'bar', - method: RequestMethod.ALL, - version: '1', - }); - expect(normalPaths).to.eql(['/api/v1/bar']); - }); - }); }); diff --git a/packages/core/test/middleware/route-info-path-extractor.spec.ts b/packages/core/test/middleware/route-info-path-extractor.spec.ts new file mode 100644 index 00000000000..0a77108e412 --- /dev/null +++ b/packages/core/test/middleware/route-info-path-extractor.spec.ts @@ -0,0 +1,93 @@ +import { RequestMethod, VersioningType } from '@nestjs/common'; +import { ApplicationConfig } from '@nestjs/core'; +import { mapToExcludeRoute } from '@nestjs/core/middleware/utils'; +import { expect } from 'chai'; +import { RouteInfoPathExtractor } from './../../middleware/route-info-path-extractor'; + +describe('RouteInfoPathExtractor', () => { + describe('getPaths', () => { + let appConfig: ApplicationConfig; + let routeInfoPathExtractor: RouteInfoPathExtractor; + beforeEach(() => { + appConfig = new ApplicationConfig(); + appConfig.enableVersioning({ + type: VersioningType.URI, + }); + routeInfoPathExtractor = new RouteInfoPathExtractor(appConfig); + }); + + it(`should return correct paths`, () => { + expect( + routeInfoPathExtractor.getPaths({ + path: '*', + method: RequestMethod.ALL, + }), + ).to.eql(['/*']); + + expect( + routeInfoPathExtractor.getPaths({ + path: '*', + method: RequestMethod.ALL, + version: '1', + }), + ).to.eql(['/v1/*']); + }); + + it(`should return correct paths when set global prefix`, () => { + appConfig.setGlobalPrefix('api'); + + expect( + routeInfoPathExtractor.getPaths({ + path: '*', + method: RequestMethod.ALL, + }), + ).to.eql(['/api/*']); + + expect( + routeInfoPathExtractor.getPaths({ + path: '*', + method: RequestMethod.ALL, + version: '1', + }), + ).to.eql(['/api/v1/*']); + }); + + it(`should return correct paths when set global prefix and global prefix options`, () => { + appConfig.setGlobalPrefix('api'); + appConfig.setGlobalPrefixOptions({ + exclude: mapToExcludeRoute(['foo']), + }); + + expect( + routeInfoPathExtractor.getPaths({ + path: '*', + method: RequestMethod.ALL, + }), + ).to.eql(['/api/*', '/foo']); + + expect( + routeInfoPathExtractor.getPaths({ + path: '*', + method: RequestMethod.ALL, + version: '1', + }), + ).to.eql(['/api/v1/*', '/v1/foo']); + + expect( + routeInfoPathExtractor.getPaths({ + path: 'foo', + method: RequestMethod.ALL, + version: '1', + }), + ).to.eql(['/v1/foo']); + + expect( + routeInfoPathExtractor.getPaths({ + path: 'bar', + method: RequestMethod.ALL, + version: '1', + }), + ).to.eql(['/api/v1/bar']); + }); + }); +}); From a1f17e2271642b0f0cbe52d8cb009fa25eccf51b Mon Sep 17 00:00:00 2001 From: codytseng Date: Thu, 24 Nov 2022 21:34:45 +0800 Subject: [PATCH 14/18] refactor: rename `getPaths` to `extractPathsFrom` --- packages/core/middleware/middleware-module.ts | 2 +- .../core/middleware/route-info-path-extractor.ts | 2 +- .../middleware/route-info-path-extractor.spec.ts | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/core/middleware/middleware-module.ts b/packages/core/middleware/middleware-module.ts index b55f78f40d5..4aec374da29 100644 --- a/packages/core/middleware/middleware-module.ts +++ b/packages/core/middleware/middleware-module.ts @@ -269,7 +269,7 @@ export class MiddlewareModule { ) => void, ) { const { method } = routeInfo; - const paths = this.routeInfoPathExtractor.getPaths(routeInfo); + const paths = this.routeInfoPathExtractor.extractPathsFrom(routeInfo); const isMethodAll = isRequestMethodAll(method); const requestMethod = RequestMethod[method]; const router = await applicationRef.createMiddlewareFactory(method); diff --git a/packages/core/middleware/route-info-path-extractor.ts b/packages/core/middleware/route-info-path-extractor.ts index 67b170d8353..c3181872259 100644 --- a/packages/core/middleware/route-info-path-extractor.ts +++ b/packages/core/middleware/route-info-path-extractor.ts @@ -15,7 +15,7 @@ export class RouteInfoPathExtractor { this.routePathFactory = new RoutePathFactory(applicationConfig); } - public getPaths({ path, method, version }: RouteInfo) { + public extractPathsFrom({ path, method, version }: RouteInfo) { const prefixPath = stripEndSlash( addLeadingSlash(this.applicationConfig.getGlobalPrefix()), ); diff --git a/packages/core/test/middleware/route-info-path-extractor.spec.ts b/packages/core/test/middleware/route-info-path-extractor.spec.ts index 0a77108e412..9ff9c82d8ed 100644 --- a/packages/core/test/middleware/route-info-path-extractor.spec.ts +++ b/packages/core/test/middleware/route-info-path-extractor.spec.ts @@ -18,14 +18,14 @@ describe('RouteInfoPathExtractor', () => { it(`should return correct paths`, () => { expect( - routeInfoPathExtractor.getPaths({ + routeInfoPathExtractor.extractPathsFrom({ path: '*', method: RequestMethod.ALL, }), ).to.eql(['/*']); expect( - routeInfoPathExtractor.getPaths({ + routeInfoPathExtractor.extractPathsFrom({ path: '*', method: RequestMethod.ALL, version: '1', @@ -37,14 +37,14 @@ describe('RouteInfoPathExtractor', () => { appConfig.setGlobalPrefix('api'); expect( - routeInfoPathExtractor.getPaths({ + routeInfoPathExtractor.extractPathsFrom({ path: '*', method: RequestMethod.ALL, }), ).to.eql(['/api/*']); expect( - routeInfoPathExtractor.getPaths({ + routeInfoPathExtractor.extractPathsFrom({ path: '*', method: RequestMethod.ALL, version: '1', @@ -59,14 +59,14 @@ describe('RouteInfoPathExtractor', () => { }); expect( - routeInfoPathExtractor.getPaths({ + routeInfoPathExtractor.extractPathsFrom({ path: '*', method: RequestMethod.ALL, }), ).to.eql(['/api/*', '/foo']); expect( - routeInfoPathExtractor.getPaths({ + routeInfoPathExtractor.extractPathsFrom({ path: '*', method: RequestMethod.ALL, version: '1', @@ -74,7 +74,7 @@ describe('RouteInfoPathExtractor', () => { ).to.eql(['/api/v1/*', '/v1/foo']); expect( - routeInfoPathExtractor.getPaths({ + routeInfoPathExtractor.extractPathsFrom({ path: 'foo', method: RequestMethod.ALL, version: '1', @@ -82,7 +82,7 @@ describe('RouteInfoPathExtractor', () => { ).to.eql(['/v1/foo']); expect( - routeInfoPathExtractor.getPaths({ + routeInfoPathExtractor.extractPathsFrom({ path: 'bar', method: RequestMethod.ALL, version: '1', From 33fe1d03377866fdd186d032a72dfac89bfec2a4 Mon Sep 17 00:00:00 2001 From: codytseng Date: Wed, 1 Feb 2023 22:41:24 +0800 Subject: [PATCH 15/18] fix: duplicate identifier --- .../core/router/interfaces/exclude-route-metadata.interface.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/router/interfaces/exclude-route-metadata.interface.ts b/packages/core/router/interfaces/exclude-route-metadata.interface.ts index ef0713cd8b9..b7f93b60098 100644 --- a/packages/core/router/interfaces/exclude-route-metadata.interface.ts +++ b/packages/core/router/interfaces/exclude-route-metadata.interface.ts @@ -1,7 +1,6 @@ import { RequestMethod } from '@nestjs/common'; export interface ExcludeRouteMetadata { - path: string; /** * Route path. */ From c6dbc05bb63c63df08707a537f8e0ab5879cccf5 Mon Sep 17 00:00:00 2001 From: codytseng Date: Wed, 1 Feb 2023 23:22:02 +0800 Subject: [PATCH 16/18] refactor: MiddlewareModule constructor parameters --- packages/core/middleware/middleware-module.ts | 5 ++--- packages/core/nest-application.ts | 7 +------ .../test/middleware/middleware-module.spec.ts | 18 ++++++++---------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/packages/core/middleware/middleware-module.ts b/packages/core/middleware/middleware-module.ts index 5530a632318..a007c007c0e 100644 --- a/packages/core/middleware/middleware-module.ts +++ b/packages/core/middleware/middleware-module.ts @@ -47,8 +47,7 @@ export class MiddlewareModule< private httpAdapter: HttpServer; private graphInspector: GraphInspector; private appOptions: TAppOptions; - - constructor(private routeInfoPathExtractor: RouteInfoPathExtractor) {} + private routeInfoPathExtractor: RouteInfoPathExtractor; public async register( middlewareContainer: MiddlewareContainer, @@ -69,7 +68,7 @@ export class MiddlewareModule< ); this.routesMapper = new RoutesMapper(container); this.resolver = new MiddlewareResolver(middlewareContainer, injector); - + this.routeInfoPathExtractor = new RouteInfoPathExtractor(config); this.injector = injector; this.container = container; this.httpAdapter = httpAdapter; diff --git a/packages/core/nest-application.ts b/packages/core/nest-application.ts index 7aeb18faa0d..174fc659152 100644 --- a/packages/core/nest-application.ts +++ b/packages/core/nest-application.ts @@ -86,13 +86,8 @@ export class NestApplication this.selectContextModule(); this.registerHttpServer(); - this.middlewareModule = new MiddlewareModule( - new RouteInfoPathExtractor(config), - ); this.injector = new Injector({ preview: this.appOptions.preview }); - this.middlewareModule = new MiddlewareModule( - new RouteInfoPathExtractor(config), - ); + this.middlewareModule = new MiddlewareModule(); this.routesResolver = new RoutesResolver( this.container, this.config, diff --git a/packages/core/test/middleware/middleware-module.spec.ts b/packages/core/test/middleware/middleware-module.spec.ts index 1ff43e42fb7..8f113dee1a8 100644 --- a/packages/core/test/middleware/middleware-module.spec.ts +++ b/packages/core/test/middleware/middleware-module.spec.ts @@ -48,22 +48,20 @@ describe('MiddlewareModule', () => { const container = new NestContainer(); const appConfig = new ApplicationConfig(); graphInspector = new GraphInspector(container); - middlewareModule = new MiddlewareModule( - new RouteInfoPathExtractor(appConfig), + middlewareModule = new MiddlewareModule(); + middlewareModule['routerExceptionFilter'] = new RouterExceptionFilters( + new NestContainer(), + appConfig, + new NoopHttpAdapter({}), + ); + middlewareModule['routeInfoPathExtractor'] = new RouteInfoPathExtractor( + appConfig, ); - (middlewareModule as any).routerExceptionFilter = - new RouterExceptionFilters( - new NestContainer(), - appConfig, - new NoopHttpAdapter({}), - ); - (middlewareModule as any).config = appConfig; middlewareModule['routerExceptionFilter'] = new RouterExceptionFilters( container, appConfig, new NoopHttpAdapter({}), ); - middlewareModule['config'] = appConfig; middlewareModule['graphInspector'] = graphInspector; }); From 5e5828ba129276bdc54ea75ec0fe676af8ed3bd4 Mon Sep 17 00:00:00 2001 From: codytseng Date: Thu, 2 Feb 2023 15:15:54 +0800 Subject: [PATCH 17/18] refactor: delete unused import --- packages/core/nest-application.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/nest-application.ts b/packages/core/nest-application.ts index 174fc659152..3b25d587738 100644 --- a/packages/core/nest-application.ts +++ b/packages/core/nest-application.ts @@ -38,7 +38,6 @@ import { Injector } from './injector/injector'; import { GraphInspector } from './inspector/graph-inspector'; import { MiddlewareContainer } from './middleware/container'; import { MiddlewareModule } from './middleware/middleware-module'; -import { RouteInfoPathExtractor } from './middleware/route-info-path-extractor'; import { mapToExcludeRoute } from './middleware/utils'; import { NestApplicationContext } from './nest-application-context'; import { Resolver } from './router/interfaces/resolver.interface'; From 6d64d91122423b0d35b4316752674b2f2d36f467 Mon Sep 17 00:00:00 2001 From: Cody Tseng Date: Fri, 3 Feb 2023 17:03:01 +0800 Subject: [PATCH 18/18] Update packages/core/middleware/route-info-path-extractor.ts Co-authored-by: Kamil Mysliwiec --- packages/core/middleware/route-info-path-extractor.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/middleware/route-info-path-extractor.ts b/packages/core/middleware/route-info-path-extractor.ts index c3181872259..dc03893ea94 100644 --- a/packages/core/middleware/route-info-path-extractor.ts +++ b/packages/core/middleware/route-info-path-extractor.ts @@ -31,7 +31,8 @@ export class RouteInfoPathExtractor { versionPath = addLeadingSlash(versionPrefix + version.toString()); } - if (['*', '/*', '/*/', '(.*)', '/(.*)'].includes(path)) { + const isAWildcard = ['*', '/*', '/*/', '(.*)', '/(.*)'].includes(path); + if (isAWildcard) { return Array.isArray(excludedRoutes) ? [ prefixPath + versionPath + addLeadingSlash(path),