做什么網(wǎng)站開發(fā)最簡(jiǎn)單網(wǎng)站排名查詢工具
前言
NestJS 作為一個(gè)強(qiáng)大的 Node.js 框架,允許你通過(guò)中間件對(duì)請(qǐng)求和響應(yīng)進(jìn)行處理。中間件的概念在其他許多框架中也存在,它們?cè)谡?qǐng)求處理流程的早期執(zhí)行,因此非常適合執(zhí)行如日志記錄、請(qǐng)求驗(yàn)證、設(shè)置響應(yīng)頭等任務(wù)。
在這篇教程中,我將通過(guò)一個(gè)簡(jiǎn)單的示例,展示如何在 NestJS 應(yīng)用中創(chuàng)建和使用自定義中間件。
使用步驟
第一步:創(chuàng)建中間件
在 NestJS 中創(chuàng)建中間件很簡(jiǎn)單,你只需要?jiǎng)?chuàng)建一個(gè)實(shí)現(xiàn)了 NestMiddleware
接口的類。這個(gè)類將包含一個(gè) use
方法,該方法接收 request
、response
對(duì)象和 next
函數(shù)。
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';@Injectable()
export class LoggingMiddleware implements NestMiddleware {use(req: Request, res: Response, next: NextFunction) {console.log(`[${new Date().toISOString()}] Request made to: ${req.path}`);next();}
}
在這個(gè)例子中,LoggingMiddleware
類會(huì)記錄請(qǐng)求到達(dá)的時(shí)間和路徑。
第二步:注冊(cè)中間件
接下來(lái),你需要在模塊中注冊(cè)這個(gè)中間件。這通常在模塊的 configure
方法中完成,你需要實(shí)現(xiàn) NestModule
接口并定義這個(gè)方法。
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';@Module({})
export class AppModule implements NestModule {configure(consumer: MiddlewareConsumer) {consumer.apply(LoggingMiddleware).forRoutes('*'); // 應(yīng)用到所有路由}
}
在這里,我們使用 MiddlewareConsumer
的 apply
方法來(lái)注冊(cè)中間件,并通過(guò) forRoutes
指定中間件應(yīng)用的路徑。在這個(gè)例子中,中間件將應(yīng)用于所有路由。
第三步:測(cè)試中間件
一旦你注冊(cè)了中間件,它就會(huì)在每個(gè)請(qǐng)求到來(lái)時(shí)執(zhí)行。要測(cè)試它,你可以啟動(dòng)你的 NestJS 應(yīng)用并向任意端點(diǎn)發(fā)送請(qǐng)求。
npm run start
然后,打開一個(gè)新的命令行窗口發(fā)送一個(gè)請(qǐng)求(使用 curl 或者任何 API 測(cè)試工具):
curl <http://localhost:3000/your-endpoint>
你應(yīng)該可以在 NestJS 應(yīng)用的控制臺(tái)輸出中看到日志行,類似于:
[2024-01-01T12:00:00.000Z] Request made to: /your-endpoint
高級(jí)使用
中間件不僅僅限于記錄日志。你可以利用中間件做很多有用的事情,比如:
- 請(qǐng)求驗(yàn)證: 確認(rèn)請(qǐng)求是否包含所需的憑證或參數(shù)。
- 速率限制: 限制來(lái)自同一來(lái)源的請(qǐng)求頻率,以預(yù)防濫用。
- CORS 設(shè)置: 在跨域請(qǐng)求中設(shè)置必要的頭信息,以支持安全的跨域交互。
記住,中間件執(zhí)行順序很重要。如果你注冊(cè)了多個(gè)中間件,它們會(huì)按順序執(zhí)行。這意味著,如果第一個(gè)中間件不調(diào)用 next()
,后續(xù)的中間件和路由處理器都不會(huì)被執(zhí)行。
一、請(qǐng)求驗(yàn)證
假設(shè)我們有一個(gè)API端點(diǎn) /secure
,它需要驗(yàn)證請(qǐng)求是否帶有有效的API密鑰。我們可以創(chuàng)建一個(gè)中間件來(lái)校驗(yàn)請(qǐng)求頭中的 x-api-key
字段。
import { Injectable, NestMiddleware, UnauthorizedException } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';@Injectable()
export class ApiKeyMiddleware implements NestMiddleware {private readonly VALID_API_KEY = 'secret';use(req: Request, res: Response, next: NextFunction) {const apiKey = req.headers['x-api-key'];if (apiKey && apiKey === this.VALID_API_KEY) {next();} else {throw new UnauthorizedException('Invalid API Key');}}
}
注冊(cè)這個(gè)中間件:
configure(consumer: MiddlewareConsumer) {consumer.apply(ApiKeyMiddleware).forRoutes('/secure');
}
任何請(qǐng)求 /secure
端點(diǎn)的客戶端都需要提供有效的API密鑰,否則請(qǐng)求會(huì)被拒絕。
二、速率限制
為了防止濫用,你可能需要限制客戶端在一定時(shí)間內(nèi)能夠發(fā)送到某個(gè)端點(diǎn)的請(qǐng)求數(shù)量。這樣的中間件可以利用第三方庫(kù)如 express-rate-limit
實(shí)現(xiàn)。
import rateLimit from 'express-rate-limit';export function RateLimiterMiddleware() {return rateLimit({windowMs: 15 * 60 * 1000, // 15分鐘max: 100, // 限制每個(gè)IP在15分鐘內(nèi)最多100個(gè)請(qǐng)求});
}
注冊(cè)中間件:
configure(consumer: MiddlewareConsumer) {consumer.apply(RateLimiterMiddleware()).forRoutes('/*'); // 適用于所有路由
}
這將會(huì)對(duì)所有請(qǐng)求施加速率限制,每個(gè)IP地址每15分鐘只允許最多100個(gè)請(qǐng)求。
三、CORS 設(shè)置
跨源資源共享(CORS)是一種安全特性,限制了網(wǎng)頁(yè)上可以加載和使用哪些資源。如果你想允許來(lái)自特定來(lái)源的請(qǐng)求,你可以使用中間件來(lái)設(shè)置CORS相關(guān)的響應(yīng)頭。
雖然 NestJS 提供了內(nèi)置的CORS支持,但如果你需要更高級(jí)的配置,可以自定義CORS中間件,例如:
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';@Injectable()
export class CorsMiddleware implements NestMiddleware {use(req: Request, res: Response, next: NextFunction) {res.header('Access-Control-Allow-Origin', '<https://example.com>');res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');next();}
}
注冊(cè)中間件:
configure(consumer: MiddlewareConsumer) {consumer.apply(CorsMiddleware).forRoutes('/*'); // 適用于所有路由
}
這個(gè)簡(jiǎn)單的CORS中間件允許來(lái)自 https://example.com
的請(qǐng)求,并允許 GET
、POST
和 OPTIONS
方法,同時(shí)允許 Content-Type
和 Authorization
請(qǐng)求頭。
結(jié)論
中間件是 NestJS 框架靈活性的關(guān)鍵組成部分,能夠通過(guò)簡(jiǎn)單有效的方式實(shí)現(xiàn)請(qǐng)求的預(yù)處理。上面介紹的高級(jí)使用方式,包括請(qǐng)求驗(yàn)證、速率限制和CORS設(shè)置,都是實(shí)際應(yīng)用中常見并且非常實(shí)用的場(chǎng)景。合理地使用中間件可以讓你的應(yīng)用更加安全和穩(wěn)定,同時(shí)提高用戶體驗(yàn)。
結(jié)論
中間件是 NestJS 框架靈活性的關(guān)鍵組成部分,能夠通過(guò)簡(jiǎn)單有效的方式實(shí)現(xiàn)請(qǐng)求的預(yù)處理。通過(guò)創(chuàng)建 NestMiddleware
接口的實(shí)現(xiàn)類,你可以在請(qǐng)求處理鏈中插入自己的邏輯。注冊(cè)中間件方法是直觀而靈活的,讓你可以精確控制中間件的應(yīng)用范圍。