我需要使用 Fastify 在我的 Nest.js API 上记录请求和响应。类似于 Apache access_log 中的内容,包括 IP 地址、URL、响应状态代码等...
我第一次尝试用中间件来做,但我找不到捕获异常的方法,next()
调用后的响应状态码总是 200。在他们使用的 Express 示例中,response.on('close', () => {}
但它不适用于 Fastify。
import { Inject, Injectable, NestMiddleware } from '@nestjs/common';
import { FastifyReply, FastifyRequest } from 'fastify';
import { HttpLoggerService } from '../logger/http-logger.service';
@Injectable()
export class HttpLoggerMiddleware implements NestMiddleware {
constructor(
@Inject(HttpLoggerService) private loggerService: HttpLoggerService,
) {}
async use(request: FastifyRequest, reply: FastifyReply, next: () => void) {
const { ip, method, url } = request;
const user = 'someone';
const now = Date.now();
await next();
this.loggerService.log(
`${ip} - ${user} [${now}] "${method} ${url}" ${reply.statusCode}`,
);
}
}
我几乎无法使用拦截器(尚未完成):
import {
CallHandler,
ExecutionContext,
HttpException,
Inject,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { Observable, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
const { body, url, ip, method } = request;
const now = Date.now();
const user = 'someone';
return next.handle().pipe(
tap(() => {
const response = context.switchToHttp().getResponse();
console.log(
`${ip} - ${user} [${now}] "${method} ${url}" ${response.statusCode}`,
);
}),
catchError((err: Error) => {
if (err instanceof HttpException) {
const status: number = (<HttpException>err).getStatus();
console.log(
`${ip} - ${user} [${now}] "${method} ${url}" ${status} ${err.stack}`,
);
}
return throwError(err);
}),
);
}
}
但是从我读到的内容来看,它是在警卫之后调用的,因此不会记录未经授权的请求。
完成这样一项任务的好方法是什么?