中间件
中间件 个人感觉不如拦截器 和 异常捕获器好用
中间件是在路由处理器之前被调用的函数.中间件函数可以访问请求和响应对象.以及应用程序请求-响应周期中的下一个中间件函数
下一个中间件函数通常用一个名为 next 的变量表示
Nest 中的中间件默认等同于 Express 中的中间件
中间件
中间件 == 拦截器 + 异常过滤器
但是中间件只能全局和局部使用
执行任何代码
修改请求和响应对象
结束请求-响应周期
调用堆栈中的下一个中间件
如果当前中间件没有结束请求-响应周期.它必须调用 next()方法将控制权传递给下一个中间件,否则请求将被挂起
代码
ts
import { AppService } from "./app.service";
import { Inject, Injectable, NestMiddleware } from "@nestjs/common";
import { Request, Response } from "express";
@Injectable()
export class AaaMiddleware implements NestMiddleware {
@Inject(AppService)
private readonly appService: AppService;
use(req: Request, res: Response, next: () => void) {
console.log("brefore");
console.log("-------" + this.appService.getHello());
next();
console.log("after");
}
}
::: waring 注意
next 前面 是请求前,next 后面是请求后之星的
可以利用 Inject 被注入的 service
:::
挂载
- 模块文件中挂载
ts
import {
Module,
NestModule,
MiddlewareConsumer,
RequestMethod,
} from "@nestjs/common";
import { Test1Service } from "./test1.service";
import { Test1Controller } from "./test1.controller";
import { Test1Middleware } from "./test1.middleware";
@Module({
controllers: [Test1Controller],
providers: [Test1Service],
})
export class Test1Module {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(Test1Middleware)
.forRoutes({ path: "test1*path", method: RequestMethod.GET });
}
}
这里就是匹配 test1 后面的所有路由 并且 方法是 GET 方法
next 与 装饰器 @Next 区别
middleware 的 next 参数就是调用下一个 middleware 的,这个很好理解。
而 @Next 装饰器是调用下一个 handler 的:
举例如下
这样他会相应第二个 返回 hello2
与拦截器的不同
- 拦截器里面能获取到 class 和 handler() 但是中间件不行
全局中间件
新建中间件文件
名字是 global.middleware.ts
这里面实现了 验证和捕获异常中间件
ts
import { Injectable, NestMiddleware } from "@nestjs/common";
import { Request, Response } from "express";
@Injectable()
export class GlobalMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => void) {
console.log("请求前");
if (req.headers["authorization"]) {
try {
next();
} catch (e) {
res.send({
code: 500,
message: "服务器错误",
data: null,
});
return;
}
} else {
res.status(401).send({
code: 401,
message: "未授权3",
data: null,
});
}
}
}
挂载到全局
- 要是多个 就在
apply(,,,)
以逗号分开
ts
import { MiddlewareConsumer, Module, NestModule } from "@nestjs/common";
import { GlobalMiddleware } from "./global/middleware/global.middleware";
import { LoginModule } from "./Login/login.module";
@Module({
imports: [LoginModule],
controllers: [],
providers: [],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(GlobalMiddleware).forRoutes("*"); // apply middleware to all routes
}
}
挂载到各个模块下面的modules,就仅仅对各个模块使用
局部中间件
排除
- exclude 排除路由 这样里面的都不执行这个中间件
exclude 通过path和method
路径和请求方式必须都一样才会排除
ts
// logins 模块
import {
MiddlewareConsumer,
Module,
NestModule,
RequestMethod,
} from "@nestjs/common";
import { LoginController } from "./controller/login.controller";
import { LoginService } from "./service/login.service";
import { LoginMiddleware } from "./middleware/login.middleware";
@Module({
imports: [],
controllers: [LoginController],
providers: [LoginService],
exports: [],
})
export class LoginModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoginMiddleware)
.exclude({ path: "logins/test2", method: RequestMethod.GET })
.forRoutes("logins");
}
}
只在某个路由使用
路径和 请求方法必须完全匹配才行
ts
import {
MiddlewareConsumer,
Module,
NestModule,
RequestMethod,
} from "@nestjs/common";
import { LoginController } from "./controller/login.controller";
import { LoginService } from "./service/login.service";
import { LoginMiddleware } from "./middleware/login.middleware";
@Module({
imports: [],
controllers: [LoginController],
providers: [LoginService],
exports: [],
})
export class LoginModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoginMiddleware)
.forRoutes({ path: "logins/test2", method: RequestMethod.GET });
}
}
限定控制器
ts
import {
MiddlewareConsumer,
Module,
NestModule,
RequestMethod,
} from "@nestjs/common";
import { LoginController } from "./controller/login.controller";
import { LoginService } from "./service/login.service";
import { LoginMiddleware } from "./middleware/login.middleware";
@Module({
imports: [],
controllers: [LoginController],
providers: [LoginService],
exports: [],
})
export class LoginModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoginMiddleware).forRoutes(LoginController);
}
}
跨域
两种方法
- 命令
main.ts
使用命令
ts
const app = await NestFactory.create(AppModule);
app.enableCors();
await app.listen(3000);
- 通过参数
ts
const app = await NestFactory.create(AppModule, { cors: true });
await app.listen(3000);