0

我需要使用 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);
      }),
    );
  }
}

但是从我读到的内容来看,它是在警卫之后调用的,因此不会记录未经授权的请求。

完成这样一项任务的好方法是什么?

4

0 回答 0