Middlewares相信用Express框架開發的朋友對這名詞不會太陌生,很多時候我們會透過Middlewares,在router收到請求前就先做些處理,Nestjs在這方面有不少的著墨,可以讓我們在使用Middlewares時有更細緻的處理。
cd src/modules & mkdir Shared & cd Shared & mkdir Middlewares
import { Middleware, ExpressMiddleware, NestMiddleware } from '@nestjs/common';
//Middleware的裝飾器
@Middleware()
export class LoggerMiddleware implements NestMiddleware {
//resolve可以傳參
resolve(...args: any[]): ExpressMiddleware {
//會返回ExpressMiddleware
return (req, res, next) => {
console.log('執行middleware...');
//呼叫next()方法,程式才會繼續往下執行,否則將停在此階段。
next();
}
}
}
核心概念其實跟Express的Middleware相差無幾。
import { Module, RequestMethod } from '@nestjs/common';
import { UsersService } from './Users/Services/users.service';
import { UsersModule } from './Users/users.module';
import { LoggerMiddleware } from './Shared/Middlewares/logger.middleware';
import { NestModule, MiddlewaresConsumer } from '@nestjs/common/interfaces';
@Module({
modules: [UsersModule]
})
//NestModule本身是個Interface,建議要implements。
export class ApplicationModule implements NestModule{
configure(consumer: MiddlewaresConsumer): void {
//apply、forRoute方法允許傳入多個參數
consumer.apply(LoggerMiddleware).forRoutes(
//RequestMethod有多個HTTP Method的屬性可以使用
{ path: '/users', method: RequestMethod.ALL },
{ path: '/products', method: RequestMethod.ALL }
)
}
}
[Nest] 15480 - 2017-12-7 23:21:06 [NestFactory] Starting Nest application...
[Nest] 15480 - 2017-12-7 23:21:06 [InstanceLoader] ApplicationModule dependencies initialized +7ms
[Nest] 15480 - 2017-12-7 23:21:06 [InstanceLoader] UsersModule dependencies initialized +3ms
[Nest] 15480 - 2017-12-7 23:21:06 [InstanceLoader] ProductsModule dependencies initialized +2ms
[Nest] 15480 - 2017-12-7 23:21:06 [RoutesResolver] UsersController {/}: +53ms
[Nest] 15480 - 2017-12-7 23:21:06 [RouterExplorer] Mapped {/users, GET} route +3ms
[Nest] 15480 - 2017-12-7 23:21:06 [RouterExplorer] Mapped {/users/:id, GET} route +1ms
[Nest] 15480 - 2017-12-7 23:21:06 [RouterExplorer] Mapped {/users, POST} route +1ms
[Nest] 15480 - 2017-12-7 23:21:06 [RouterExplorer] Mapped {/testProducts, GET} route +1ms
[Nest] 15480 - 2017-12-7 23:21:06 [RoutesResolver] ProductsController {/products}: +2ms
[Nest] 15480 - 2017-12-7 23:21:06 [RouterExplorer] Mapped {/, GET} route +10ms
[Nest] 15480 - 2017-12-7 23:21:06 [RouterExplorer] Mapped {/:id, GET} route +2ms
[Nest] 15480 - 2017-12-7 23:21:06 [RouterExplorer] Mapped {/, POST} route +1ms
[Nest] 15480 - 2017-12-7 23:21:06 [NestApplication] Nest application successfully started +3ms
Application based on Express is listening on port 3000
執行middleware...
LoggerMiddleware有正常執行。
import { Module, RequestMethod } from '@nestjs/common';
import { UsersController } from './Users/users.controller';
import { UsersService } from './Users/Services/users.service';
import { UsersModule } from './Users/users.module';
import { LoggerMiddleware } from './Shared/Middlewares/logger.middleware';
import { NestModule, MiddlewaresConsumer } from '@nestjs/common/interfaces';
import { ProductsController } from './Products/products.controller';
@Module({
modules: [UsersModule]
})
//NestModule本身是個Interface,建議要implements。
export class ApplicationModule implements NestModule{
configure(consumer: MiddlewaresConsumer): void {
//apply、forRoute方法允許傳入多個參數
consumer.apply(LoggerMiddleware).forRoutes(
//load進Controllers
UsersController,
ProductsController
)
}
}
import { Module, RequestMethod } from '@nestjs/common';
import { UsersController } from './Users/users.controller';
import { UsersService } from './Users/Services/users.service';
import { UsersModule } from './Users/users.module';
import { LoggerMiddleware } from './Shared/Middlewares/logger.middleware';
import { NestModule, MiddlewaresConsumer } from '@nestjs/common/interfaces';
import { ProductsController } from './Products/products.controller';
@Module({
modules: [UsersModule]
})
//NestModule本身是個Interface,建議要implements。
export class ApplicationModule implements NestModule{
configure(consumer: MiddlewaresConsumer): void {
//apply、forRoute方法允許傳入多個參數
consumer.apply(LoggerMiddleware)
//with方法可以傳入參數到middleware
.with('來自根模組的參數')
.forRoutes(
//load進Controllers
UsersController,
ProductsController
)
}
}
src/modules/Shared/Middlewares/logger.middleware.ts
import { Middleware, ExpressMiddleware, NestMiddleware } from '@nestjs/common';
//Middleware的裝飾器
@Middleware()
export class LoggerMiddleware implements NestMiddleware {
//resolve可以傳參
resolve(message: string): ExpressMiddleware {
//會返回ExpressMiddleware
return (req, res, next) => {
//使用字符串
console.log(`${message}`);
console.log('執行middleware...');
//呼叫next()方法,程式才會繼續往下執行,否則將停在此階段。
next();
}
}
}
console結果如下。
[Nest] 13708 - 2017-12-7 23:47:52 [NestFactory] Starting Nest application...
[Nest] 13708 - 2017-12-7 23:47:52 [InstanceLoader] ApplicationModule dependencies initialized +7ms
[Nest] 13708 - 2017-12-7 23:47:52 [InstanceLoader] UsersModule dependencies initialized +4ms
[Nest] 13708 - 2017-12-7 23:47:52 [InstanceLoader] ProductsModule dependencies initialized +1ms
[Nest] 13708 - 2017-12-7 23:47:52 [RoutesResolver] UsersController {/}: +55ms
[Nest] 13708 - 2017-12-7 23:47:52 [RouterExplorer] Mapped {/users, GET} route +3ms
[Nest] 13708 - 2017-12-7 23:47:52 [RouterExplorer] Mapped {/users/:id, GET} route +1ms
[Nest] 13708 - 2017-12-7 23:47:52 [RouterExplorer] Mapped {/users, POST} route +1ms
[Nest] 13708 - 2017-12-7 23:47:52 [RouterExplorer] Mapped {/testProducts, GET} route +1ms
[Nest] 13708 - 2017-12-7 23:47:52 [RoutesResolver] ProductsController {/products}: +1ms
[Nest] 13708 - 2017-12-7 23:47:52 [RouterExplorer] Mapped {/, GET} route +3ms
[Nest] 13708 - 2017-12-7 23:47:52 [RouterExplorer] Mapped {/:id, GET} route +3ms
[Nest] 13708 - 2017-12-7 23:47:52 [RouterExplorer] Mapped {/, POST} route +8ms
[Nest] 13708 - 2017-12-7 23:47:52 [NestApplication] Nest application successfully started +2ms
Application based on Express is listening on port 3000
來自根模組的參數
執行middleware...
middleware確實有收到來自根模組傳過來的參數。
export const SimpleMiddleware = (req, res, next) => {
console.log('我是簡單的Middleware');
next();
}
import { Module, RequestMethod } from '@nestjs/common';
import { UsersController } from './Users/users.controller';
import { UsersService } from './Users/Services/users.service';
import { UsersModule } from './Users/users.module';
import { LoggerMiddleware } from './Shared/Middlewares/logger.middleware';
import { SimpleMiddleware } from './Shared/Middlewares/simple.middleware';
import { NestModule, MiddlewaresConsumer } from '@nestjs/common/interfaces';
import { ProductsController } from './Products/products.controller';
@Module({
modules: [UsersModule]
})
//NestModule本身是個Interface,建議要implements。
export class ApplicationModule implements NestModule {
configure(consumer: MiddlewaresConsumer): void {
//apply、forRoute方法允許傳入多個參數
consumer.apply([LoggerMiddleware,SimpleMiddleware])
//with方法可以傳入參數到middleware
.with('來自根模組的參數')
.forRoutes(
//load進Controllers
UsersController,
ProductsController
)
}
}
[Nest] 7232 - 2017-12-8 00:30:29 [NestFactory] Starting Nest application...
[Nest] 7232 - 2017-12-8 00:30:29 [InstanceLoader] ApplicationModule dependencies initialized +7ms
[Nest] 7232 - 2017-12-8 00:30:29 [InstanceLoader] UsersModule dependencies initialized +2ms
[Nest] 7232 - 2017-12-8 00:30:29 [InstanceLoader] ProductsModule dependencies initialized +1ms
[Nest] 7232 - 2017-12-8 00:30:30 [RoutesResolver] UsersController {/}: +66ms
[Nest] 7232 - 2017-12-8 00:30:30 [RouterExplorer] Mapped {/users, GET} route +4ms
[Nest] 7232 - 2017-12-8 00:30:30 [RouterExplorer] Mapped {/users/:id, GET} route +1ms
[Nest] 7232 - 2017-12-8 00:30:30 [RouterExplorer] Mapped {/users, POST} route +1ms
[Nest] 7232 - 2017-12-8 00:30:30 [RouterExplorer] Mapped {/testProducts, GET} route +1ms
[Nest] 7232 - 2017-12-8 00:30:30 [RoutesResolver] ProductsController {/products}: +1ms
[Nest] 7232 - 2017-12-8 00:30:30 [RouterExplorer] Mapped {/, GET} route +1ms
[Nest] 7232 - 2017-12-8 00:30:30 [RouterExplorer] Mapped {/:id, GET} route +1ms
[Nest] 7232 - 2017-12-8 00:30:30 [RouterExplorer] Mapped {/, POST} route +0ms
[Nest] 7232 - 2017-12-8 00:30:30 [NestApplication] Nest application successfully started +3ms
Application based on Express is listening on port 3000
來自根模組的參數
執行middleware...
我是簡單的Middleware
Middlewares執行是有順序性的,consumer.apply([xxx,ooo]),會依據陣列順序下去執行,藉由next()進行下個Middware。
程式在github