Reputation: 13656
I want to add routing prefixes at the module level and/or have complex global routing prefix logic in general.
I know I can use the undocumented function NestApplication.setGlobalPrefix
to set a single global prefix:
// main.ts
app.setGlobalPrefix(version);
However, I want to set prefixes at the module level in this case.
It appears I could achieve this by setting my desired prefix into the decorators at the controller level:
//controler.ts
@Get('/PREFIX/health')
async getHealth() {
// TODO: implement
return {};
}
But this seems fairly hacky and error-prone. Surely there is a better way?
Upvotes: 14
Views: 32610
Reputation: 11
import { applyDecorators, Controller } from '@nestjs/common'
export function SystemController(path: string) {
return applyDecorators(Controller(`system/${path}`))
}
// system/action module example
import { BaseController } from 'src/shared/providers/base.controller'
import { ActionsService } from './actions.service'
import { Action } from './entities/action.entity'
import { SystemController } from 'src/shared/decorators'
@SystemController('actions')
export class ActionsController extends BaseController<Action> {
constructor(private readonly actionsService: ActionsService) {
super(actionsService)
}
}
Upvotes: 1
Reputation: 1031
You can now use either the RouterModule configuration or you can exclude some paths from the global prefix configuration (or mix both):
RouterModule: https://docs.nestjs.com/recipes/router-module#router-module
Global prefix "exclude": https://docs.nestjs.com/faq/global-prefix#global-prefix
Upvotes: 3
Reputation: 13656
NestJS now supports the original answer natively.
In addtion, NestJS v8 also adds more sophisticated routing when the primary function is versioning an API:
@Controller({
path: 'cats',
version: '1', // 👈
})
export class CatsController {
...
The most robust way to accomplish this in NestJS is to use the nest-router package to create a routing tree.
yarn add nest-router
# or npm i nest-router
Create a file next to main.ts
called routes.ts
like so:
import { Routes } from 'nest-router';
import { YourModule } from './your/your.module';
export const routes: Routes = [
{
path: '/v1',
module: YourModule,
},
];
Then, inside your app.module.ts
file, add the router before any other modules are loaded:
@Module({
imports: [
RouterModule.forRoutes(routes),
YourModule,
DebugModule
],
})
Now when you navigate to YourModule
controller, all of its routes will be prefixed with e.g. v1
in this case:
curl http://localhost:3000/v1/your/operation
Using this approach gives you the most flexibility as each module does not need to know how it will be prefixed; the application can decide at a higher level. Almost more advanced prefixes can be computed dynamic versus relying on a static string.
Upvotes: 19
Reputation: 359
For me, adding a third party package just to achieve this would be a bit unnecessary, let alone the risk of it being outdated/unmaintained. You can add your custom route prefix in the Controller
class instead.
@Controller('custom/prefix')
export const MyController {
@Get('health')
getHealth() {
//this route would be: custom/prefix/health
return {};
}
@Get('other')
getOther() {
//this route would be: custom/prefix/other
return {};
}
}
Then just simply add this controller inside your Module
Upvotes: 3