mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
feat(core) exclude middleware based on path
This commit is contained in:
@@ -1,30 +1,91 @@
|
||||
import { Type } from '@nestjs/common/interfaces';
|
||||
import { RequestMethod } from '@nestjs/common';
|
||||
import { HttpServer, RouteInfo, Type } from '@nestjs/common/interfaces';
|
||||
import { isFunction } from '@nestjs/common/utils/shared.utils';
|
||||
import * as pathToRegexp from 'path-to-regexp';
|
||||
import * as uuid from 'uuid/v4';
|
||||
|
||||
export const filterMiddleware = <T>(middleware: T[]) => {
|
||||
type RouteInfoRegex = RouteInfo & { regex: RegExp };
|
||||
|
||||
export const filterMiddleware = <T extends Function | Type<any> = any>(
|
||||
middleware: T[],
|
||||
excludedRoutes: RouteInfo[],
|
||||
httpAdapter: HttpServer,
|
||||
) => {
|
||||
const excluded = excludedRoutes.map(route => ({
|
||||
...route,
|
||||
regex: pathToRegexp(route.path),
|
||||
}));
|
||||
return []
|
||||
.concat(middleware)
|
||||
.filter(isFunction)
|
||||
.map(mapToClass);
|
||||
.map((item: T) => mapToClass(item, excluded, httpAdapter));
|
||||
};
|
||||
|
||||
export const mapToClass = <T extends Function | Type<any>>(middleware: T) => {
|
||||
export const mapToClass = <T extends Function | Type<any>>(
|
||||
middleware: T,
|
||||
excludedRoutes: RouteInfoRegex[],
|
||||
httpAdapter: HttpServer,
|
||||
) => {
|
||||
if (isClass(middleware)) {
|
||||
return middleware;
|
||||
if (excludedRoutes.length <= 0) {
|
||||
return middleware;
|
||||
}
|
||||
const middlewareHost = class extends (middleware as Type<any>) {
|
||||
use(...params: unknown[]) {
|
||||
const [req, _, next] = params as [Record<string, any>, any, Function];
|
||||
const isExcluded = isRouteExcluded(req, excludedRoutes, httpAdapter);
|
||||
if (isExcluded) {
|
||||
return next();
|
||||
}
|
||||
return super.use(...params);
|
||||
}
|
||||
};
|
||||
return assignToken(middlewareHost, middleware.name);
|
||||
}
|
||||
return assignToken(
|
||||
class {
|
||||
use = (...params: any[]) => (middleware as Function)(...params);
|
||||
use = (...params: unknown[]) => {
|
||||
const [req, _, next] = params as [Record<string, any>, any, Function];
|
||||
const isExcluded = isRouteExcluded(req, excludedRoutes, httpAdapter);
|
||||
if (isExcluded) {
|
||||
return next();
|
||||
}
|
||||
return (middleware as Function)(...params);
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export function isClass(middleware: any) {
|
||||
export function isClass(middleware: any): middleware is Type<any> {
|
||||
return middleware.toString().substring(0, 5) === 'class';
|
||||
}
|
||||
|
||||
export function assignToken(metatype: Type<any>): Type<any> {
|
||||
Object.defineProperty(metatype, 'name', { value: uuid() });
|
||||
export function assignToken(metatype: Type<any>, token = uuid()): Type<any> {
|
||||
Object.defineProperty(metatype, 'name', { value: token });
|
||||
return metatype;
|
||||
}
|
||||
|
||||
export function isRouteExcluded(
|
||||
req: Record<string, any>,
|
||||
excludedRoutes: RouteInfoRegex[],
|
||||
httpAdapter: HttpServer,
|
||||
): boolean {
|
||||
if (excludedRoutes.length <= 0) {
|
||||
return false;
|
||||
}
|
||||
const reqMethod = httpAdapter.getRequestMethod(req);
|
||||
const originalUrl = httpAdapter.getRequestUrl(req);
|
||||
const queryParamsIndex = originalUrl && originalUrl.indexOf('?');
|
||||
const pathname =
|
||||
queryParamsIndex >= 0
|
||||
? originalUrl.slice(0, queryParamsIndex)
|
||||
: originalUrl;
|
||||
|
||||
const isExcluded = excludedRoutes.some(({ method, regex }) => {
|
||||
if (RequestMethod[method] === reqMethod) {
|
||||
return regex.exec(pathname);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return isExcluded;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user