Skip to content

Commit

Permalink
fix(core): Improve middleware route exclusion for dynamic endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
sapenlei committed Nov 24, 2024
1 parent 67e30e2 commit 3d65af2
Show file tree
Hide file tree
Showing 6 changed files with 470 additions and 18 deletions.
13 changes: 12 additions & 1 deletion packages/core/middleware/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import {
} from '@nestjs/common/interfaces/middleware';
import { stripEndSlash } from '@nestjs/common/utils/shared.utils';
import { iterate } from 'iterare';
import { isRouteIncluded } from '../router/utils';
import { RouteInfoPathExtractor } from './route-info-path-extractor';
import { RoutesMapper } from './routes-mapper';
import { filterMiddleware } from './utils';
import { filterMiddleware, mapToExcludeRoute } from './utils';

export class MiddlewareBuilder implements MiddlewareConsumer {
private readonly middlewareCollection = new Set<MiddlewareConfiguration>();
Expand Down Expand Up @@ -84,9 +85,19 @@ export class MiddlewareBuilder implements MiddlewareConsumer {

const flattedRoutes = this.getRoutesFlatList(routes);
const forRoutes = this.removeOverlappedRoutes(flattedRoutes);

const includedRoutes = flattedRoutes.filter(route =>
isRouteIncluded(
mapToExcludeRoute(this.excludedRoutes),
route.path,
route.method,
),
);

const configuration = {
middleware: filterMiddleware(
this.middleware,
includedRoutes,
this.excludedRoutes,
this.builder.getHttpAdapter(),
),
Expand Down
33 changes: 25 additions & 8 deletions packages/core/middleware/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import {
import { iterate } from 'iterare';
import * as pathToRegexp from 'path-to-regexp';
import { uid } from 'uid';
import { ExcludeRouteMetadata } from '../router/interfaces/exclude-route-metadata.interface';
import {
ExcludeRouteMetadata,
RouteMetadata,
} from '../router/interfaces/exclude-route-metadata.interface';
import { isRouteExcluded } from '../router/utils';

export const mapToExcludeRoute = (
routes: (string | RouteInfo)[],
): ExcludeRouteMetadata[] => {
Expand All @@ -32,20 +34,28 @@ export const mapToExcludeRoute = (

export const filterMiddleware = <T extends Function | Type<any> = any>(
middleware: T[],
routes: RouteInfo[],
includedRoutes: RouteInfo[],
excludedRoutes: RouteInfo[],
httpAdapter: HttpServer,
) => {
const excludedRoutes = mapToExcludeRoute(routes);
return iterate([])
.concat(middleware)
.filter(isFunction)
.map((item: T) => mapToClass(item, excludedRoutes, httpAdapter))
.map((item: T) =>
mapToClass(
item,
mapToExcludeRoute(includedRoutes),
mapToExcludeRoute(excludedRoutes),
httpAdapter,
),
)
.toArray();
};

export const mapToClass = <T extends Function | Type<any>>(
middleware: T,
excludedRoutes: ExcludeRouteMetadata[],
includedRoutes: RouteMetadata[],
excludedRoutes: RouteMetadata[],
httpAdapter: HttpServer,
) => {
if (isMiddlewareClass(middleware)) {
Expand All @@ -57,6 +67,7 @@ export const mapToClass = <T extends Function | Type<any>>(
const [req, _, next] = params as [Record<string, any>, any, Function];
const isExcluded = isMiddlewareRouteExcluded(
req,
includedRoutes,
excludedRoutes,
httpAdapter,
);
Expand All @@ -74,6 +85,7 @@ export const mapToClass = <T extends Function | Type<any>>(
const [req, _, next] = params as [Record<string, any>, any, Function];
const isExcluded = isMiddlewareRouteExcluded(
req,
includedRoutes,
excludedRoutes,
httpAdapter,
);
Expand Down Expand Up @@ -106,7 +118,8 @@ export function assignToken(metatype: Type<any>, token = uid(21)): Type<any> {

export function isMiddlewareRouteExcluded(
req: Record<string, any>,
excludedRoutes: ExcludeRouteMetadata[],
includedRoutes: RouteMetadata[],
excludedRoutes: RouteMetadata[],
httpAdapter: HttpServer,
): boolean {
if (excludedRoutes.length <= 0) {
Expand All @@ -120,5 +133,9 @@ export function isMiddlewareRouteExcluded(
? originalUrl.slice(0, queryParamsIndex)
: originalUrl;

return isRouteExcluded(excludedRoutes, pathname, RequestMethod[reqMethod]);
if (includedRoutes.length > 0) {
return !isRouteExcluded(includedRoutes, pathname, RequestMethod[reqMethod]);
} else {
return isRouteExcluded(excludedRoutes, pathname, RequestMethod[reqMethod]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ export interface ExcludeRouteMetadata {
*/
requestMethod: RequestMethod;
}

export type RouteMetadata = ExcludeRouteMetadata;
16 changes: 16 additions & 0 deletions packages/core/router/utils/exclude-route.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,19 @@ export function isRouteExcluded(
return false;
});
}

export function isRouteIncluded(
excludedRoutes: ExcludeRouteMetadata[],
path: string,
requestMethod?: RequestMethod,
) {
return excludedRoutes.some(route => {
if (
isRequestMethodAll(route.requestMethod) ||
route.requestMethod === requestMethod
) {
return route.pathRegex.exec(addLeadingSlash(path)) && route.path !== path;
}
return false;
});
}
Loading

0 comments on commit 3d65af2

Please sign in to comment.