拦截器
拦截器和中间件的不同处
- 中间件的执行时机要早于拦截器
中间件的执行时机要早于拦截器
- 中间件是可以中断不合法的请求的,拦截器不行
拦截器是对控制器方法的增强或者削弱,它必须依赖于控制器的方法
- 中间件无法知道处理当前请求的控制器和处理请求的控制器方法
拦截器可以知道.拦截器能够利用反射获取到控制器或方法上的一些元数据,从而判断token,鉴权之类的
拦截器种类和位置
种类
全局拦截器
控制器拦截器
路由拦截器
位置
前置拦截器
后置拦截器
拦截器使用
按照位置(来说)
- 先创建一个拦截器起名 : xxxx.interceptor.ts
ts
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
Inject,
HttpException,
} from "@nestjs/common";
import { Observable, map, of } from "rxjs";
import { Request } from "express";
import { WINSTON_MODULE_PROVIDER } from "nest-winston";
import { Logger } from "winston";
import { getReqMainInfo } from "../utils/utils";
@Injectable()
export class GlobalInterceptor implements NestInterceptor {
constructor(
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger
) {}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
/* 前置拦截器 */
/* 判断有没有token,没有就不要进入路由 直接返回,有则放行 */
/* 这里返回用of,你抛出异常也可以会记录到日志,所以一般用of */
const ctx = context.switchToHttp();
const req = ctx.getRequest<Request>();
// 获取路径
const url = req.url;
const token = req.headers["access-token"];
if (token) {
return of({
code: 401,
msg: "token不存在",
});
// 或者直接抛出异常
// throw new HttpException('token不存在', 401);
}
/* 前置拦截器结束 */
/* 后置拦截器 */
/* 统一回复管理 */
return next.handle().pipe(
map((data) => {
// 记录请求日志
this.logger.info("response", {
responseData: data,
req: getReqMainInfo(req),
});
// 设置响应头
ctx.getResponse().set("access-token", token);
// 设置相应头部
ctx.getResponse().set("test", "hehhe");
// 返回数据
return {
code: 200,
data,
msg: "success",
};
})
);
}
}
拦截器功能
- 全局拦截器
找到 app.module.ts 文件,在 providers 中添加
ts
// 拦截器
// 引入类型 方便挂载全局
import { APP_FILTER, APP_INTERCEPTOR } from '@nestjs/core';
// 引入 你自己的拦截器
import { GlobalInterceptor } from './global/interceptor/global.interceptor';
@Module({
imports: [],
controllers: [],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: GlobalInterceptor,
},
],
})
这样全局都可以使用
- 控制器使用
在你自己的控制器 xxxxx.controller.ts 中添加
这样这个路由下面的所有路由都会使用这个拦截器
ts
// 引用
import { UseInterceptors } from "@nestjs/common";
import { GlobalInterceptor } from "src/global/interceptor/global.interceptor";
@Controller("logins")
@UseInterceptors(GlobalInterceptor)
export class LoginController {
// .......
}
- 针对单个方法
ts
// 引用
import { UseInterceptors } from "@nestjs/common";
import { GlobalInterceptor } from "src/global/interceptor/global.interceptor";
@Controller("logins")
export class LoginController {
@Get("test")
@UseInterceptors(GlobalInterceptor)
test() {
return "test";
}
}