fontcolor_theme
Deepkit HTTP

中间件

HTTP 中间件允许你在请求/响应周期中挂钩,作为 HTTP 事件的替代方案。其 API 允许你使用来自 Express/Connect 框架的所有中间件。

中间件可以是一个类(由依赖注入容器实例化),也可以是一个简单函数。

import { HttpMiddleware, httpMiddleware, HttpRequest, HttpResponse } from '@deepkit/http';

class MyMiddleware implements HttpMiddleware {
    async execute(request: HttpRequest, response: HttpResponse, next: (err?: any) => void) {
        response.setHeader('middleware', '1');
        next();
    }
}


function myMiddlewareFunction(request: HttpRequest, response: HttpResponse, next: (err?: any) => void) {
    response.setHeader('middleware', '1');
    next();
}

new App({
    providers: [MyMiddleware],
    middlewares: [
        httpMiddleware.for(MyMiddleware),
        httpMiddleware.for(myMiddlewareFunction),
    ],
    imports: [new FrameworkModule]
}).run();

全局

通过使用 httpMiddleware.for(MyMiddleware),可以将中间件全局注册到所有路由。

import { httpMiddleware } from '@deepkit/http';

new App({
    providers: [MyMiddleware],
    middlewares: [
        httpMiddleware.for(MyMiddleware)
    ],
    imports: [new FrameworkModule]
}).run();

按控制器

可以通过两种方式将中间件限定到一个或多个控制器:使用 @http.controller,或使用 httpMiddleware.for(T).forControllers()excludeControllers 允许你排除某些控制器。

@http.middleware(MyMiddleware)
class MyFirstController {

}
new App({
    providers: [MyMiddleware],
    controllers: [MainController, UsersCommand],
    middlewares: [
        httpMiddleware.for(MyMiddleware).forControllers(MyFirstController, MySecondController)
    ],
    imports: [new FrameworkModule]
}).run();

按路由名称

forRouteNames 及其对应的 excludeRouteNames 允许你按路由名称筛选中间件的执行。

class MyFirstController {
    @http.GET('/hello').name('firstRoute')
    myAction() {
    }

    @http.GET('/second').name('secondRoute')
    myAction2() {
    }
}
new App({
    controllers: [MainController, UsersCommand],
    providers: [MyMiddleware],
    middlewares: [
        httpMiddleware.for(MyMiddleware).forRouteNames('firstRoute', 'secondRoute')
    ],
    imports: [new FrameworkModule]
}).run();

按操作/路由

若只在某个路由上执行中间件,可以使用 @http.GET().middleware(),或使用 httpMiddleware.for(T).forRoute(),其中 forRoute 提供多种选项来筛选路由。

class MyFirstController {
    @http.GET('/hello').middleware(MyMiddleware)
    myAction() {
    }
}
new App({
    controllers: [MainController, UsersCommand],
    providers: [MyMiddleware],
    middlewares: [
        httpMiddleware.for(MyMiddleware).forRoutes({
            path: 'api/*'
        })
    ],
    imports: [new FrameworkModule]
}).run();

forRoutes() 的第一个参数支持多种方式来筛选路由。

{
    path?: string;
    pathRegExp?: RegExp;
    httpMethod?: 'GET' | 'HEAD' | 'POST' | 'PATCH' | 'PUT' | 'DELETE' | 'OPTIONS' | 'TRACE';
    category?: string;
    excludeCategory?: string;
    group?: string;
    excludeGroup?: string;
}

路径模式

path 支持通配符 *。

httpMiddleware.for(MyMiddleware).forRoutes({
    path: 'api/*'
})

正则表达式

httpMiddleware.for(MyMiddleware).forRoutes({
    pathRegExp: /'api/.*'/
})

HTTP 方法

按某个 HTTP 方法筛选所有路由。

httpMiddleware.for(MyMiddleware).forRoutes({
    httpMethod: 'GET'
})

分类

category 及其对应的 excludeCategory 允许你按路由分类进行筛选。

@http.category('myCategory')
class MyFirstController {

}

class MySecondController {
    @http.GET().category('myCategory')
    myAction() {
    }
}
httpMiddleware.for(MyMiddleware).forRoutes({
    category: 'myCategory'
})

分组

group 及其对应的 excludeGroup 允许你按路由分组进行筛选。

@http.group('myGroup')
class MyFirstController {

}

class MySecondController {
    @http.GET().group('myGroup')
    myAction() {
    }
}
httpMiddleware.for(MyMiddleware).forRoutes({
    group: 'myGroup'
})

按模块

可以将中间件的执行限定为整个模块。

httpMiddleware.for(MyMiddleware).forModule(ApiModule)

按自身模块

若要让中间件只在其注册所在的模块中的所有控制器/路由上执行,请使用 forSelfModules()

const ApiModule = new AppModule({}, {
    controllers: [MainController, UsersCommand],
    providers: [MyMiddleware],
    middlewares: [
        //对同一模块中注册的所有控制器
        httpMiddleware.for(MyMiddleware).forSelfModules(),
    ],
});

超时

所有中间件最终都需要调用 next()。如果某个中间件在超时时间内没有调用 next(),则会记录一条警告并继续执行下一个中间件。要将默认的 4 秒更改为其他值,请使用 timeout(milliseconds)。

const ApiModule = new AppModule({}, {
    controllers: [MainController, UsersCommand],
    providers: [MyMiddleware],
    middlewares: [
        //对同一模块中注册的所有控制器
        httpMiddleware.for(MyMiddleware).timeout(15_000),
    ],
});

多重规则

要组合多个筛选条件,可以链式调用方法。

const ApiModule = new AppModule({}, {
    controllers: [MyController],
    providers: [MyMiddleware],
    middlewares: [
        httpMiddleware.for(MyMiddleware).forControllers(MyController).excludeRouteNames('secondRoute')
    ],
});

Express 中间件

几乎所有 Express 中间件都受支持。那些依赖于 Express 特定请求方法的中间件目前尚不支持。

import * as compression from 'compression';

const ApiModule = new AppModule({}, {
    middlewares: [
        httpMiddleware.for(compress()).forControllers(MyController)
    ],
});
English中文 (Chinese)한국어 (Korean)日本語 (Japanese)Deutsch (German)