Repository: nestjs/nest
Pull request #11041 (2023-02-03 22:23:48)

fix(core): :ambulance: Fix for calculating durability of a provider
## PR Checklist
Please check if your PR fulfills the following requirements:

- [x] The commit message follows our guidelines: https://github.com/nestjs/nest/blob/master/CONTRIBUTING.md
- [x] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)


## PR Type
What kind of change does this PR introduce?

<!-- Please check the one that applies to this PR using "x". -->
- [x] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Other... Please describe:

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->

Issue Number: #11002

## What is the new behavior?
Providers are correctly scoped.

## Does this PR introduce a breaking change?
- [ ] Yes
- [x] No

<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->


## Other information

![nestJSBug11002 drawio](https://user-images.githubusercontent.com/138939/216764327-5d6cbe8d-2cf3-4686-b916-602968975af9.png)




Patch:
diff --git a/Readme.md b/Readme.md
index 16f48336d..0524401fb 100644
--- a/Readme.md
+++ b/Readme.md
@@ -11,6 +11,7 @@
 <a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
 <a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
 <a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
+<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
 <a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
 <a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
 <a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
diff --git a/integration/nest-application/global-prefix/src/app.controller.ts b/integration/nest-application/global-prefix/src/app.controller.ts
index d826cd0db..912c0d76c 100644
--- a/integration/nest-application/global-prefix/src/app.controller.ts
+++ b/integration/nest-application/global-prefix/src/app.controller.ts
@@ -7,11 +7,6 @@ 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 f182915c4..85d1e6ac4 100644
--- a/integration/nest-application/global-prefix/src/app.module.ts
+++ b/integration/nest-application/global-prefix/src/app.module.ts
@@ -22,11 +22,6 @@ 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/lerna.json b/lerna.json
index 3b44f42f8..db9ca5def 100644
--- a/lerna.json
+++ b/lerna.json
@@ -3,5 +3,5 @@
   "packages": [
     "packages/*"
   ],
-  "version": "9.3.2"
+  "version": "9.3.1"
 }
diff --git a/packages/common/constants.ts b/packages/common/constants.ts
index f25ddff68..2d18929e0 100644
--- a/packages/common/constants.ts
+++ b/packages/common/constants.ts
@@ -35,7 +35,7 @@ export const ENHANCER_KEY_TO_SUBTYPE_MAP = {
 } as const;
 
 export type EnhancerSubtype =
-  (typeof ENHANCER_KEY_TO_SUBTYPE_MAP)[keyof typeof ENHANCER_KEY_TO_SUBTYPE_MAP];
+  typeof ENHANCER_KEY_TO_SUBTYPE_MAP[keyof typeof ENHANCER_KEY_TO_SUBTYPE_MAP];
 
 export const RENDER_METADATA = '__renderTemplate__';
 export const HTTP_CODE_METADATA = '__httpCode__';
diff --git a/packages/common/exceptions/http.exception.ts b/packages/common/exceptions/http.exception.ts
index 800287695..7bdd1b111 100644
--- a/packages/common/exceptions/http.exception.ts
+++ b/packages/common/exceptions/http.exception.ts
@@ -99,9 +99,9 @@ export class HttpException extends Error {
     ) {
       this.message = (this.response as Record<string, any>).message;
     } else if (this.constructor) {
-      this.message =
-        this.constructor.name.match(/[A-Z][a-z]+|[0-9]+/g)?.join(' ') ??
-        'Error';
+      this.message = this.constructor.name
+        .match(/[A-Z][a-z]+|[0-9]+/g)
+        ?.join(' ') ?? 'Error';
     }
   }
 
diff --git a/packages/common/index.ts b/packages/common/index.ts
index 99d074870..c8d815187 100644
--- a/packages/common/index.ts
+++ b/packages/common/index.ts
@@ -1,6 +1,6 @@
 /*
  * Nest @common
- * Copyright(c) 2017 - 2023 Kamil Mysliwiec
+ * Copyright(c) 2017 - 2022 Kamil Mysliwiec
  * https://nestjs.com
  * MIT Licensed
  */
diff --git a/packages/common/package.json b/packages/common/package.json
index 8b5979271..22aea56b6 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@nestjs/common",
-  "version": "9.3.2",
+  "version": "9.3.1",
   "description": "Nest - modern, fast, powerful node.js web framework (@common)",
   "author": "Kamil Mysliwiec",
   "homepage": "https://nestjs.com",
diff --git a/packages/common/pipes/validation.pipe.ts b/packages/common/pipes/validation.pipe.ts
index eed2fa017..d13437523 100644
--- a/packages/common/pipes/validation.pipe.ts
+++ b/packages/common/pipes/validation.pipe.ts
@@ -66,10 +66,8 @@ export class ValidationPipe implements PipeTransform<any> {
       ...validatorOptions
     } = options;
 
-    // @see https://github.com/nestjs/nest/issues/10683#issuecomment-1413690508
-    this.validatorOptions = { forbidUnknownValues: false, ...validatorOptions };
-
     this.isTransformEnabled = !!transform;
+    this.validatorOptions = validatorOptions;
     this.transformOptions = transformOptions;
     this.isDetailedOutputDisabled = disableErrorMessages;
     this.validateCustomDecorators = validateCustomDecorators || false;
diff --git a/packages/core/index.ts b/packages/core/index.ts
index 75c7156e3..1babf6c15 100644
--- a/packages/core/index.ts
+++ b/packages/core/index.ts
@@ -1,6 +1,6 @@
 /*
  * Nest @core
- * Copyright(c) 2017 - 2023 Kamil Mysliwiec
+ * Copyright(c) 2017 - 2022 Kamil Mysliwiec
  * https://nestjs.com
  * MIT Licensed
  */
