Skip to content

Middleware

Hàm middleware thực thi trước bộ xử lý route. Chúng có quyền truy cập vào đối tượng yêu cầu và phản hồi và có thể sửa đổi chúng.

Tạo Middleware

Middleware hàm

typescript
import { MiddlewareFunction } from '@galaxy-stack/orbit-core';

export const loggerMiddleware: MiddlewareFunction = async (request, next) => {
  console.log(`[${new Date().toISOString()}] ${request.method} ${request.url}`);
  return next();
};

Middleware class

typescript
import { Injectable, NestMiddleware } from '@galaxy-stack/orbit-core';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(request: Request, next: () => Promise<Response>): Promise<Response> {
    console.log(`Yêu cầu: ${request.method} ${request.url}`);
    return next();
  }
}

Áp dụng Middleware

Middleware toàn cục

typescript
const app = await BunFactory.create(AppModule);
app.use(loggerMiddleware);

Middleware dựa trên Module

typescript
import { Module, MiddlewareConsumer, NestModule } from '@galaxy-stack/orbit-core';

@Module({
  controllers: [UserController],
})
export class UserModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes(UserController);
  }
}

Middleware cho route cụ thể

typescript
@Module({})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(AuthMiddleware)
      .forRoutes(
        { path: 'users', method: RequestMethod.ALL },
        { path: 'posts', method: RequestMethod.POST }
      );
  }
}

Loại trừ Route

typescript
consumer
  .apply(AuthMiddleware)
  .exclude(
    { path: 'auth/login', method: RequestMethod.POST },
    { path: 'auth/register', method: RequestMethod.POST },
  )
  .forRoutes('*');

Middleware tích hợp

Middleware CORS

typescript
import { CorsMiddleware } from '@galaxy-stack/orbit-core';

app.use(new CorsMiddleware({
  origin: ['https://example.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,
}));

Middleware file tĩnh

typescript
import { StaticMiddleware } from '@galaxy-stack/orbit-core';

app.use(new StaticMiddleware({
  root: './public',
  prefix: '/static',
  maxAge: 86400,
  etag: true,
}));

Ví dụ Middleware phổ biến

Middleware xác thực

typescript
@Injectable()
export class AuthMiddleware implements NestMiddleware {
  constructor(private authService: AuthService) {}

  async use(request: Request, next: () => Promise<Response>): Promise<Response> {
    const token = request.headers.get('authorization')?.replace('Bearer ', '');

    if (token) {
      try {
        const user = await this.authService.validateToken(token);
        (request as any).user = user;
      } catch (error) {
        // Token không hợp lệ, tiếp tục mà không có user
      }
    }

    return next();
  }
}

Middleware ID yêu cầu

typescript
export const requestIdMiddleware: MiddlewareFunction = async (request, next) => {
  const requestId = request.headers.get('x-request-id') || crypto.randomUUID();
  
  const response = await next();
  
  response.headers.set('x-request-id', requestId);
  
  return response;
};

Middleware đo thời gian

typescript
export const timingMiddleware: MiddlewareFunction = async (request, next) => {
  const start = Date.now();
  
  const response = await next();
  
  const duration = Date.now() - start;
  response.headers.set('x-response-time', `${duration}ms`);
  
  return response;
};

Thứ tự Middleware

Middleware thực thi theo thứ tự chúng được áp dụng:

typescript
app.use(requestIdMiddleware);   // Thứ 1
app.use(timingMiddleware);       // Thứ 2
app.use(loggerMiddleware);       // Thứ 3

Middleware bất đồng bộ

Middleware có thể là bất đồng bộ:

typescript
export const asyncMiddleware: MiddlewareFunction = async (request, next) => {
  await someAsyncOperation();
  const response = await next();
  await anotherAsyncOperation();
  return response;
};

Released under the MIT License.