You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Nest.js多租户应用中配置全局路径参数:tenantID?

NestJS 实现全局租户ID路由前缀方案

方法一:全局路由前缀统一配置

直接在应用启动时设置全局路由前缀为:tenantID,所有模块的路由会自动继承这个前缀,无需逐个模块修改。

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 设置全局路由前缀为租户ID参数
  app.setGlobalPrefix(':tenantID');
  await app.listen(3000);
}
bootstrap();

控制器只需定义自身模块的路由部分:

// users.controller.ts
import { Controller, Get, Param } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get()
  getUsers(@Param('tenantID') tenantID: string) {
    // 直接获取路径中的租户ID,后续可用于数据隔离查询
    return `租户 ${tenantID} 的用户列表`;
  }
}

此时访问路径为http://localhost:3000/your-tenant-id/users,完全符合需求。

方法二:模块级路由前缀配置(按需使用)

如果不需要全局统一前缀,可为每个模块单独配置带租户ID的路由前缀:

// users.controller.ts
import { Controller, Get, Param } from '@nestjs/common';

// 直接在控制器上指定带租户ID的完整前缀
@Controller(':tenantID/users')
export class UsersController {
  @Get()
  getUsers(@Param('tenantID') tenantID: string) {
    return `租户 ${tenantID} 的用户列表`;
  }
}

或者在模块导入时动态配置(需模块支持路由前缀注入):

// app.module.ts
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module';
import { ConversationsModule } from './conversations/conversations.module';

@Module({
  imports: [
    // 假设模块支持通过forRoot传入路由前缀
    UsersModule.forRoot({ routePrefix: ':tenantID/users' }),
    ConversationsModule.forRoot({ routePrefix: ':tenantID/conversations' }),
  ],
})
export class AppModule {}

方法三:全局中间件处理租户ID验证与传递

为确保租户ID合法性,可添加全局中间件统一处理:

// tenant.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class TenantMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    const tenantID = req.params.tenantID;
    // 验证租户ID是否合法(示例:非空检查)
    if (!tenantID) {
      return res.status(400).json({ message: '租户ID不能为空' });
    }
    // 将租户ID挂载到请求对象,供后续控制器/服务使用
    (req as any).tenantID = tenantID;
    next();
  }
}

在main.ts中注册全局中间件:

// main.ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.setGlobalPrefix(':tenantID');
  // 注册租户中间件
  app.use(TenantMiddleware);
  await app.listen(3000);
}
bootstrap();

后续在服务中可直接获取租户ID:

// users.service.ts
import { Injectable, Request } from '@nestjs/common';

@Injectable()
export class UsersService {
  getUsers(@Request() req: Request) {
    const tenantID = (req as any).tenantID;
    // 基于租户ID查询数据(单库多租户的核心:数据隔离)
    return this.userRepository.find({ where: { tenantID } });
  }
}

Swagger 文档适配

若使用Swagger,需添加全局参数说明:

// main.ts
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.setGlobalPrefix(':tenantID');
  
  const config = new DocumentBuilder()
    .setTitle('多租户API')
    .setDescription('单库单应用多租户REST API')
    .setVersion('1.0')
    .addParameter('tenantID', {
      in: 'path',
      required: true,
      description: '租户唯一标识',
      schema: { type: 'string' },
    })
    .build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api', app, document);
  
  await app.listen(3000);
}
bootstrap();

内容的提问来源于stack exchange,提问作者BratZdenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 02:03:17