Прамежкавае праграмнае забеспячэнне
Прамежкавае праграмнае забеспячэнне - гэта функцыя, якая выклікаецца перад апрацоўшчыкам маршруту. Функцыі прамежкавага праграмнага забеспячэння маюць доступ да аб'ектаў запыту і адказу , а таксама функцыі прамежкавага праграмнага забеспячэння next()
у цыкле запыт-адказ прыкладання. Наступная функцыя прамежкавага праграмнага забеспячэння звычайна пазначаецца зменнай з імем next
.
Прамежкавае праграмнае забеспячэнне Nest па змаўчанні эквівалентна экспрэс - п рамежкавым ПЗ. Наступнае апісанне з афіцыйнай экспрэс-дакументацыі апісвае магчымасці прамежкавага праграмнага забеспячэння:
Функцыі прамежкавага праграмнага забеспячэння могуць выконваць наступныя задачы:
- выканаць любы код.
- уносіць змены ў аб'екты запыту і адказу.
- завяршыць цыкл запыт-адказ.
- выклікаць наступную функцыю прамежкавага праграмнага забеспячэння ў стэку.
- калі бягучая функцыя прамежкавага праграмнага забеспячэння не завяршае цыкл запыт-адказ, яна павінна выклікаць
next()
каб перадаць кіраванне наступнай функцыі прамежкавага праграмнага забеспячэння. У адваротным выпадку запыт застанецца вісіць.
Вы рэалізуеце карыстальніцкае прамежкавае праграмнае забеспячэнне Nest альбо ў функцыі, альбо ў класе з дэкаратарам @Injectable()
. Клас павінен рэалізаваць інтэрфейс NestMiddleware
, пры гэтым функцыя не мае асаблівых патрабаванняў. Давайце пачнем з рэалізацыі простай функцыі прамежкавага праграмнага забеспячэння з выкарыстаннем метаду класа.
папярэджанне Папярэджанне
Express
іfastify
па-роз наму апрацоўваюць прамежкавае праграмнае забеспячэнне і забяспечваюць розныя сігнатуры метадаў, чытайце больш тут .
@@filename(logger.middleware)
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log('Request...');
next();
}
}
@@switch
import { Injectable } from '@nestjs/common';
@Injectable()
export class LoggerMiddleware {
use(req, res, next) {
console.log('Request...');
next();
}
}
Ін'екцыя залежнасці
Прамежкавае праграмнае забеспячэнне Nest цалкам падтрымлівае Dependency Injection. Гэтак жа, як у выпадку з пастаўшчыкамі і кантролерам, яны могуць уводзіць залежнасці , якія даступныя ў адным модулі. Як звычайна, гэта робіцца праз constructor
.
Прымяненне прамежкавага праграмнага забеспячэння
У дэкаратары @Module()
няма месца для прамежкавага праграмнага забеспячэння. Замест гэтага мы наладжваем іх з дапамогай метаду configure()
класа модуля. Модулі, якія ўключаюць прамежкавае праграмнае забеспячэнне, павінны рэалізаваць інтэрфейс NestModule
. Давайце наладзім LoggerMiddleware
на ўзроўні AppModule
.
@@filename(app.module)
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('cats');
}
}
@@switch
import { Module } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class AppModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('cats');
}
}
У прыведзеным вышэй прыкладзе мы наладзілі LoggerMiddleware
для апрацоўшчыкаў маршрутаў /cats
, якія раней былі вызначаны ўнутры CatsController
. Мы таксама можам дадаткова абмежаваць прамежкавае праграмнае забеспячэнне пэўным метадам запыту, перадаўшы аб'ект, які змяшчае path
маршруту і method
запыту, у метад forRoutes()
пры наладжванні прамежкавага праграмнага забеспячэння. Звярніце ўвагу на тое, што ў прыведзеным ніжэй прыкладзе мы імпартуем пералік RequestMethod
для спасылкі на патрэбны тып метаду запыту.
@@filename(app.module)
import { Module, NestModule, RequestMethod, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes({ path: 'cats', method: RequestMethod.GET });
}
}
@@switch
import { Module, RequestMethod } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class AppModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes({ path: 'cats', method: RequestMethod.GET });
}
}
configure()
можна зрабіць асінхронным з дапамогай async/await
(напрыклад, вы можаце await
завяршэння асінхроннай аперацыі ўнутры цела метаду configure()
). ::::::папярэджанне Папярэджанне Пры выкарыстанні express
адаптара праграма NestJS па змаўчанні зарэгіструе json
і urlencoded
з body-parser
пакета. Гэта азначае, што калі вы хочаце наладзіць прамежкавае праграмнае забеспячэнне праз MiddlewareConsumer
, вам трэба адключыць глабальнае прамежкавае праграмнае забеспячэнне, усталяваўшы для флага bodyParser
значэнне false
пры стварэнні прыкладання з дапамогай NestFactory.create()
. :::
Падстаноўныя знакі маршруту
Таксама падтрымліваюцца маршруты на аснове шаблонаў. Напрыклад, зорачка выкарыстоўваецца як сімвал падстаноўкі і будзе адпавядаць любой камбінацыі знакаў:
forRoutes({ path: 'ab*cd', method: RequestMethod.ALL });
Шлях маршруту 'ab*cd'
будзе адпавядаць abcd
, ab_cd
, abecd
і гэтак далей. Персанажы ?
, +
, *
і ()
могуць выкарыстоўвацца ў шляху маршруту і з'яўляюцца падмноствамі сваіх аналагаў рэгулярных выразаў. Злучок ( -
) і кропка ( .
) інтэрпрэтуюцца літаральна шляхамі на аснове радкоў.
:::папярэджанне Папярэджанне Пакет fastify
выкарыстоўвае апошнюю версію пакета path-to-regexp
, які больш не падтрымлівае падстаноўныя зорачкі *
. Замест гэтага вы павінны выкарыстоўваць параметры (напрыклад, (.*)
, :splat*
). :::
Спажывец прамежкавага ПЗ
MiddlewareConsumer
- гэта дапаможны клас. Ён забяспечвае некалькі ўбудаваных метадаў кіравання прамежкавым праграмным забеспячэннем. Усе яны могуць быць проста звязаны ў ланцужок у беглым стылі . Метад forRoutes()
можа прымаць адзін радок, некалькі радкоў, аб'ект RouteInfo
, клас кантролера і нават некалькі класаў кантролера. У большасці выпадкаў вы, верагодна, проста перадасце спіс кантролераў, падзеленых коскамі. Ніжэй прыведзены прыклад з адным кантролерам:
@@filename(app.module)
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
import { CatsController } from './cats/cats.controller';
@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes(CatsController);
}
}
@@switch
import { Module } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';
import { CatsController } from './cats/cats.controller';
@Module({
imports: [CatsModule],
})
export class AppModule {
configure(consumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes(CatsController);
}
}
apply()
можа прымаць адно прамежкавае праграмнае забеспячэнне або некалькі аргументаў для ўказання некалькіх прамежкавых праграм . :::Без уліку маршрутаў
Часам мы хочам выключыць некаторыя маршруты з прымянення прамежкавага праграмнага забеспячэння. Мы можам лёгка выключыць пэўныя маршруты з дапамогай метаду exclude()
. Гэты метад можа выключаць адзін радок, некалькі радкоў або аб'ект RouteInfo
, які вызначае маршруты, як паказана ніжэй:
consumer
.apply(LoggerMiddleware)
.exclude(
{ path: 'cats', method: RequestMethod.GET },
{ path: 'cats', method: RequestMethod.POST },
'cats/(.*)',
)
.forRoutes(CatsController);
exclude()
падтрымлівае параметры падстаноўкі з выкарыстаннем пакета шлях да рэгулярных выразаў . :::У прыведзеным вышэй прыкладзе LoggerMiddleware
будзе прывязаны да ўсіх маршрутаў, вызначаных у CatsController
акрамя трох, перададзеных у метад exclude()
.
Функцыянальнае прамежкавае праграмнае забеспячэнне
Клас LoggerMiddleware
які мы выкарыстоўваем, даволі просты. Ён не мае членаў, дадатковых метадаў і залежнасцей. Чаму мы не можам проста вызначыць яго ў простай функцыі замест класа? На самай справе, мы можам. Гэты тып прамежкавага праграмнага забеспячэння называецца функцыянальным прамежкавым праграмным забеспячэннем . Давайце пераўтворым прамежкавае праграмнае забеспячэнне рэгістратара з класавага ў функцыянальнае прамежкавае праграмнае забеспячэнне, каб праілюстраваць розніцу:
@@filename(logger.middleware)
import { Request, Response, NextFunction } from 'express';
export function logger(req: Request, res: Response, next: NextFunction) {
console.log(`Request...`);
next();
};
@@switch
export function logger(req, res, next) {
console.log(`Request...`);
next();
};
І выкарыстоўвайце яго ў AppModule
:
@@filename(app.module)
consumer
.apply(logger)
.forRoutes(CatsController);
Некалькі прамежкавага праграмнага забеспячэння
Як згадвалася вышэй, каб прывязаць некалькі прамежкавага праграмнага забеспячэння, якое выконваецца паслядоўна, проста ўвядзіце спіс праз коскі ўнутры метаду apply()
:
consumer.apply(cors(), helmet(), logger).forRoutes(CatsController);
Глабальнае прамежкавае праграмнае забеспячэнне
Калі мы хочам прывязаць прамежкавае праграмнае забеспячэнне да кожнага зарэгістраванага маршруту адначасова, мы мож ам выкарыстоўваць метад use()
, які пастаўляецца асобнікам INestApplication
:
@@filename(main)
const app = await NestFactory.create(AppModule);
app.use(logger);
await app.listen(3000);
app.use()
. Акрамя таго, вы можаце выкарыстоўваць прамежкавае праграмнае забеспячэнне класа і выкарыстоўваць яго з дапамогай .forRoutes('*')
у AppModule
(ці любым іншым модулі). :::