diff --git a/packages/core/injector/compiler.ts b/packages/core/injector/compiler.ts
index 353e27581..6c707fd61 100644
--- a/packages/core/injector/compiler.ts
+++ b/packages/core/injector/compiler.ts
@@ -1,8 +1,4 @@
-import {
-  DynamicModule,
-  ForwardReference,
-  Type,
-} from '@nestjs/common/interfaces';
+import { DynamicModule, Type } from '@nestjs/common/interfaces';
 import { ModuleTokenFactory } from './module-token-factory';
 
 export interface ModuleFactory {
@@ -22,25 +18,19 @@ export class ModuleCompiler {
     return { type, dynamicMetadata, token };
   }
 
-  public extractMetadata(
-    metatype: Type<any> | ForwardReference | DynamicModule,
-  ): {
+  public extractMetadata(metatype: Type<any> | DynamicModule): {
     type: Type<any>;
     dynamicMetadata?: Partial<DynamicModule> | undefined;
   } {
     if (!this.isDynamicModule(metatype)) {
-      return {
-        type: (metatype as ForwardReference)?.forwardRef
-          ? (metatype as ForwardReference).forwardRef()
-          : metatype,
-      };
+      return { type: metatype };
     }
     const { module: type, ...dynamicMetadata } = metatype;
     return { type, dynamicMetadata };
   }
 
   public isDynamicModule(
-    module: Type<any> | DynamicModule | ForwardReference,
+    module: Type<any> | DynamicModule,
   ): module is DynamicModule {
     return !!(module as DynamicModule).module;
   }
diff --git a/packages/core/injector/injector.ts b/packages/core/injector/injector.ts
index 4930d4768..7d32a173f 100644
--- a/packages/core/injector/injector.ts
+++ b/packages/core/injector/injector.ts
@@ -353,9 +353,7 @@ export class Injector {
   }
 
   public reflectConstructorParams<T>(type: Type<T>): any[] {
-    const paramtypes = [
-      ...(Reflect.getMetadata(PARAMTYPES_METADATA, type) || []),
-    ];
+    const paramtypes = [...(Reflect.getMetadata(PARAMTYPES_METADATA, type) || [])];
     const selfParams = this.reflectSelfParams<T>(type);
 
     selfParams.forEach(({ index, param }) => (paramtypes[index] = param));
diff --git a/packages/core/injector/instance-wrapper.ts b/packages/core/injector/instance-wrapper.ts
index 79e4f1d69..24e4a56ce 100644
--- a/packages/core/injector/instance-wrapper.ts
+++ b/packages/core/injector/instance-wrapper.ts
@@ -203,15 +203,18 @@ export class InstanceWrapper<T = any> {
     if (!isUndefined(this.isTreeDurable)) {
       return this.isTreeDurable;
     }
-    if (this.durable === true) {
-      this.isTreeDurable = true;
-      this.printIntrospectedAsDurable();
+    if (this.scope === Scope.REQUEST) {
+      this.isTreeDurable = this.durable === undefined ? false : this.durable;
+      if (this.isTreeDurable) {
+        this.printIntrospectedAsDurable();
+      }
       return this.isTreeDurable;
     }
     const isStatic = this.isDependencyTreeStatic();
     if (isStatic) {
       return false;
     }
+
     const isTreeNonDurable = this.introspectDepsAttribute(
       (collection, registry) =>
         collection.some(
@@ -221,7 +224,7 @@ export class InstanceWrapper<T = any> {
         ),
       lookupRegistry,
     );
-    this.isTreeDurable = !isTreeNonDurable && this.durable !== false;
+    this.isTreeDurable = !isTreeNonDurable;
     if (this.isTreeDurable) {
       this.printIntrospectedAsDurable();
     }
@@ -243,25 +246,23 @@ export class InstanceWrapper<T = any> {
     const { dependencies, properties, enhancers } =
       this[INSTANCE_METADATA_SYMBOL];
 
-    let introspectionResult =
-      (dependencies && callback(dependencies, lookupRegistry)) || !dependencies;
+    let introspectionResult = dependencies
+      ? callback(dependencies, lookupRegistry)
+      : false;
 
-    if (!introspectionResult || !(properties || enhancers)) {
+    if (introspectionResult || !(properties || enhancers)) {
       return introspectionResult;
     }
-    const propertiesHosts = (properties || []).map(item => item.wrapper);
-    introspectionResult =
-      introspectionResult &&
-      ((properties &&
-        callback(
+    introspectionResult = properties
+      ? callback(
           properties.map(item => item.wrapper),
           lookupRegistry,
-        )) ||
-        !properties);
-    if (!introspectionResult || !enhancers) {
+        )
+      : false;
+    if (introspectionResult || !enhancers) {
       return introspectionResult;
     }
-    return callback(enhancers, lookupRegistry);
+    return enhancers ? callback(enhancers, lookupRegistry) : false;
   }
 
   public isDependencyTreeStatic(lookupRegistry: string[] = []): boolean {
@@ -273,10 +274,10 @@ export class InstanceWrapper<T = any> {
       this.printIntrospectedAsRequestScoped();
       return this.isTreeStatic;
     }
-    this.isTreeStatic = this.introspectDepsAttribute(
+    this.isTreeStatic = !this.introspectDepsAttribute(
       (collection, registry) =>
-        collection.every((item: InstanceWrapper) =>
-          item.isDependencyTreeStatic(registry),
+        collection.some(
+          (item: InstanceWrapper) => !item.isDependencyTreeStatic(registry),
         ),
       lookupRegistry,
     );
diff --git a/packages/core/inspector/uuid-factory.ts b/packages/core/inspector/uuid-factory.ts
index 979760975..62b973ff2 100644
--- a/packages/core/inspector/uuid-factory.ts
+++ b/packages/core/inspector/uuid-factory.ts
@@ -1,4 +1,4 @@
-import { randomStringGenerator } from '@nestjs/common/utils/random-string-generator.util';
+import { randomStringGenerator } from '../../common/utils/random-string-generator.util';
 import { DeterministicUuidRegistry } from './deterministic-uuid-registry';
 
 export enum UuidFactoryMode {
diff --git a/packages/core/middleware/middleware-module.ts b/packages/core/middleware/middleware-module.ts
index a007c007c..3885bab2d 100644
--- a/packages/core/middleware/middleware-module.ts
+++ b/packages/core/middleware/middleware-module.ts
@@ -1,4 +1,4 @@
-import { HttpServer, Logger } from '@nestjs/common';
+import { HttpServer, Logger, VersioningType } from '@nestjs/common';
 import { RequestMethod } from '@nestjs/common/enums/request-method.enum';
 import {
   MiddlewareConfiguration,
@@ -6,7 +6,10 @@ import {
   RouteInfo,
 } from '@nestjs/common/interfaces/middleware';
 import { NestApplicationContextOptions } from '@nestjs/common/interfaces/nest-application-context-options.interface';
-import { isUndefined } from '@nestjs/common/utils/shared.utils';
+import {
+  addLeadingSlash,
+  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';
@@ -15,7 +18,7 @@ import { ExecutionContextHost } from '../helpers/execution-context-host';
 import { STATIC_CONTEXT } from '../injector/constants';
 import { NestContainer } from '../injector/container';
 import { Injector } from '../injector/injector';
-import { ContextId, InstanceWrapper } from '../injector/instance-wrapper';
+import { InstanceWrapper } from '../injector/instance-wrapper';
 import { InstanceToken, Module } from '../injector/module';
 import { GraphInspector } from '../inspector/graph-inspector';
 import {
@@ -23,13 +26,13 @@ import {
   MiddlewareEntrypointMetadata,
 } from '../inspector/interfaces/entrypoint.interface';
 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 } from '../router/utils';
+import { isRequestMethodAll, isRouteExcluded } 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<
@@ -43,11 +46,13 @@ export class MiddlewareModule<
   private routerExceptionFilter: RouterExceptionFilters;
   private routesMapper: RoutesMapper;
   private resolver: MiddlewareResolver;
+  private config: ApplicationConfig;
   private container: NestContainer;
   private httpAdapter: HttpServer;
   private graphInspector: GraphInspector;
   private appOptions: TAppOptions;
-  private routeInfoPathExtractor: RouteInfoPathExtractor;
+
+  constructor(private readonly routePathFactory: RoutePathFactory) {}
 
   public async register(
     middlewareContainer: MiddlewareContainer,
@@ -68,7 +73,8 @@ export class MiddlewareModule<
     );
     this.routesMapper = new RoutesMapper(container);
     this.resolver = new MiddlewareResolver(middlewareContainer, injector);
-    this.routeInfoPathExtractor = new RouteInfoPathExtractor(config);
+
+    this.config = config;
     this.injector = injector;
     this.container = container;
     this.httpAdapter = httpAdapter;
@@ -244,9 +250,6 @@ export class MiddlewareModule<
       const proxy = await this.createProxy(instance);
       return this.registerHandler(applicationRef, routeInfo, proxy);
     }
-
-    const isTreeDurable = wrapper.isDependencyTreeDurable();
-
     await this.registerHandler(
       applicationRef,
       routeInfo,
@@ -256,7 +259,19 @@ export class MiddlewareModule<
         next: () => void,
       ) => {
         try {
-          const contextId = this.getContextId(req, isTreeDurable);
+          const contextId = ContextIdFactory.getByRequest(req);
+          if (!req[REQUEST_CONTEXT_ID]) {
+            Object.defineProperty(req, REQUEST_CONTEXT_ID, {
+              value: contextId,
+              enumerable: false,
+              writable: false,
+              configurable: false,
+            });
+            this.container.registerRequestProvider(
+              contextId.getParent ? contextId.payload : req,
+              contextId,
+            );
+          }
           const contextInstance = await this.injector.loadPerContext(
             instance,
             moduleRef,
@@ -301,18 +316,44 @@ export class MiddlewareModule<
 
   private async registerHandler(
     applicationRef: HttpServer,
-    routeInfo: RouteInfo,
+    { path, method, version }: RouteInfo,
     proxy: <TRequest, TResponse>(
       req: TRequest,
       res: TResponse,
       next: () => void,
     ) => void,
   ) {
-    const { method } = routeInfo;
-    const paths = this.routeInfoPathExtractor.extractPathsFrom(routeInfo);
+    const prefix = this.config.getGlobalPrefix();
+    const excludedRoutes = this.config.getGlobalPrefixOptions().exclude;
+    const isAWildcard = ['*', '/*', '(.*)', '/(.*)'].includes(path);
+    if (
+      (Array.isArray(excludedRoutes) &&
+        isRouteExcluded(excludedRoutes, path, method)) ||
+      isAWildcard
+    ) {
+      path = 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 applicationVersioningConfig = this.config.getVersioning();
+    if (version && applicationVersioningConfig.type === VersioningType.URI) {
+      const versionPrefix = this.routePathFactory.getVersionPrefix(
+        applicationVersioningConfig,
+      );
+      path = `/${versionPrefix}${version.toString()}${path}`;
+    }
+
     const isMethodAll = isRequestMethodAll(method);
     const requestMethod = RequestMethod[method];
     const router = await applicationRef.createMiddlewareFactory(method);
+
     const middlewareFunction = isMethodAll
       ? proxy
       : <TRequest, TResponse>(
@@ -325,22 +366,7 @@ export class MiddlewareModule<
           }
           return next();
         };
-    paths.forEach(path => router(path, middlewareFunction));
-  }
 
-  private getContextId(request: unknown, isTreeDurable: boolean): ContextId {
-    const contextId = ContextIdFactory.getByRequest(request);
-    if (!request[REQUEST_CONTEXT_ID]) {
-      Object.defineProperty(request, REQUEST_CONTEXT_ID, {
-        value: contextId,
-        enumerable: false,
-        writable: false,
-        configurable: false,
-      });
-
-      const requestProviderValue = isTreeDurable ? contextId.payload : request;
-      this.container.registerRequestProvider(requestProviderValue, contextId);
-    }
-    return contextId;
+    router(path, middlewareFunction);
   }
 }
diff --git a/packages/core/middleware/route-info-path-extractor.ts b/packages/core/middleware/route-info-path-extractor.ts
deleted file mode 100644
index dc03893ea..000000000
--- a/packages/core/middleware/route-info-path-extractor.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-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 extractPathsFrom({ 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());
-    }
-
-    const isAWildcard = ['*', '/*', '/*/', '(.*)', '/(.*)'].includes(path);
-    if (isAWildcard) {
-      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/utils.ts b/packages/core/middleware/utils.ts
index d9365e90f..d0aad4849 100644
--- a/packages/core/middleware/utils.ts
+++ b/packages/core/middleware/utils.ts
@@ -1,10 +1,6 @@
 import { RequestMethod } from '@nestjs/common';
 import { HttpServer, RouteInfo, Type } from '@nestjs/common/interfaces';
-import {
-  addLeadingSlash,
-  isFunction,
-  isString,
-} from '@nestjs/common/utils/shared.utils';
+import { isFunction } from '@nestjs/common/utils/shared.utils';
 import { iterate } from 'iterare';
 import * as pathToRegexp from 'path-to-regexp';
 import { v4 as uuid } from 'uuid';
@@ -12,22 +8,13 @@ import { ExcludeRouteMetadata } from '../router/interfaces/exclude-route-metadat
 import { isRouteExcluded } from '../router/utils';
 
 export const mapToExcludeRoute = (
-  routes: (string | RouteInfo)[],
+  routes: RouteInfo[],
 ): ExcludeRouteMetadata[] => {
-  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)),
-    };
-  });
+  return routes.map(({ path, method }) => ({
+    pathRegex: pathToRegexp(path),
+    requestMethod: method,
+    path,
+  }));
 };
 
 export const filterMiddleware = <T extends Function | Type<any> = any>(
diff --git a/packages/core/nest-application.ts b/packages/core/nest-application.ts
index 3b25d5877..b5fae0e22 100644
--- a/packages/core/nest-application.ts
+++ b/packages/core/nest-application.ts
@@ -7,6 +7,7 @@ import {
   NestHybridApplicationOptions,
   NestInterceptor,
   PipeTransform,
+  RequestMethod,
   VersioningOptions,
   VersioningType,
   WebSocketAdapter,
@@ -14,6 +15,7 @@ import {
 import {
   GlobalPrefixOptions,
   NestApplicationOptions,
+  RouteInfo,
 } from '@nestjs/common/interfaces';
 import {
   CorsOptions,
@@ -29,6 +31,7 @@ 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';
@@ -38,9 +41,10 @@ import { Injector } from './injector/injector';
 import { GraphInspector } from './inspector/graph-inspector';
 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';
 
 const { SocketModule } = optionalRequire(
@@ -85,8 +89,9 @@ export class NestApplication
 
     this.selectContextModule();
     this.registerHttpServer();
+
     this.injector = new Injector({ preview: this.appOptions.preview });
-    this.middlewareModule = new MiddlewareModule();
+    this.middlewareModule = new MiddlewareModule(new RoutePathFactory(config));
     this.routesResolver = new RoutesResolver(
       this.container,
       this.config,
@@ -367,9 +372,22 @@ export class NestApplication
   public setGlobalPrefix(prefix: string, options?: GlobalPrefixOptions): this {
     this.config.setGlobalPrefix(prefix);
     if (options) {
-      const exclude = options?.exclude
-        ? mapToExcludeRoute(options.exclude)
-        : [];
+      const exclude = options?.exclude.map(
+        (route: string | RouteInfo): ExcludeRouteMetadata => {
+          if (isString(route)) {
+            return {
+              requestMethod: RequestMethod.ALL,
+              pathRegex: pathToRegexp(addLeadingSlash(route)),
+              path: route,
+            };
+          }
+          return {
+            requestMethod: route.method,
+            pathRegex: pathToRegexp(addLeadingSlash(route.path)),
+            path: route.path,
+          };
+        },
+      );
       this.config.setGlobalPrefixOptions({
         ...options,
         exclude,
diff --git a/packages/core/package.json b/packages/core/package.json
index 0eedee890..f547d4a8e 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@nestjs/core",
-  "version": "9.3.2",
+  "version": "9.3.1",
   "description": "Nest - modern, fast, powerful node.js web framework (@core)",
   "author": "Kamil Mysliwiec",
   "license": "MIT",
@@ -36,7 +36,7 @@
     "uuid": "9.0.0"
   },
   "devDependencies": {
-    "@nestjs/common": "9.3.2"
+    "@nestjs/common": "9.3.1"
   },
   "peerDependencies": {
     "@nestjs/common": "^9.0.0",
diff --git a/packages/core/router/interfaces/exclude-route-metadata.interface.ts b/packages/core/router/interfaces/exclude-route-metadata.interface.ts
index b7f93b600..dfa143041 100644
--- a/packages/core/router/interfaces/exclude-route-metadata.interface.ts
+++ b/packages/core/router/interfaces/exclude-route-metadata.interface.ts
@@ -1,11 +1,7 @@
 import { RequestMethod } from '@nestjs/common';
 
 export interface ExcludeRouteMetadata {
-  /**
-   * Route path.
-   */
   path: string;
-
   /**
    * Regular expression representing the route path.
    */
diff --git a/packages/core/router/router-explorer.ts b/packages/core/router/router-explorer.ts
index 843ca5d2d..bddc4ae94 100644
--- a/packages/core/router/router-explorer.ts
+++ b/packages/core/router/router-explorer.ts
@@ -355,16 +355,13 @@ export class RouterExplorer {
   ) {
     const { instance } = instanceWrapper;
     const collection = moduleRef.controllers;
-
-    const isTreeDurable = instanceWrapper.isDependencyTreeDurable();
-
     return async <TRequest extends Record<any, any>, TResponse>(
       req: TRequest,
       res: TResponse,
       next: () => void,
     ) => {
       try {
-        const contextId = this.getContextId(req, isTreeDurable);
+        const contextId = this.getContextId(req);
         const contextInstance = await this.injector.loadPerContext(
           instance,
           moduleRef,
@@ -400,7 +397,6 @@ export class RouterExplorer {
 
   private getContextId<T extends Record<any, unknown> = any>(
     request: T,
-    isTreeDurable: boolean,
   ): ContextId {
     const contextId = ContextIdFactory.getByRequest(request);
     if (!request[REQUEST_CONTEXT_ID as any]) {
@@ -410,9 +406,10 @@ export class RouterExplorer {
         writable: false,
         configurable: false,
       });
-
-      const requestProviderValue = isTreeDurable ? contextId.payload : request;
-      this.container.registerRequestProvider(requestProviderValue, contextId);
+      this.container.registerRequestProvider(
+        contextId.getParent ? contextId.payload : request,
+        contextId,
+      );
     }
     return contextId;
   }
diff --git a/packages/core/router/utils/exclude-route.util.ts b/packages/core/router/utils/exclude-route.util.ts
index 8670f18f4..798260bf2 100644
--- a/packages/core/router/utils/exclude-route.util.ts
+++ b/packages/core/router/utils/exclude-route.util.ts
@@ -1,5 +1,4 @@
 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) => {
@@ -16,7 +15,7 @@ export function isRouteExcluded(
       isRequestMethodAll(route.requestMethod) ||
       route.requestMethod === requestMethod
     ) {
-      return route.pathRegex.exec(addLeadingSlash(path));
+      return route.pathRegex.exec(path);
     }
     return false;
   });
diff --git a/packages/microservices/client/client-kafka.ts b/packages/microservices/client/client-kafka.ts
index 2932f1b13..ba9ad099a 100644
--- a/packages/microservices/client/client-kafka.ts
+++ b/packages/microservices/client/client-kafka.ts
@@ -42,13 +42,13 @@ let kafkaPackage: any = {};
 
 export class ClientKafka extends ClientProxy {
   protected logger = new Logger(ClientKafka.name);
-  protected client: Kafka | null = null;
-  protected consumer: Consumer | null = null;
-  protected producer: Producer | null = null;
-  protected parser: KafkaParser | null = null;
-  protected initialized: Promise<void> | null = null;
+  protected client: Kafka = null;
+  protected consumer: Consumer = null;
+  protected producer: Producer = null;
+  protected parser: KafkaParser = null;
   protected responsePatterns: string[] = [];
   protected consumerAssignments: { [key: string]: number } = {};
+
   protected brokers: string[] | BrokersFunction;
   protected clientId: string;
   protected groupId: string;
@@ -94,56 +94,46 @@ export class ClientKafka extends ClientProxy {
     this.consumer && (await this.consumer.disconnect());
     this.producer = null;
     this.consumer = null;
-    this.initialized = null;
     this.client = null;
   }
 
   public async connect(): Promise<Producer> {
-    if (this.initialized) {
-      return this.initialized.then(() => this.producer);
+    if (this.client) {
+      return this.producer;
     }
-    this.initialized = new Promise(async (resolve, reject) => {
-      try {
-        this.client = this.createClient();
-
-        if (!this.producerOnlyMode) {
-          const partitionAssigners = [
-            (
-              config: ConstructorParameters<
-                typeof KafkaReplyPartitionAssigner
-              >[1],
-            ) => new KafkaReplyPartitionAssigner(this, config),
-          ];
-
-          const consumerOptions = Object.assign(
-            {
-              partitionAssigners,
-            },
-            this.options.consumer || {},
-            {
-              groupId: this.groupId,
-            },
-          );
+    this.client = this.createClient();
+
+    if (!this.producerOnlyMode) {
+      const partitionAssigners = [
+        (
+          config: ConstructorParameters<typeof KafkaReplyPartitionAssigner>[1],
+        ) => new KafkaReplyPartitionAssigner(this, config),
+      ] as any[];
+
+      const consumerOptions = Object.assign(
+        {
+          partitionAssigners,
+        },
+        this.options.consumer || {},
+        {
+          groupId: this.groupId,
+        },
+      );
 
-          this.consumer = this.client.consumer(consumerOptions);
-          // set member assignments on join and rebalance
-          this.consumer.on(
-            this.consumer.events.GROUP_JOIN,
-            this.setConsumerAssignments.bind(this),
-          );
-          await this.consumer.connect();
-          await this.bindTopics();
-        }
+      this.consumer = this.client.consumer(consumerOptions);
+      // set member assignments on join and rebalance
+      this.consumer.on(
+        this.consumer.events.GROUP_JOIN,
+        this.setConsumerAssignments.bind(this),
+      );
+      await this.consumer.connect();
+      await this.bindTopics();
+    }
 
-        this.producer = this.client.producer(this.options.producer || {});
-        await this.producer.connect();
+    this.producer = this.client.producer(this.options.producer || {});
+    await this.producer.connect();
 
-        resolve();
-      } catch (err) {
-        reject(err);
-      }
-    });
-    return this.initialized.then(() => this.producer);
+    return this.producer;
   }
 
   public async bindTopics(): Promise<void> {
diff --git a/packages/microservices/index.ts b/packages/microservices/index.ts
index bf44f34f7..886c0be72 100644
--- a/packages/microservices/index.ts
+++ b/packages/microservices/index.ts
@@ -1,6 +1,6 @@
 /*
  * Nest @microservices
- * Copyright(c) 2017 - 2023 Kamil Mysliwiec
+ * Copyright(c) 2017 - 2022 Kamil Mysliwiec
  * https://nestjs.com
  * MIT Licensed
  */
diff --git a/packages/microservices/listeners-controller.ts b/packages/microservices/listeners-controller.ts
index 83fd1d941..6fa85d93a 100644
--- a/packages/microservices/listeners-controller.ts
+++ b/packages/microservices/listeners-controller.ts
@@ -14,15 +14,7 @@ import { Module } from '@nestjs/core/injector/module';
 import { GraphInspector } from '@nestjs/core/inspector/graph-inspector';
 import { MetadataScanner } from '@nestjs/core/metadata-scanner';
 import { REQUEST_CONTEXT_ID } from '@nestjs/core/router/request/request-constants';
-import {
-  forkJoin,
-  from as fromPromise,
-  isObservable,
-  mergeMap,
-  Observable,
-  ObservedValueOf,
-  of,
-} from 'rxjs';
+import { connectable, Observable, Subject } from 'rxjs';
 import { IClientProxyFactory } from './client/client-proxy-factory';
 import { ClientsContainer } from './container';
 import { ExceptionFiltersContext } from './context/exception-filters-context';
@@ -119,18 +111,20 @@ export class ListenersController {
             defaultCallMetadata,
           );
           if (isEventHandler) {
-            const eventHandler: MessageHandler = async (...args: unknown[]) => {
+            const eventHandler: MessageHandler = (...args: unknown[]) => {
               const originalArgs = args;
               const [dataOrContextHost] = originalArgs;
               if (dataOrContextHost instanceof RequestContextHost) {
                 args = args.slice(1, args.length);
               }
-              const returnValue = proxy(...args);
-              return this.forkJoinHandlersIfAttached(
-                returnValue,
-                originalArgs,
-                eventHandler,
+              const originalReturnValue = proxy(...args);
+              const returnedValueWrapper = eventHandler.next?.(
+                ...(originalArgs as Parameters<MessageHandler>),
+              );
+              returnedValueWrapper?.then(returnedValue =>
+                this.connectIfStream(returnedValue as Observable<unknown>),
               );
+              return originalReturnValue;
             };
             return server.addHandler(
               pattern,
@@ -149,7 +143,6 @@ export class ListenersController {
           moduleKey,
           methodKey,
           defaultCallMetadata,
-          isEventHandler,
         );
         server.addHandler(pattern, asyncHandler, isEventHandler, extras);
       });
@@ -181,23 +174,6 @@ export class ListenersController {
     );
   }
 
-  public forkJoinHandlersIfAttached(
-    currentReturnValue: Promise<unknown> | Observable<unknown>,
-    originalArgs: unknown[],
-    handlerRef: MessageHandler,
-  ) {
-    if (handlerRef.next) {
-      const returnedValueWrapper = handlerRef.next(
-        ...(originalArgs as Parameters<MessageHandler>),
-      );
-      return forkJoin({
-        current: this.transformToObservable(currentReturnValue),
-        next: this.transformToObservable(returnedValueWrapper),
-      });
-    }
-    return currentReturnValue;
-  }
-
   public assignClientsToProperties(instance: Controller | Injectable) {
     for (const {
       property,
@@ -225,20 +201,17 @@ export class ListenersController {
     moduleKey: string,
     methodKey: string,
     defaultCallMetadata: Record<string, any> = DEFAULT_CALLBACK_METADATA,
-    isEventHandler = false,
   ) {
     const collection = moduleRef.controllers;
     const { instance } = wrapper;
 
-    const isTreeDurable = wrapper.isDependencyTreeDurable();
-
     const requestScopedHandler: MessageHandler = async (...args: unknown[]) => {
       try {
         let contextId: ContextId;
 
         let [dataOrContextHost] = args;
         if (dataOrContextHost instanceof RequestContextHost) {
-          contextId = this.getContextId(dataOrContextHost, isTreeDurable);
+          contextId = this.getContextId(dataOrContextHost);
           args.shift();
         } else {
           const [data, reqCtx] = args;
@@ -247,10 +220,13 @@ export class ListenersController {
             data,
             reqCtx as BaseRpcContext,
           );
-          contextId = this.getContextId(request, isTreeDurable);
+          contextId = this.getContextId(request);
+          this.container.registerRequestProvider(
+            contextId.getParent ? contextId.payload : request,
+            contextId,
+          );
           dataOrContextHost = request;
         }
-
         const contextInstance = await this.injector.loadPerContext(
           instance,
           moduleRef,
@@ -266,16 +242,14 @@ export class ListenersController {
           wrapper.id,
           defaultCallMetadata,
         );
-
-        const returnValue = proxy(...args);
-        if (isEventHandler) {
-          return this.forkJoinHandlersIfAttached(
-            returnValue,
-            [dataOrContextHost, ...args],
-            requestScopedHandler,
-          );
-        }
-        return returnValue;
+        const returnedValueWrapper = requestScopedHandler.next?.(
+          dataOrContextHost,
+          ...args,
+        );
+        returnedValueWrapper?.then(returnedValue =>
+          this.connectIfStream(returnedValue as Observable<unknown>),
+        );
+        return proxy(...args);
       } catch (err) {
         let exceptionFilter = this.exceptionFiltersCache.get(
           instance[methodKey],
@@ -296,10 +270,7 @@ export class ListenersController {
     return requestScopedHandler;
   }
 
-  private getContextId<T extends RequestContext = any>(
-    request: T,
-    isTreeDurable: boolean,
-  ): ContextId {
+  private getContextId<T extends RequestContext = any>(request: T): ContextId {
     const contextId = ContextIdFactory.getByRequest(request);
     if (!request[REQUEST_CONTEXT_ID as any]) {
       Object.defineProperty(request, REQUEST_CONTEXT_ID, {
@@ -308,32 +279,22 @@ export class ListenersController {
         writable: false,
         configurable: false,
       });
-
-      const requestProviderValue = isTreeDurable ? contextId.payload : request;
-      this.container.registerRequestProvider(requestProviderValue, contextId);
+      this.container.registerRequestProvider(
+        contextId.getParent ? contextId.payload : request,
+        contextId,
+      );
     }
     return contextId;
   }
 
-  public transformToObservable<T>(
-    resultOrDeferred: Observable<T> | Promise<T>,
-  ): Observable<T>;
-  public transformToObservable<T>(
-    resultOrDeferred: T,
-  ): never extends Observable<ObservedValueOf<T>>
-    ? Observable<T>
-    : Observable<ObservedValueOf<T>>;
-  public transformToObservable(resultOrDeferred: any) {
-    if (resultOrDeferred instanceof Promise) {
-      return fromPromise(resultOrDeferred).pipe(
-        mergeMap(val => (isObservable(val) ? val : of(val))),
-      );
+  private connectIfStream(source: Observable<unknown>) {
+    if (!source) {
+      return;
     }
-
-    if (isObservable(resultOrDeferred)) {
-      return resultOrDeferred;
-    }
-
-    return of(resultOrDeferred);
+    const connectableSource = connectable(source, {
+      connector: () => new Subject(),
+      resetOnDisconnect: false,
+    });
+    connectableSource.connect();
   }
 }
diff --git a/packages/microservices/microservices-module.ts b/packages/microservices/microservices-module.ts
index 3dbda4464..b5ab826dc 100644
--- a/packages/microservices/microservices-module.ts
+++ b/packages/microservices/microservices-module.ts
@@ -79,7 +79,7 @@ export class MicroservicesModule<
     if (!this.listenersController) {
       throw new RuntimeException();
     }
-    if (this.appOptions?.preview) {
+    if (this.appOptions.preview) {
       return;
     }
     const modules = container.getModules();
diff --git a/packages/microservices/package.json b/packages/microservices/package.json
index 9f1ae97a5..d6694ec6b 100644
--- a/packages/microservices/package.json
+++ b/packages/microservices/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@nestjs/microservices",
-  "version": "9.3.2",
+  "version": "9.3.1",
   "description": "Nest - modern, fast, powerful node.js web framework (@microservices)",
   "author": "Kamil Mysliwiec",
   "license": "MIT",
@@ -21,8 +21,8 @@
     "tslib": "2.5.0"
   },
   "devDependencies": {
-    "@nestjs/common": "9.3.2",
-    "@nestjs/core": "9.3.2"
+    "@nestjs/common": "9.3.1",
+    "@nestjs/core": "9.3.1"
   },
   "peerDependencies": {
     "@grpc/grpc-js": "*",
diff --git a/packages/microservices/server/server-kafka.ts b/packages/microservices/server/server-kafka.ts
index 292cbb384..8bd6a7cfb 100644
--- a/packages/microservices/server/server-kafka.ts
+++ b/packages/microservices/server/server-kafka.ts
@@ -191,7 +191,7 @@ export class ServerKafka extends Server implements CustomTransportStrategy {
     }
 
     const response$ = this.transformToObservable(
-      handler(packet.data, kafkaContext),
+      await handler(packet.data, kafkaContext),
     );
 
     const replayStream$ = new ReplaySubject();
@@ -219,7 +219,7 @@ export class ServerKafka extends Server implements CustomTransportStrategy {
             isPromiseResolved = true;
             reject(err);
           } else {
-            resolve();
+            resolve()
           }
           replayStream$.error(err);
         },
diff --git a/packages/microservices/server/server.ts b/packages/microservices/server/server.ts
index 8a88a1296..4e8ee9bf6 100644
--- a/packages/microservices/server/server.ts
+++ b/packages/microservices/server/server.ts
@@ -11,7 +11,7 @@ import {
   Subject,
   Subscription,
 } from 'rxjs';
-import { catchError, finalize, mergeMap } from 'rxjs/operators';
+import { catchError, finalize } from 'rxjs/operators';
 import { NO_EVENT_HANDLER } from '../constants';
 import { BaseRpcContext } from '../ctx-host/base-rpc.context';
 import { IncomingRequestDeserializer } from '../deserializers/incoming-request.deserializer';
@@ -133,9 +133,7 @@ export abstract class Server {
     : Observable<ObservedValueOf<T>>;
   public transformToObservable(resultOrDeferred: any) {
     if (resultOrDeferred instanceof Promise) {
-      return fromPromise(resultOrDeferred).pipe(
-        mergeMap(val => (isObservable(val) ? val : of(val))),
-      );
+      return fromPromise(resultOrDeferred);
     }
 
     if (isObservable(resultOrDeferred)) {
diff --git a/packages/platform-express/adapters/express-adapter.ts b/packages/platform-express/adapters/express-adapter.ts
index d9b7bff0d..0771b647d 100644
--- a/packages/platform-express/adapters/express-adapter.ts
+++ b/packages/platform-express/adapters/express-adapter.ts
@@ -49,9 +49,6 @@ type VersionedRoute = <
   next: () => void,
 ) => any;
 
-/**
- * @publicApi
- */
 export class ExpressAdapter extends AbstractHttpAdapter {
   private readonly routerMethodFactory = new RouterMethodFactory();
   private readonly logger = new Logger(ExpressAdapter.name);
diff --git a/packages/platform-express/index.ts b/packages/platform-express/index.ts
index ce3dbc432..0ed4c2d76 100644
--- a/packages/platform-express/index.ts
+++ b/packages/platform-express/index.ts
@@ -1,6 +1,6 @@
 /*
  * Nest @platform-express
- * Copyright(c) 2017 - 2023 Kamil Mysliwiec
+ * Copyright(c) 2017 - 2022 Kamil Mysliwiec
  * https://nestjs.com
  * MIT Licensed
  */
diff --git a/packages/platform-express/package.json b/packages/platform-express/package.json
index d2e1e5b5a..388559848 100644
--- a/packages/platform-express/package.json
+++ b/packages/platform-express/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@nestjs/platform-express",
-  "version": "9.3.2",
+  "version": "9.3.1",
   "description": "Nest - modern, fast, powerful node.js web framework (@platform-express)",
   "author": "Kamil Mysliwiec",
   "license": "MIT",
@@ -24,8 +24,8 @@
     "tslib": "2.5.0"
   },
   "devDependencies": {
-    "@nestjs/common": "9.3.2",
-    "@nestjs/core": "9.3.2"
+    "@nestjs/common": "9.3.1",
+    "@nestjs/core": "9.3.1"
   },
   "peerDependencies": {
     "@nestjs/common": "^9.0.0",
diff --git a/packages/platform-fastify/adapters/fastify-adapter.ts b/packages/platform-fastify/adapters/fastify-adapter.ts
index 06aa48d7e..7c3d2a969 100644
--- a/packages/platform-fastify/adapters/fastify-adapter.ts
+++ b/packages/platform-fastify/adapters/fastify-adapter.ts
@@ -93,9 +93,6 @@ type VersionedRoute<TRequest, TResponse> = ((
 type FastifyRawRequest<TServer extends RawServerBase> =
   RawRequestDefaultExpression<TServer> & { originalUrl?: string };
 
-/**
- * @publicApi
- */
 export class FastifyAdapter<
   TServer extends RawServerBase = RawServerDefault,
   TRawRequest extends FastifyRawRequest<TServer> = FastifyRawRequest<TServer>,
diff --git a/packages/platform-fastify/index.ts b/packages/platform-fastify/index.ts
index 6d28e2ccd..2918a05af 100644
--- a/packages/platform-fastify/index.ts
+++ b/packages/platform-fastify/index.ts
@@ -1,6 +1,6 @@
 /*
  * Nest @platform-fastify
- * Copyright(c) 2017 - 2023 Kamil Mysliwiec
+ * Copyright(c) 2017 - 2022 Kamil Mysliwiec
  * https://nestjs.com
  * MIT Licensed
  */
diff --git a/packages/platform-fastify/interfaces/external/fastify-static-options.interface.ts b/packages/platform-fastify/interfaces/external/fastify-static-options.interface.ts
index 8bd294c0f..c8f155f51 100644
--- a/packages/platform-fastify/interfaces/external/fastify-static-options.interface.ts
+++ b/packages/platform-fastify/interfaces/external/fastify-static-options.interface.ts
@@ -1,7 +1,6 @@
 /**
  * "fastify-static" interfaces
  * @see https://github.com/fastify/fastify-static/blob/master/types/index.d.ts
- * @publicApi
  */
 import { Stats } from 'fs';
 
diff --git a/packages/platform-fastify/interfaces/external/fastify-view-options.interface.ts b/packages/platform-fastify/interfaces/external/fastify-view-options.interface.ts
index c6774c65d..6de84627f 100644
--- a/packages/platform-fastify/interfaces/external/fastify-view-options.interface.ts
+++ b/packages/platform-fastify/interfaces/external/fastify-view-options.interface.ts
@@ -1,7 +1,6 @@
 /**
  * "fastify/view" interfaces
  * @see https://github.com/fastify/point-of-view/blob/master/types/index.d.ts
- * @publicApi
  */
 export interface FastifyViewOptions {
   engine: {
diff --git a/packages/platform-fastify/interfaces/nest-fastify-application.interface.ts b/packages/platform-fastify/interfaces/nest-fastify-application.interface.ts
index 2214f30af..936167bb4 100644
--- a/packages/platform-fastify/interfaces/nest-fastify-application.interface.ts
+++ b/packages/platform-fastify/interfaces/nest-fastify-application.interface.ts
@@ -16,9 +16,6 @@ import {
 import { FastifyStaticOptions, FastifyViewOptions } from './external';
 import { NestFastifyBodyParserOptions } from './nest-fastify-body-parser-options.interface';
 
-/**
- * @publicApi
- */
 export interface NestFastifyApplication extends INestApplication {
   /**
    * A wrapper function around native `fastify.register()` method.
diff --git a/packages/platform-fastify/package.json b/packages/platform-fastify/package.json
index 70d1b00fe..0947a8248 100644
--- a/packages/platform-fastify/package.json
+++ b/packages/platform-fastify/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@nestjs/platform-fastify",
-  "version": "9.3.2",
+  "version": "9.3.1",
   "description": "Nest - modern, fast, powerful node.js web framework (@platform-fastify)",
   "author": "Kamil Mysliwiec",
   "license": "MIT",
diff --git a/packages/platform-socket.io/adapters/io-adapter.ts b/packages/platform-socket.io/adapters/io-adapter.ts
index d3c8d161d..22eb9155c 100644
--- a/packages/platform-socket.io/adapters/io-adapter.ts
+++ b/packages/platform-socket.io/adapters/io-adapter.ts
@@ -8,9 +8,6 @@ import { fromEvent, Observable } from 'rxjs';
 import { filter, first, map, mergeMap, share, takeUntil } from 'rxjs/operators';
 import { Server, ServerOptions, Socket } from 'socket.io';
 
-/**
- * @publicApi
- */
 export class IoAdapter extends AbstractWsAdapter {
   public create(
     port: number,
diff --git a/packages/platform-socket.io/index.ts b/packages/platform-socket.io/index.ts
index 434d79eb4..2805fc831 100644
--- a/packages/platform-socket.io/index.ts
+++ b/packages/platform-socket.io/index.ts
@@ -1,6 +1,6 @@
 /*
  * Nest @platform-socket.io
- * Copyright(c) 2017 - 2023 Kamil Mysliwiec
+ * Copyright(c) 2017 - 2022 Kamil Mysliwiec
  * https://nestjs.com
  * MIT Licensed
  */
diff --git a/packages/platform-socket.io/package.json b/packages/platform-socket.io/package.json
index cf1df7a46..0fd0bc605 100644
--- a/packages/platform-socket.io/package.json
+++ b/packages/platform-socket.io/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@nestjs/platform-socket.io",
-  "version": "9.3.2",
+  "version": "9.3.1",
   "description": "Nest - modern, fast, powerful node.js web framework (@platform-socket.io)",
   "author": "Kamil Mysliwiec",
   "license": "MIT",
diff --git a/packages/platform-ws/adapters/ws-adapter.ts b/packages/platform-ws/adapters/ws-adapter.ts
index bc67b82f8..973bce7b9 100644
--- a/packages/platform-ws/adapters/ws-adapter.ts
+++ b/packages/platform-ws/adapters/ws-adapter.ts
@@ -27,9 +27,6 @@ type WsServerRegistryEntry = any[];
 
 const UNDERLYING_HTTP_SERVER_PORT = 0;
 
-/**
- * @publicApi
- */
 export class WsAdapter extends AbstractWsAdapter {
   protected readonly logger = new Logger(WsAdapter.name);
   protected readonly httpServersRegistry = new Map<
diff --git a/packages/platform-ws/index.ts b/packages/platform-ws/index.ts
index e83223e11..0fb20dd10 100644
--- a/packages/platform-ws/index.ts
+++ b/packages/platform-ws/index.ts
@@ -1,6 +1,6 @@
 /*
  * Nest @platform-ws
- * Copyright(c) 2017 - 2023 Kamil Mysliwiec
+ * Copyright(c) 2017 - 2022 Kamil Mysliwiec
  * https://nestjs.com
  * MIT Licensed
  */
diff --git a/packages/platform-ws/package.json b/packages/platform-ws/package.json
index 1d5c81b2c..5e6f694e8 100644
--- a/packages/platform-ws/package.json
+++ b/packages/platform-ws/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@nestjs/platform-ws",
-  "version": "9.3.2",
+  "version": "9.3.1",
   "description": "Nest - modern, fast, powerful node.js web framework (@platform-ws)",
   "author": "Kamil Mysliwiec",
   "license": "MIT",
diff --git a/packages/websockets/index.ts b/packages/websockets/index.ts
index bccb398b5..e8baa6f07 100644
--- a/packages/websockets/index.ts
+++ b/packages/websockets/index.ts
@@ -1,6 +1,6 @@
 /*
  * Nest @websockets
- * Copyright(c) 2017 - 2023 Kamil Mysliwiec
+ * Copyright(c) 2017 - 2022 Kamil Mysliwiec
  * https://nestjs.com
  * MIT Licensed
  */
diff --git a/packages/websockets/package.json b/packages/websockets/package.json
index 6afa99f34..f510854ed 100644
--- a/packages/websockets/package.json
+++ b/packages/websockets/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@nestjs/websockets",
-  "version": "9.3.2",
+  "version": "9.3.1",
   "description": "Nest - modern, fast, powerful node.js web framework (@websockets)",
   "author": "Kamil Mysliwiec",
   "license": "MIT",
@@ -17,8 +17,8 @@
     "tslib": "2.5.0"
   },
   "devDependencies": {
-    "@nestjs/common": "9.3.2",
-    "@nestjs/core": "9.3.2"
+    "@nestjs/common": "9.3.1",
+    "@nestjs/core": "9.3.1"
   },
   "peerDependencies": {
     "@nestjs/common": "^9.0.0",
diff --git a/renovate.json b/renovate.json
index 26c1d72d6..0bb2d8556 100644
--- a/renovate.json
+++ b/renovate.json
@@ -1,5 +1,5 @@
 {
-  "extends": ["config:base", ":dependencyDashboard"],
+  "extends": ["config:base"],
   "labels": ["dependencies"],
   "packageRules": [
     {


Test patch:
diff --git a/integration/hello-world/e2e/middleware-with-versioning.spec.ts b/integration/hello-world/e2e/middleware-with-versioning.spec.ts
index a16645b68..c8d800a90 100644
--- a/integration/hello-world/e2e/middleware-with-versioning.spec.ts
+++ b/integration/hello-world/e2e/middleware-with-versioning.spec.ts
@@ -77,26 +77,6 @@ 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({
@@ -153,7 +133,6 @@ describe('Middleware', () => {
 
 async function createAppWithVersioning(
   versioningOptions: VersioningOptions,
-  beforeInit?: (app: INestApplication) => Promise<void>,
 ): Promise<INestApplication> {
   const app = (
     await Test.createTestingModule({
@@ -162,9 +141,6 @@ 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 74f8e9ad6..131d2dd03 100644
--- a/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts
+++ b/integration/nest-application/global-prefix/e2e/global-prefix.spec.ts
@@ -119,17 +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/: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/packages/common/test/pipes/validation.pipe.spec.ts b/packages/common/test/pipes/validation.pipe.spec.ts
index d9a97f885..f5b44e867 100644
--- a/packages/common/test/pipes/validation.pipe.spec.ts
+++ b/packages/common/test/pipes/validation.pipe.spec.ts
@@ -384,7 +384,7 @@ describe('ValidationPipe', () => {
       });
       describe('otherwise', () => {
         it('should not reject', async () => {
-          target = new ValidationPipe();
+          target = new ValidationPipe({ forbidUnknownValues: false });
           const testObj = [
             { prop1: 'value1', prop2: 'value2', prop3: 'value3' },
           ];
@@ -447,7 +447,7 @@ describe('ValidationPipe', () => {
       target = new ValidationPipe({ expectedType: TestModel });
       const testObj = { prop1: 'value1', prop2: 'value2' };
 
-      expect(await target.transform(testObj, m)).to.deep.equal(testObj);
+      expect(await target.transform(testObj, m)).to.equal(testObj);
     });
 
     it('should validate against the expected type if presented and metatype is primitive type', async () => {
@@ -460,7 +460,7 @@ describe('ValidationPipe', () => {
       target = new ValidationPipe({ expectedType: TestModel });
       const testObj = { prop1: 'value1', prop2: 'value2' };
 
-      expect(await target.transform(testObj, m)).to.deep.equal(testObj);
+      expect(await target.transform(testObj, m)).to.equal(testObj);
     });
   });
 });
diff --git a/packages/core/test/application-config.spec.ts b/packages/core/test/application-config.spec.ts
index cff91bb11..9bf573bb9 100644
--- a/packages/core/test/application-config.spec.ts
+++ b/packages/core/test/application-config.spec.ts
@@ -24,9 +24,9 @@ describe('ApplicationConfig', () => {
       const options: GlobalPrefixOptions<ExcludeRouteMetadata> = {
         exclude: [
           {
-            path: '/health',
             pathRegex: new RegExp(/health/),
             requestMethod: RequestMethod.GET,
+            path: 'health',
           },
         ],
       };
diff --git a/packages/core/test/injector/instance-wrapper.spec.ts b/packages/core/test/injector/instance-wrapper.spec.ts
index d6ab2c9d4..0ac4a1332 100644
--- a/packages/core/test/injector/instance-wrapper.spec.ts
+++ b/packages/core/test/injector/instance-wrapper.spec.ts
@@ -39,7 +39,68 @@ describe('InstanceWrapper', () => {
         expect(wrapper.isDependencyTreeStatic()).to.be.false;
       });
     });
+    describe('when request scoped durable', () => {
+      it('should return false', () => {
+        const wrapper = new InstanceWrapper({
+          scope: Scope.REQUEST,
+          durable: true,
+        });
+        expect(wrapper.isDependencyTreeStatic()).to.be.false;
+      });
+    });
+    describe('when request scoped explicit non durable', () => {
+      it('should return false', () => {
+        const wrapper = new InstanceWrapper({
+          scope: Scope.REQUEST,
+          durable: false,
+        });
+        expect(wrapper.isDependencyTreeStatic()).to.be.false;
+      });
+    });
+    describe('when default', () => {
+      it('should return true', () => {
+        const wrapper = new InstanceWrapper({});
+        expect(wrapper.isDependencyTreeStatic()).to.be.true;
+      });
+    });
     describe('when statically scoped', () => {
+      describe('dependencies, properties, enhancers', () => {
+        describe('dependecies non static, properties static, enhancers static', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper();
+            wrapper.addCtorMetadata(
+              0,
+              new InstanceWrapper({ scope: Scope.REQUEST }),
+            );
+            wrapper.addPropertiesMetadata('key1', new InstanceWrapper());
+            wrapper.addEnhancerMetadata(new InstanceWrapper());
+            expect(wrapper.isDependencyTreeStatic()).to.be.false;
+          });
+        });
+        describe('dependecies static, properties non static, enhancers static', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper();
+            wrapper.addCtorMetadata(0, new InstanceWrapper());
+            wrapper.addPropertiesMetadata(
+              'key1',
+              new InstanceWrapper({ scope: Scope.REQUEST }),
+            );
+            wrapper.addEnhancerMetadata(new InstanceWrapper());
+            expect(wrapper.isDependencyTreeStatic()).to.be.false;
+          });
+        });
+        describe('dependecies static, properties static, enhancers non static', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper();
+            wrapper.addCtorMetadata(0, new InstanceWrapper());
+            wrapper.addPropertiesMetadata('key1', new InstanceWrapper());
+            wrapper.addEnhancerMetadata(
+              new InstanceWrapper({ scope: Scope.REQUEST }),
+            );
+            expect(wrapper.isDependencyTreeStatic()).to.be.false;
+          });
+        });
+      });
       describe('dependencies', () => {
         describe('when each is static', () => {
           it('should return true', () => {
@@ -116,8 +177,157 @@ describe('InstanceWrapper', () => {
         expect(wrapper.isDependencyTreeDurable()).to.be.true;
       });
     });
+    describe('when request scoped and non durable', () => {
+      it('should return false', () => {
+        const wrapper = new InstanceWrapper({
+          scope: Scope.REQUEST,
+        });
+        expect(wrapper.isDependencyTreeDurable()).to.be.false;
+      });
+    });
+    describe('when request scoped and explicit non durable', () => {
+      it('should return false', () => {
+        const wrapper = new InstanceWrapper({
+          scope: Scope.REQUEST,
+          durable: false,
+        });
+        expect(wrapper.isDependencyTreeDurable()).to.be.false;
+      });
+    });
+    describe('when default scope', () => {
+      it('should return false', () => {
+        const wrapper = new InstanceWrapper();
+        expect(wrapper.isDependencyTreeDurable()).to.be.false;
+      });
+    });
     describe('when statically scoped', () => {
+      describe('dependencies, properties, enhancers', () => {
+        describe('dependecies non durable, properties non durable, enhancers durable', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper();
+            wrapper.addCtorMetadata(
+              0,
+              new InstanceWrapper({ scope: Scope.REQUEST }),
+            );
+            wrapper.addCtorMetadata(1, new InstanceWrapper());
+            wrapper.addPropertiesMetadata('key1', new InstanceWrapper());
+            wrapper.addEnhancerMetadata(new InstanceWrapper());
+            expect(wrapper.isDependencyTreeDurable()).to.be.false;
+          });
+        });
+        describe('dependecies non durable, properties durable, enhancers durable', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper();
+            wrapper.addCtorMetadata(
+              0,
+              new InstanceWrapper({ scope: Scope.REQUEST }),
+            );
+            wrapper.addCtorMetadata(1, new InstanceWrapper());
+            wrapper.addPropertiesMetadata(
+              'key1',
+              new InstanceWrapper({ scope: Scope.REQUEST }),
+            );
+            wrapper.addEnhancerMetadata(new InstanceWrapper());
+            expect(wrapper.isDependencyTreeDurable()).to.be.false;
+          });
+        });
+        describe('dependecies non durable, properties durable', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper();
+            wrapper.addCtorMetadata(
+              0,
+              new InstanceWrapper({ scope: Scope.REQUEST }),
+            );
+            wrapper.addCtorMetadata(1, new InstanceWrapper());
+            wrapper.addPropertiesMetadata('key1', new InstanceWrapper());
+            wrapper.addPropertiesMetadata(
+              'key2',
+              new InstanceWrapper({ scope: Scope.REQUEST, durable: true }),
+            );
+            expect(wrapper.isDependencyTreeDurable()).to.be.false;
+          });
+        });
+        describe('properties durable, enhancers non durable', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper();
+            wrapper.addPropertiesMetadata('key1', new InstanceWrapper());
+            wrapper.addPropertiesMetadata(
+              'key2',
+              new InstanceWrapper({ scope: Scope.REQUEST, durable: true }),
+            );
+            wrapper.addEnhancerMetadata(
+              new InstanceWrapper({ scope: Scope.REQUEST }),
+            );
+            expect(wrapper.isDependencyTreeDurable()).to.be.false;
+          });
+        });
+        describe('dependencies durable, enhancers non durable', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper();
+            wrapper.addCtorMetadata(
+              0,
+              new InstanceWrapper({ scope: Scope.REQUEST, durable: true }),
+            );
+            wrapper.addEnhancerMetadata(
+              new InstanceWrapper({ scope: Scope.REQUEST }),
+            );
+            expect(wrapper.isDependencyTreeDurable()).to.be.false;
+          });
+        });
+      });
       describe('dependencies', () => {
+        describe('when wrapper is non durable and dependecy is static', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper({ scope: Scope.REQUEST });
+            wrapper.addCtorMetadata(0, new InstanceWrapper());
+            expect(wrapper.isDependencyTreeDurable()).to.be.false;
+          });
+        });
+        describe('when wrapper is durable and dependecy is static', () => {
+          it('should return true', () => {
+            const wrapper = new InstanceWrapper({
+              scope: Scope.REQUEST,
+              durable: true,
+            });
+            wrapper.addCtorMetadata(0, new InstanceWrapper());
+            expect(wrapper.isDependencyTreeDurable()).to.be.true;
+          });
+        });
+        describe('when wrapper is non durable and dependecy is durable', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper({
+              scope: Scope.REQUEST,
+            });
+            wrapper.addCtorMetadata(
+              0,
+              new InstanceWrapper({ scope: Scope.REQUEST, durable: true }),
+            );
+            expect(wrapper.isDependencyTreeDurable()).to.be.false;
+          });
+        });
+        describe('when wrapper is durable and dependecy is static', () => {
+          it('should return true', () => {
+            const wrapper = new InstanceWrapper({
+              scope: Scope.REQUEST,
+              durable: true,
+            });
+            wrapper.addCtorMetadata(0, new InstanceWrapper());
+            expect(wrapper.isDependencyTreeDurable()).to.be.true;
+          });
+        });
+        describe('when wrapper is durable and dependecy is non durable', () => {
+          it('should return true', () => {
+            const wrapper = new InstanceWrapper({
+              scope: Scope.REQUEST,
+              durable: true,
+            });
+            wrapper.addCtorMetadata(
+              0,
+              new InstanceWrapper({ scope: Scope.REQUEST }),
+            );
+            expect(wrapper.isDependencyTreeDurable()).to.be.true;
+          });
+        });
         describe('when each is static', () => {
           it('should return false', () => {
             const wrapper = new InstanceWrapper();
@@ -174,6 +384,58 @@ describe('InstanceWrapper', () => {
         });
       });
       describe('properties', () => {
+        describe('when wrapper is non durable and dependecy is static', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper({ scope: Scope.REQUEST });
+            wrapper.addPropertiesMetadata('key1', new InstanceWrapper());
+            expect(wrapper.isDependencyTreeDurable()).to.be.false;
+          });
+        });
+        describe('when wrapper is durable and dependecy is static', () => {
+          it('should return true', () => {
+            const wrapper = new InstanceWrapper({
+              scope: Scope.REQUEST,
+              durable: true,
+            });
+            wrapper.addPropertiesMetadata('key1', new InstanceWrapper());
+            expect(wrapper.isDependencyTreeDurable()).to.be.true;
+          });
+        });
+        describe('when wrapper is non durable and dependecy is durable', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper({
+              scope: Scope.REQUEST,
+            });
+            wrapper.addPropertiesMetadata(
+              'key1',
+              new InstanceWrapper({ scope: Scope.REQUEST, durable: true }),
+            );
+            expect(wrapper.isDependencyTreeDurable()).to.be.false;
+          });
+        });
+        describe('when wrapper is durable and dependecy is static', () => {
+          it('should return true', () => {
+            const wrapper = new InstanceWrapper({
+              scope: Scope.REQUEST,
+              durable: true,
+            });
+            wrapper.addPropertiesMetadata('key1', new InstanceWrapper());
+            expect(wrapper.isDependencyTreeDurable()).to.be.true;
+          });
+        });
+        describe('when wrapper is durable and dependecy is non durable', () => {
+          it('should return true', () => {
+            const wrapper = new InstanceWrapper({
+              scope: Scope.REQUEST,
+              durable: true,
+            });
+            wrapper.addPropertiesMetadata(
+              'key1',
+              new InstanceWrapper({ scope: Scope.REQUEST }),
+            );
+            expect(wrapper.isDependencyTreeDurable()).to.be.true;
+          });
+        });
         describe('when each is static', () => {
           it('should return false', () => {
             const wrapper = new InstanceWrapper();
@@ -221,6 +483,56 @@ describe('InstanceWrapper', () => {
         });
       });
       describe('enhancers', () => {
+        describe('when wrapper is non durable and dependecy is static', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper({ scope: Scope.REQUEST });
+            wrapper.addEnhancerMetadata(new InstanceWrapper());
+            expect(wrapper.isDependencyTreeDurable()).to.be.false;
+          });
+        });
+        describe('when wrapper is durable and dependecy is static', () => {
+          it('should return true', () => {
+            const wrapper = new InstanceWrapper({
+              scope: Scope.REQUEST,
+              durable: true,
+            });
+            wrapper.addEnhancerMetadata(new InstanceWrapper());
+            expect(wrapper.isDependencyTreeDurable()).to.be.true;
+          });
+        });
+        describe('when wrapper is non durable and dependecy is durable', () => {
+          it('should return false', () => {
+            const wrapper = new InstanceWrapper({
+              scope: Scope.REQUEST,
+            });
+            wrapper.addEnhancerMetadata(
+              new InstanceWrapper({ scope: Scope.REQUEST, durable: true }),
+            );
+            expect(wrapper.isDependencyTreeDurable()).to.be.false;
+          });
+        });
+        describe('when wrapper is durable and dependecy is static', () => {
+          it('should return true', () => {
+            const wrapper = new InstanceWrapper({
+              scope: Scope.REQUEST,
+              durable: true,
+            });
+            wrapper.addEnhancerMetadata(new InstanceWrapper());
+            expect(wrapper.isDependencyTreeDurable()).to.be.true;
+          });
+        });
+        describe('when wrapper is durable and dependecy is non durable', () => {
+          it('should return true', () => {
+            const wrapper = new InstanceWrapper({
+              scope: Scope.REQUEST,
+              durable: true,
+            });
+            wrapper.addEnhancerMetadata(
+              new InstanceWrapper({ scope: Scope.REQUEST }),
+            );
+            expect(wrapper.isDependencyTreeDurable()).to.be.true;
+          });
+        });
         describe('when each is static', () => {
           it('should return false', () => {
             const wrapper = new InstanceWrapper();
diff --git a/packages/core/test/middleware/middleware-module.spec.ts b/packages/core/test/middleware/middleware-module.spec.ts
index 8f113dee1..e30ba206a 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 } from '@nestjs/common';
-import { RouteInfoPathExtractor } from '@nestjs/core/middleware/route-info-path-extractor';
+import { RoutePathFactory } from '@nestjs/core/router/route-path-factory';
 import * as chai from 'chai';
 import { expect } from 'chai';
 import * as chaiAsPromised from 'chai-as-promised';
@@ -47,21 +47,15 @@ describe('MiddlewareModule', () => {
   beforeEach(() => {
     const container = new NestContainer();
     const appConfig = new ApplicationConfig();
+
     graphInspector = new GraphInspector(container);
-    middlewareModule = new MiddlewareModule();
-    middlewareModule['routerExceptionFilter'] = new RouterExceptionFilters(
-      new NestContainer(),
-      appConfig,
-      new NoopHttpAdapter({}),
-    );
-    middlewareModule['routeInfoPathExtractor'] = new RouteInfoPathExtractor(
-      appConfig,
-    );
+    middlewareModule = new MiddlewareModule(new RoutePathFactory(appConfig));
     middlewareModule['routerExceptionFilter'] = new RouterExceptionFilters(
       container,
       appConfig,
       new NoopHttpAdapter({}),
     );
+    middlewareModule['config'] = appConfig;
     middlewareModule['graphInspector'] = graphInspector;
   });
 
diff --git a/packages/core/test/middleware/route-info-path-extractor.spec.ts b/packages/core/test/middleware/route-info-path-extractor.spec.ts
deleted file mode 100644
index 9ff9c82d8..000000000
--- a/packages/core/test/middleware/route-info-path-extractor.spec.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-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.extractPathsFrom({
-          path: '*',
-          method: RequestMethod.ALL,
-        }),
-      ).to.eql(['/*']);
-
-      expect(
-        routeInfoPathExtractor.extractPathsFrom({
-          path: '*',
-          method: RequestMethod.ALL,
-          version: '1',
-        }),
-      ).to.eql(['/v1/*']);
-    });
-
-    it(`should return correct paths when set global prefix`, () => {
-      appConfig.setGlobalPrefix('api');
-
-      expect(
-        routeInfoPathExtractor.extractPathsFrom({
-          path: '*',
-          method: RequestMethod.ALL,
-        }),
-      ).to.eql(['/api/*']);
-
-      expect(
-        routeInfoPathExtractor.extractPathsFrom({
-          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.extractPathsFrom({
-          path: '*',
-          method: RequestMethod.ALL,
-        }),
-      ).to.eql(['/api/*', '/foo']);
-
-      expect(
-        routeInfoPathExtractor.extractPathsFrom({
-          path: '*',
-          method: RequestMethod.ALL,
-          version: '1',
-        }),
-      ).to.eql(['/api/v1/*', '/v1/foo']);
-
-      expect(
-        routeInfoPathExtractor.extractPathsFrom({
-          path: 'foo',
-          method: RequestMethod.ALL,
-          version: '1',
-        }),
-      ).to.eql(['/v1/foo']);
-
-      expect(
-        routeInfoPathExtractor.extractPathsFrom({
-          path: 'bar',
-          method: RequestMethod.ALL,
-          version: '1',
-        }),
-      ).to.eql(['/api/v1/bar']);
-    });
-  });
-});
diff --git a/packages/core/test/middleware/utils.spec.ts b/packages/core/test/middleware/utils.spec.ts
index a1c91d77b..754878c22 100644
--- a/packages/core/test/middleware/utils.spec.ts
+++ b/packages/core/test/middleware/utils.spec.ts
@@ -1,5 +1,4 @@
 import { RequestMethod, Type } from '@nestjs/common';
-import { addLeadingSlash } from '@nestjs/common/utils/shared.utils';
 import { expect } from 'chai';
 import * as sinon from 'sinon';
 import {
@@ -11,7 +10,6 @@ import {
   mapToExcludeRoute,
 } from '../../middleware/utils';
 import { NoopHttpAdapter } from '../utils/noop-adapter.spec';
-import * as pathToRegexp from 'path-to-regexp';
 
 describe('middleware utils', () => {
   const noopAdapter = new NoopHttpAdapter({});
@@ -19,27 +17,6 @@ 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 7ae09fe53..9e9bf348e 100644
--- a/packages/core/test/nest-application.spec.ts
+++ b/packages/core/test/nest-application.spec.ts
@@ -1,10 +1,8 @@
-import { RequestMethod } from '@nestjs/common';
 import { expect } from 'chai';
 import { ApplicationConfig } from '../application-config';
 import { NestContainer } from '../injector/container';
 import { GraphInspector } from '../inspector/graph-inspector';
 import { NestApplication } from '../nest-application';
-import { mapToExcludeRoute } from './../middleware/utils';
 import { NoopHttpAdapter } from './utils/noop-adapter.spec';
 
 describe('NestApplication', () => {
@@ -56,24 +54,4 @@ 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,
-        new GraphInspector(container),
-        {},
-      );
-      const excludeRoute = ['foo', { path: 'bar', method: RequestMethod.GET }];
-      instance.setGlobalPrefix('api', {
-        exclude: excludeRoute,
-      });
-      expect(applicationConfig.getGlobalPrefixOptions()).to.eql({
-        exclude: mapToExcludeRoute(excludeRoute),
-      });
-    });
-  });
 });
diff --git a/packages/core/test/router/route-path-factory.spec.ts b/packages/core/test/router/route-path-factory.spec.ts
index 4c110651d..4bf952295 100644
--- a/packages/core/test/router/route-path-factory.spec.ts
+++ b/packages/core/test/router/route-path-factory.spec.ts
@@ -247,9 +247,9 @@ describe('RoutePathFactory', () => {
           sinon.stub(applicationConfig, 'getGlobalPrefixOptions').returns({
             exclude: [
               {
-                path: '/random',
                 pathRegex: pathToRegexp('/random'),
                 requestMethod: RequestMethod.ALL,
+                path: '/random',
               },
             ],
           });
@@ -266,9 +266,9 @@ describe('RoutePathFactory', () => {
           sinon.stub(applicationConfig, 'getGlobalPrefixOptions').returns({
             exclude: [
               {
-                path: '/cats',
                 pathRegex: pathToRegexp('/cats'),
                 requestMethod: RequestMethod.ALL,
+                path: '/cats',
               },
             ],
           });
@@ -285,9 +285,9 @@ describe('RoutePathFactory', () => {
             sinon.stub(applicationConfig, 'getGlobalPrefixOptions').returns({
               exclude: [
                 {
-                  path: '/cats',
                   pathRegex: pathToRegexp('/cats'),
                   requestMethod: RequestMethod.GET,
+                  path: '/cats',
                 },
               ],
             });
diff --git a/packages/microservices/test/client/client-kafka.spec.ts b/packages/microservices/test/client/client-kafka.spec.ts
index 4bc9e6eca..39743da52 100644
--- a/packages/microservices/test/client/client-kafka.spec.ts
+++ b/packages/microservices/test/client/client-kafka.spec.ts
@@ -11,6 +11,7 @@ import {
 } from '../../external/kafka.interface';
 
 describe('ClientKafka', () => {
+  // static
   const topic = 'test.topic';
   const partition = 0;
   const replyTopic = 'test.topic.reply';
@@ -24,6 +25,7 @@ describe('ClientKafka', () => {
   const heartbeat = async () => {};
   const pause = () => () => {};
 
+  // message
   const message: KafkaMessage = {
     key: Buffer.from(key),
     offset,
@@ -33,6 +35,7 @@ describe('ClientKafka', () => {
     attributes,
   };
 
+  // deserialized message
   const deserializedMessage: any = {
     key,
     offset,
@@ -44,6 +47,7 @@ describe('ClientKafka', () => {
     partition,
   };
 
+  // payloads
   const payload: EachMessagePayload = {
     topic,
     partition,
@@ -148,6 +152,26 @@ describe('ClientKafka', () => {
     pause,
   };
 
+  const deserializedPayloadError: EachMessagePayload = {
+    topic,
+    partition,
+    message: Object.assign(
+      {
+        headers: {
+          [KafkaHeaders.CORRELATION_ID]: correlationId,
+          [KafkaHeaders.NEST_ERR]: NO_MESSAGE_HANDLER,
+        },
+      },
+      deserializedMessage,
+      {
+        size: 0,
+        value: null,
+      },
+    ),
+    heartbeat,
+    pause,
+  };
+
   let client: ClientKafka;
   let callback: sinon.SinonSpy;
   let connect: sinon.SinonSpy;
@@ -158,7 +182,7 @@ describe('ClientKafka', () => {
   let consumerStub: sinon.SinonStub;
   let producerStub: sinon.SinonStub;
   let createClientStub: sinon.SinonStub;
-  let kafkaClient: any;
+  let kafkaClient;
 
   beforeEach(() => {
     client = new ClientKafka({});
@@ -298,8 +322,7 @@ describe('ClientKafka', () => {
       });
 
       it('should expect the connection to be reused', async () => {
-        (client as any).initialized = Promise.resolve({});
-
+        (client as any).client = kafkaClient;
         await client.connect();
 
         expect(createClientStub.calledOnce).to.be.false;
@@ -345,8 +368,7 @@ describe('ClientKafka', () => {
       });
 
       it('should expect the connection to be reused', async () => {
-        (client as any).initialized = Promise.resolve({});
-
+        (client as any).client = kafkaClient;
         await client.connect();
 
         expect(createClientStub.calledOnce).to.be.false;
diff --git a/packages/testing/index.ts b/packages/testing/index.ts
index d760d09f7..0a4a47f73 100644
--- a/packages/testing/index.ts
+++ b/packages/testing/index.ts
@@ -1,6 +1,6 @@
 /*
  * Nest @testing
- * Copyright(c) 2017 - 2023 Kamil Mysliwiec
+ * Copyright(c) 2017 - 2022 Kamil Mysliwiec
  * https://nestjs.com
  * MIT Licensed
  */
diff --git a/packages/testing/package.json b/packages/testing/package.json
index f94b4170e..3fe77048a 100644
--- a/packages/testing/package.json
+++ b/packages/testing/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@nestjs/testing",
-  "version": "9.3.2",
+  "version": "9.3.1",
   "description": "Nest - modern, fast, powerful node.js web framework (@testing)",
   "author": "Kamil Mysliwiec",
   "license": "MIT",