chore: add http logger and core interceptors
This commit is contained in:
+7
-2
@@ -1,10 +1,11 @@
|
|||||||
import { CacheModule } from "@nestjs/cache-manager";
|
import { CacheModule } from "@nestjs/cache-manager";
|
||||||
import { Module } from "@nestjs/common";
|
import { MiddlewareConsumer, Module, NestModule } from "@nestjs/common";
|
||||||
import { ConfigModule } from "@nestjs/config";
|
import { ConfigModule } from "@nestjs/config";
|
||||||
import { TypeOrmModule } from "@nestjs/typeorm";
|
import { TypeOrmModule } from "@nestjs/typeorm";
|
||||||
|
|
||||||
import { cacheConfig } from "./configs/cache.config";
|
import { cacheConfig } from "./configs/cache.config";
|
||||||
import { DatabaseConfigs } from "./configs/typeorm.config";
|
import { DatabaseConfigs } from "./configs/typeorm.config";
|
||||||
|
import { HTTPLogger } from "./core/middlewares/logger.middleware";
|
||||||
import { TicketsModule } from "./modules/tickets/tickets.module";
|
import { TicketsModule } from "./modules/tickets/tickets.module";
|
||||||
import { UsersModule } from "./modules/users/users.module";
|
import { UsersModule } from "./modules/users/users.module";
|
||||||
|
|
||||||
@@ -19,4 +20,8 @@ import { UsersModule } from "./modules/users/users.module";
|
|||||||
controllers: [],
|
controllers: [],
|
||||||
providers: [],
|
providers: [],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule implements NestModule {
|
||||||
|
configure(consumer: MiddlewareConsumer) {
|
||||||
|
consumer.apply(HTTPLogger).forRoutes("*");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus } from "@nestjs/common";
|
||||||
|
import { FastifyReply, FastifyRequest } from "fastify";
|
||||||
|
|
||||||
|
@Catch(HttpException)
|
||||||
|
export class HttpExceptionFilter implements ExceptionFilter {
|
||||||
|
catch(exception: HttpException, host: ArgumentsHost) {
|
||||||
|
const ctx = host.switchToHttp();
|
||||||
|
const reply = ctx.getResponse<FastifyReply>();
|
||||||
|
const request = ctx.getRequest<FastifyRequest>();
|
||||||
|
const status = exception.getStatus() || HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
|
||||||
|
const exceptionResponse = exception.getResponse();
|
||||||
|
const message = this.extractMessage(exceptionResponse);
|
||||||
|
|
||||||
|
reply.status(status).send({
|
||||||
|
statusCode: status,
|
||||||
|
success: false,
|
||||||
|
error: {
|
||||||
|
message,
|
||||||
|
// timestamp: new Date().toISOString(),
|
||||||
|
path: request.url,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private extractMessage(response: string | Record<string, any>): string | string[] {
|
||||||
|
if (typeof response === "string") {
|
||||||
|
return [response];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof response === "object" && "message" in response) {
|
||||||
|
return Array.isArray(response.message) ? response.message : [response.message];
|
||||||
|
}
|
||||||
|
|
||||||
|
return "something wrong";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from "@nestjs/common";
|
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from "@nestjs/common";
|
||||||
import { Response } from "express";
|
import { FastifyReply } from "fastify";
|
||||||
import { Observable } from "rxjs";
|
import { Observable } from "rxjs";
|
||||||
import { map } from "rxjs/operators";
|
import { map } from "rxjs/operators";
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ import { map } from "rxjs/operators";
|
|||||||
export class ResponseInterceptor implements NestInterceptor {
|
export class ResponseInterceptor implements NestInterceptor {
|
||||||
//
|
//
|
||||||
intercept(context: ExecutionContext, next: CallHandler<Record<string, unknown>>): Observable<unknown> {
|
intercept(context: ExecutionContext, next: CallHandler<Record<string, unknown>>): Observable<unknown> {
|
||||||
const ctx = context.switchToHttp().getResponse<Response>();
|
const ctx = context.switchToHttp().getResponse<FastifyReply>();
|
||||||
const statusCode = ctx.statusCode;
|
const statusCode = ctx.statusCode;
|
||||||
|
|
||||||
return next.handle().pipe(
|
return next.handle().pipe(
|
||||||
|
|||||||
@@ -1,24 +1,26 @@
|
|||||||
// import { Injectable, Logger, NestMiddleware } from "@nestjs/common";
|
import { Injectable, Logger, NestMiddleware } from "@nestjs/common";
|
||||||
// import { FastifyReply, FastifyRequest } from "fastify";
|
import { FastifyReply, FastifyRequest } from "fastify";
|
||||||
|
|
||||||
// @Injectable()
|
@Injectable()
|
||||||
// export class HTTPLoggerMiddleware implements NestMiddleware {
|
export class HTTPLogger implements NestMiddleware {
|
||||||
// private readonly logger = new Logger(HTTPLoggerMiddleware.name);
|
private readonly logger = new Logger(HTTPLogger.name);
|
||||||
// // use(req: any, res: any, next: (error?: Error | any) => void) {}
|
// use(req: any, res: any, next: (error?: Error | any) => void) {}
|
||||||
|
|
||||||
// use(req: FastifyRequest, res: FastifyReply, next: NextFunction) {
|
use(req: FastifyRequest, rep: FastifyReply["raw"], next: () => void) {
|
||||||
// const { ip, method, baseUrl } = req;
|
const { ip, method, originalUrl } = req;
|
||||||
// const userAgent = req.get("user-agent") || "";
|
const userAgent = req.headers["user-agent"] || "";
|
||||||
// const startAt = process.hrtime();
|
const startAt = process.hrtime();
|
||||||
|
|
||||||
// res.on("finish", () => {
|
rep.on("finish", () => {
|
||||||
// const { statusCode } = res;
|
const { statusCode } = rep;
|
||||||
// const contentLength = res.get("content-length") || 0;
|
const contentLength = rep.getHeader("content-length") || 0;
|
||||||
// const dif = process.hrtime(startAt);
|
const dif = process.hrtime(startAt);
|
||||||
// const responseTime = dif[0] * 1e3 + dif[1] * 1e-6;
|
const responseTime = dif[0] * 1e3 + dif[1] * 1e-6;
|
||||||
// this.logger.log(`${method} - ${baseUrl} - ${statusCode} - ${contentLength} - ${userAgent} - ${ip} - ${responseTime.toFixed(2)}ms`);
|
this.logger.log(
|
||||||
// });
|
`${method} - ${originalUrl} - ${statusCode} - ${contentLength} - ${userAgent} - ${ip} - ${responseTime.toFixed(2)}ms`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
// next();
|
next();
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|||||||
@@ -5,12 +5,17 @@ import { FastifyAdapter, NestFastifyApplication } from "@nestjs/platform-fastify
|
|||||||
|
|
||||||
import { AppModule } from "./app.module";
|
import { AppModule } from "./app.module";
|
||||||
import { getSwaggerDocument } from "./configs/swagger.config";
|
import { getSwaggerDocument } from "./configs/swagger.config";
|
||||||
|
import { HttpExceptionFilter } from "./core/exceptions/http.exceptions";
|
||||||
|
import { PaginationInterceptor } from "./core/interceptors/pagination.interceptor";
|
||||||
|
import { ResponseInterceptor } from "./core/interceptors/response.interceptor";
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const logger = new Logger("APP");
|
const logger = new Logger("APP");
|
||||||
const app = await NestFactory.create<NestFastifyApplication>(AppModule, new FastifyAdapter());
|
const app = await NestFactory.create<NestFastifyApplication>(AppModule, new FastifyAdapter());
|
||||||
|
|
||||||
app.useGlobalPipes(new ValidationPipe({ transform: true, whitelist: true }));
|
app.useGlobalPipes(new ValidationPipe({ transform: true, whitelist: true }));
|
||||||
|
app.useGlobalInterceptors(new ResponseInterceptor(), new PaginationInterceptor());
|
||||||
|
app.useGlobalFilters(new HttpExceptionFilter());
|
||||||
|
|
||||||
app.enableCors({
|
app.enableCors({
|
||||||
origin: true,
|
origin: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user