如何使用 NestJS 创建带参数的嵌套路由

Fra*_*rzi 23 javascript api node.js typescript nestjs

我需要构建一个 API,其中大多数路由都以一个通用 URL 部分为前缀,该部分也有一个参数。

在我的具体情况下,我的路线需要看起来像:

/accounts/:account/resource1/:someParam

/accounts/:account/resource2/:someParam/whatever

/accounts/:account/resource3/

/accounts/:account/resource4/subResource/

等等..

所以最好我会创造一个家长的路线/accounts/:account/,将包含儿童路由(resource1resource2resource3resource4,等...)。

我还需要:account可以从所有子路由访问该参数。

使用 NestJS 实现这一目标的最佳方法是什么?

A. *_*tre 11

关于您的用例,您可能想看看这个路由器模块
=> https://github.com/shekohex/nest-router

按照此模块的文档,您可以像这样定义路由:

... //imports
const routes: Routes = [
    {
      path: '/ninja',
      module: NinjaModule,
      children: [
        {
          path: '/cats',
          module: CatsModule,
        },
        {
          path: '/dogs',
          module: DogsModule,
        },
      ],
    },
  ];

@Module({
  imports: [
      RouterModule.forRoutes(routes), // setup the routes
      CatsModule,
      DogsModule,
      NinjaModule
      ], // as usual, nothing new
})
export class ApplicationModule {}
Run Code Online (Sandbox Code Playgroud)

当然,路由将在一个单独的文件中定义,如 routes.ts

鉴于您有一个逐模块的控制器,前面的代码将以以下路由树结尾:

ninja
    ??? /
    ??? /katana
    ??? cats
    ?   ??? /
    ?   ??? /ketty
    ??? dogs
        ??? /
        ??? /puppy
Run Code Online (Sandbox Code Playgroud)


示例
如果要到达ketty控制器的路由,则需要到达此端点:
<your-api-host>/ninja/cats/ketty

  • Nestjs 文档不推荐这种方式,因为维护起来太复杂了 https://docs.nestjs.com/recipes/router-module (4认同)

sma*_*ite 10

我想你需要这个?

import {Controller, Get, Param} from "@nestjs/common";

@Controller('accounts/:account')
export class TestController{

    @Get('resource2/:someParam/whatever')
    arsPW(@Param('account') account, @Param('someParam') someparam){
        console.log(':account/resource2/:someParam/whatever',account,someparam)
        return account+'_'+someparam+'___';
    }

    @Get('resource1/:someparam')
    aRSP(@Param('account') account, @Param('someparam') someparam){
        console.log(':account/resource1/:someParam',account,someparam)
        return account+'_'+someparam;
    }


    @Get()
    getget(){
        console.log('get');
        return 'aaa';
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 这是我目前正在使用的,但是如果我有很多儿童路线怎么办?我不想有一个单一的、胖的 Controller 类。理想情况下,我将能够在不同的 Controller 类中创建不同的子路由 (5认同)

Fad*_*del 8

父控制器:

@Controller('accounts')
export class AccountsController {
  // http://api.domaine.com/accounts
  @Get()
Run Code Online (Sandbox Code Playgroud)

子控制器:

@Controller('accounts/:id')
export class ResourcesController {
  // http://api.domaine.com/accounts/1/resources
  @Get('resources')
Run Code Online (Sandbox Code Playgroud)

  • 这是我正在使用的模式,它是我见过的最好的模式,但对于企业 API 来说它仍然不是很好。如果您想拥有“/resources/:id”,则需要定义另一个“ResourcesController”,也许将上面的重命名为“AccountsResourcesController”以留出“空间”。我希望有一种机制来注释类方法以忽略父控制器路由/覆盖它。如果有人发现这个并找到更好的方法,请告诉我! (3认同)

yeh*_*kel 5

你可以简单地这样做

@Controller('trainer/:trainerId/heroes')
 export class HeroesController {
    constructor(private readonly heroesService: HeroesService) {}

    @Get(':id')
    findOne(@Param('trainerId') trainerId:string,@Param('id') id: string) {
       return `This action returns a #${id} hero trainer id ${trainerId}`;
    }

 }
Run Code Online (Sandbox Code Playgroud)

URI 是:

http://localhost:3000/trainer/4/heroes/5
Run Code Online (Sandbox Code Playgroud)

结果是

This action returns a #5 hero trainer id 4
Run Code Online (Sandbox Code Playgroud)